This article provides a base template that will allow you to deploy a SharePoint 2019 farm using PowerShell Desired State Configuration (DSC). This article is meant to be an evolutive process, and will get updated to always reflect the latest version of the SharePointDSC module. It currently uses the v3.0-development branch that is currently in preview and which is the only branch that supports SharePoint 2019 at the moment. The public version of SharePointDSC that is available on the PowerShell Gallery does not offer support for SharePoint 2019. For more information about this SharePointDSC preview, please refer to my Introducing SharePointDSC Support for SharePoint 2019 article.
The script was originally written to target Azure Automation, but can easily be used for on-premises deployments. The only modifications required for on-premises support would be to change the Get-AutomationPSCredential calls to Get-Credential ones instead. This script currently assumes that you have a 3-servers environment: 1 Web Front-End, 1 Application server and 1 Search server. If you wish to deploy such an environment in your Azure subscription, I’d recommend you using the following ARM templates: SharePoint Blank Templates. Those are the ARM templates I always use when doing workshops, demos or conferences. They will take care of automatically create a domain controller, a SQL Server, and the 3 SharePoint servers, with nothing installed on them. The following users will be created at deployment time:
- U: lcladmin P: Pass@word!123
- U: sp_setup P: Pass@word!123
- U: sp_farm P: Pass@word!123
- U: sp_services P: Pass@word!123
- U: sp_search P: Pass@word!123
- U: sharepointadmin P: Pass@word!123
The DSC script will take care of downloading all prerequisites locally, install the French and Dutch language packs, create a Web Application with its site collection, and create services applications, all by leveraging the power of PowerShell Desired State Configuration
The Script
configuration Starter3Servers { $credsLocalAdmin = Get-AutomationPSCredential -Name "LocalAdmin" $credsDomainAdmin = Get-AutomationPSCredential -Name "DomainAdmin" $credsSPFarm = Get-AutomationPSCredential -Name "FarmAccount" $credsSPSetup = Get-AutomationPSCredential -Name "SetupAccount" $credsSPServices = Get-AutomationPSCredential -Name "SPServices" $credsSPSearch = Get-AutomationPSCredential -Name "SPSearch" $credsSPAdmin = Get-AutomationPSCredential -Name "SharePointAdmin" Import-DscResource -ModuleName "SharePointDSC" -Moduleversion "3.0.0.0" Import-DscResource -ModuleName "xDownloadFile" -ModuleVersion "1.0" Import-DscResource -ModuleName "xDownloadISO" -ModuleVersion "1.0" Import-DscResource -ModuleName "xPendingReboot" -ModuleVersion "0.4.0.0" Node $AllNodes.NodeName { xDownloadISO DownloadBits { SourcePath = "https://download.microsoft.com/download/8/1/4/8144DA0D-FB9A-48B8-B56E-2C12E0C30079/en-us/16.0.10711.37301_OfficeServer_none_ship_x64_en-us_dvd/officeserver_en-us.img" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath PsDscRunAsCredential = $credsLocalAdmin } xDownloadISO FrenchLPISO { SourcePath = "https://spdsctap.blob.core.windows.net/spdsc/LP-French.iso" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "LP\French\" PsDscRunAsCredential = $credsLocalAdmin } xDownloadISO DutchLPISO { SourcePath = "https://spdsctap.blob.core.windows.net/spdsc/LP-Deutch.iso" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "LP\Dutch" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile AppFabricKBDL { SourcePath = "https://download.microsoft.com/download/F/1/0/F1093AF6-E797-4CA8-A9F6-FC50024B385C/AppFabric-KB3092423-x64-ENU.exe" FileName = "AppFabric-KB3092423-x64-ENU.exe" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" PsDscRunAsCredential = $credsLocalAdmin DependsOn = "[xDownloadISO]DownloadBits" } xDownloadFile MicrosoftIdentityExtensionsDL { SourcePath = "http://download.microsoft.com/download/0/1/D/01D06854-CA0C-46F1-ADBA-EBF86010DCC6/rtm/MicrosoftIdentityExtensions-64.msi" FileName = "MicrosoftIdentityExtensions-64.msi" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]AppFabricKBDL" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile MSIPCDL { SourcePath = "https://download.microsoft.com/download/3/C/F/3CF781F5-7D29-4035-9265-C34FF2369FA2/setup_msipc_x64.exe" FileName = "setup_msipc_x64.msi" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]MicrosoftIdentityExtensionsDL" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile SQLNCLIDL { SourcePath = "https://download.microsoft.com/download/B/E/D/BED73AAC-3C8A-43F5-AF4F-EB4FEA6C8F3A/ENU/x64/sqlncli.msi" FileName = "sqlncli.msi" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]MSIPCDL" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile WcfDataServices56DL { SourcePath = "http://download.microsoft.com/download/1/C/A/1CAA41C7-88B9-42D6-9E11-3C655656DAB1/WcfDataServices.exe" FileName = "WcfDataServices56.exe" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]SQLNCLIDL" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile AppFabricDL { SourcePath = "http://download.microsoft.com/download/A/6/7/A678AB47-496B-4907-B3D4-0A2D280A13C0/WindowsServerAppFabricSetup_x64.exe" FileName = "WindowsServerAppFabricSetup_x64.exe" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]WcfDataServices56DL" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile DotNet472 { SourcePath = "https://go.microsoft.com/fwlink/?linkid=863265" FileName = "NDP472-KB4054530-x86-x64-AllOS-ENU.exe" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]AppFabricDL" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile SynchronizationDL { SourcePath = "http://download.microsoft.com/download/E/0/0/E0060D8F-2354-4871-9596-DC78538799CC/Synchronization.msi" FileName = "Synchronization.msi" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]DotNet472" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile MSVCRT141 { SourcePath = "https://aka.ms/vs/15/release/vc_redist.x64.exe" FileName = "vc_redist.x64.exe" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]SynchronizationDL" PsDscRunAsCredential = $credsLocalAdmin } xDownloadFile MSVCRT11 { SourcePath = "https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe" FileName = "vcredist_x64.exe" DestinationDirectoryPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles" DependsOn = "[xDownloadFile]MSVCRT141" PsDscRunAsCredential = $credsLocalAdmin } Group GrantSetupAccountLocalAdmin { GroupName = "Administrators" Ensure = "Present" MembersToInclude = $credsSPSetup.UserName PsDscRunAsCredential = $credsLocalAdmin DependsOn = "[xDownloadFile]MSVCRT11" } SPInstallPrereqs SharePointPrereqInstall { IsSingleInstance = "Yes" InstallerPath = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstaller.exe" OnlineMode = $false SQLNCli = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\sqlncli.msi" Sync = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\Synchronization.msi" AppFabric = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\WindowsServerAppFabricSetup_x64.exe" IDFX11 = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\MicrosoftIdentityExtensions-64.msi" MSIPCClient = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\setup_msipc_x64.msi" WCFDataServices56 = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\WcfDataServices56.exe" MSVCRT11 = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\vcredist_x64.exe" MSVCRT141 = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\vc_redist.x64.exe" KB3092423 = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\AppFabric-KB3092423-x64-ENU.exe" DotNet472 = $ConfigurationData.SharePoint.Settings.BinaryPath + "prerequisiteinstallerfiles\NDP472-KB4054530-x86-x64-AllOS-ENU.exe" Ensure = "Present" DependsOn = "[Group]GrantSetupAccountLocalAdmin" # For On-prem - SXSPath = "D:\sources\sxs" PsDscRunAsCredential = $credsSPSetup } xPendingReboot AfterPrereqInstall { Name = "AfterPrereqInstall" DependsOn = "[SPInstallPrereqs]SharePointPrereqInstall" PsDscRunAsCredential = $credsDomainAdmin } SPInstall SharePointInstall { IsSingleInstance = "Yes" BinaryDir = $ConfigurationData.SharePoint.Settings.BinaryPath ProductKey = $ConfigurationData.SharePoint.Settings.ProductKey Ensure = "Present" DependsOn = "[xPendingReboot]AfterPrereqInstall" PsDscRunAsCredential = $credsSPSetup } SPInstallLanguagePack DutchLanguagePack { BinaryDir = $ConfigurationData.SharePoint.Settings.BinaryPath + "LP\Dutch" DependsOn = "[SPInstall]SharePointInstall" PsDscRunAsCredential = $credsSPSetup } SPInstallLanguagePack FrenchLanguagePack { BinaryDir = $ConfigurationData.SharePoint.Settings.BinaryPath + "LP\French" DependsOn = "[SPInstall]SharePointInstall" PsDscRunAsCredential = $credsSPSetup } xPendingReboot AfterSPInstall { Name = "AfterSPInstall" DependsOn = "[SPInstall]SharePointInstall" PsDscRunAsCredential = $credsDomainAdmin } SPFarm SharePointFarm { IsSingleInstance = "Yes" Ensure = "Present" FarmConfigDatabaseName = "SP_Config" DatabaseServer = $ConfigurationData.SharePoint.Settings.DatabaseServer FarmAccount = $credsSPFarm Passphrase = $credsSPFarm AdminContentDatabaseName = "SP_Admin" RunCentralAdmin = $Node.RunCentralAdmin CentralAdministrationPort = "7777" ServerRole = $Node.ServerRole PSDSCRunAsCredential = $credsSPSetup DependsOn = "[SPInstall]SharePointInstall" } if ($node.RunCentralAdmin -eq $true) { SPManagedAccount SPFarmAccount { AccountName = $credsSPFarm.UserName Account = $credsSPFarm PSDSCRunAsCredential = $credsSPSetup DependsOn = "[SPFarm]SharePointFarm" } SPManagedAccount SPServices { AccountName = $credsSPServices.UserName Account = $credsSPServices PSDSCRunAsCredential = $credsSPSetup DependsOn = "[SPFarm]SharePointFarm" } SPManagedAccount SPSearch { AccountName = $credsSPSearch.UserName Account = $credsSPSearch PSDSCRunAsCredential = $credsSPSetup DependsOn = "[SPFarm]SharePointFarm" } SPManagedAccount SPAdmin { AccountName = $credsSPAdmin.UserName Account = $credsSPAdmin PSDSCRunAsCredential = $credsSPSetup DependsOn = "[SPFarm]SharePointFarm" } SPWebApplication Root { Ensure = "Present" Name = "Root" ApplicationPool = "SharePoint - 80" ApplicationPoolAccount = $credsSPFarm.UserName WebAppUrl = "http://root.contoso.com" DatabaseServer = $ConfigurationData.SharePoint.Settings.DatabaseServer DatabaseName = "Root_Content_DB" HostHeader = "root.contoso.com" AllowAnonymous = $false PSDSCRunAsCredential = $credsSPSetup DependsOn = "[SPManagedAccount]SPFarmAccount" } SPSite RootSite { Name = "Root Site Collection" Url = "http://root.contoso.com" OwnerAlias = "contoso\lcladmin" ContentDatabase = "Root_Content_DB" Description = "Root Site Collection" Template = "STS#0" PSDSCRunAsCredential = $credsSPSetup DependsOn = "[SPWebApplication]Root" } SPWeb SubWeb1 { Name = "Subweb1" Url = "http://root.contoso.com/subweb1" AddToQuickLaunch = $true AddToTopNav = $true Description = "This is a subsite" UseParentTopNav = $true UniquePermissions = $true Template = "STS#0" PSDSCRunAsCredential = $credsSPSetup DependsOn = "[SPSite]RootSite" } } } }
The Configuration Data
$ConfigData = @{ AllNodes = @( @{ NodeName = "SPWFE.contoso.com" RunCentralAdmin = $false ServerRole = "WebFrontEnd" }, @{ NodeName = "SPApp.contoso.com" RunCentralAdmin = $true ServerRole = "Application" }, @{ NodeName = "SPSearch.contoso.com" RunCentralAdmin = $false ServerRole = "Search" }, @{ NodeName = "*" PSDSCAllowPlainTextPassword = $true PSDSCAllowDomainUser = $true } ) SharePoint = @{ Settings = @{ DatabaseServer = "SPSQL" BinaryPath = "C:\SP2019\" ProductKey = "M692G-8N2JP-GG8B2-2W2P7-YY7J6" } } }
Any way to use PowerShell to get the latest SharePointDsc? Currently published is only 2.4.0.0 and I can’t find a method to install the package. I could manually download from Github of course, but is there a better method to get the 3.0.0.0?
We are looking at options to provide beta version through the PowerShell Gallery now that this is available. We will keep you posted.
In the SPFarm SharePointFarm configuration, I think it should be: ServerRole = $node.ServerRole
There is also no DependsOn in the SPFarm section, do I need it, or does it detect automatically that it can only create the farm after SharePoint binaries are installed?
Hans, you are absolutely right regarding the SPFarm section. The article has been updated accordingly. As for the DependsOn clause for SPFarm, you could add it if you wished. If the Binaries are not able to install, then SPFarm would indeed throw an error with the current script. Because of the items order in the config script, SPInstall will always be executed before SPFarm, so the Depends Clause would simply help in reducing the overall number of errors in case it fails. Best practice wants you to have proper dependencies defined, so again here it was a miss in my original script. Thanks for pointing it out.