SharePoint DSC Gotchas and Best Practices

In the Microsoft Virtual Academy on SharePoint Automation with DSC my colleague Brian Farnhill and I recorded in June of 2017, we dedicated an entire module to SharePointDSC best practices. I thought I’d take a few minutes to put the items we discussed during that session on paper. This article will act as a list of the most frequent issues and problem encountered by people using SharePoint DSC. It will be updated as the tool evolves.

Frequent Issues

Installation of Prerequisites, Binaries or Language Pack is Stuck

Symptom:

This is one of the most frequent issue people encountered when starting off with SharePoint DSC. When running the configuration using Start-DSCConfiguration, or when in Pull mode, the installation seems to get stuck when trying to install components (prerequisites, binaries, or language pack). No errors are being thrown.

Most Likely Reason:

There is some level of User Account Control set on the installation file. In most cases this issues will happen when the installation is done from a Network Drive. Upon executing the installation of the component, windows triggers a prompt for the user to confirm the execution of an executable that was launched from an untrusted location, but because this was initiates from a background thread, it is impossible to ever approve that prompt and the installation gets stuck.

In order to test if this is your issue, launch a new PowerShell session, running as the user defined in the PsDscRunAsCredential parameter of the execution block. From there, run the following line of PowerShell. If there are any prompts that appear, that means that the installation is most likely stuck because of the User Account Control.

Start-Process -FilePath <Path to the Installer file> -Wait -PassThru

Solution:

The solution here is two fold. First off, we recommend you turn off the User Account Control feature for the user running the PsDscRunAsCredential installation block in your script. As a second step, launch Internet Explorer and go to Internet Explorer Settings. From there, go to the Security tab, click on the Local Intranet Zone, then click on the Sites button. In the prompt, click on the Advanced button, this will open the window that let’s you specify addresses to identify as being part of the Local Intranet Zone. In that window, type in the location of the Network share (or other common location) where the installer file is located, and click on Add.

Using a completely DSC based solution, you could use the xSystemSecurity module to disable the User Account Control prompt as follow:

# Make sure you import the module
Import-DSCResource -ModuleName "MSFT_xSystemSecurity"

# Put this in the node's configuration;
xUAC NeverNotifyAndDisableAll
{
    Setting = "NeverNotifyAndDisableAll"
}

Best Practices

Master Node

SharePoint is a distributed system, meaning that not all components run on the same server, and that most of the content and configuration is actually stored in a SQL Server database, that all servers in the farm can access at any time. When you define a DSC configuration file, you should identify one of the servers in your farm to be what I refer to has your Master Node. this is the node on which you will define most of the components in the Farm. All other nodes, referred to as secondary nodes in this scenario, should only define resources that allow them to install the required binaries and updates, to join the farm, and the service instances to run on that server. All other components should ONLY be defined on the Master Node.For example, don’t go and define an SPSite entry on multiple node, it is not necessary. SPSite objects are defined in the Content Databases anyway, so you don’t need every server in the farm to attempt to create them.

Take another example where you wish to update the DSC definition of a certain feature on a Site Collection to be disabled instead of enabled. If you properly defined your configuration, you only have to update the DSC definition for that feature within a single node (Master Node) in the DSC configuration file, but let’s imagine you have it defined within every node instead. You now have to go and modify it multiple times within your configuration, and that opens the door to mistakes. Let’s say our farm has 3 servers, that you updated the feature’s definition for Server #1 and #2, but forgot to update the definition in server #3. To make things worst, you’ve set all 3 servers’ Local Configuration Manager (LCM) to be set to ApplyAndAutocorrect. We all know that by default, the ConfigurationMode for the LCM will check every 15 minutes to make sure it is in its desired state, but that 15 minutes may not happen exactly at the same time on each of the servers in the farm. Imagine that at 10h a.m., server one has its LCM kick in, and realize that the feature has to be turned on based on the new definition. It will go and disable the feature. Now, let’s pretend that server #3’s LCM kicks in at 10h05 a.m., but since that server doesn’t have the proper definition, it re-disables the feature that was just turned on 5 minutes ago by Server #1. You can see where this is going, and that can cause a lot of headaches for your admin team. DO NOT DECLARE components (other than SPFarm, SPIntall, SPInstallPrereqs, and SPServiceInstance) on more than one server in the configuration.

Use ApplyAndAutocorrect with Caution

We took a decision a few years back not to let SharePointDSC deal with content such as SPList, SPContentTypes, etc. However, we do deal with items such as SPSite and SPWeb that are stored in the Content Database. The real beauty behind SharePoint is that it lets users deal with their content as they see fit. Users can easily go and create a new list, play with it for a few days, and then decide to delete it after because their tests are done.

PowerShell Desired State Configuration is very powerful. When you set the Local Configuration Manager of a server to ApplyAndAutocorrect, the server will automatically attempt to bring itself back into its defined Desired State Configuration whenever it detects that it drifted away from that configuration. While this feature is very powerful, my recommendation is not to set the LCM in ApplyAndAutocorrect the moment your configuration includes either and SPWeb or SPSite resource declaration, unless you are absolutely certain and aware of what this will do to your environment.

Imagine the following scenario where you have an environment which declares 3 SPWeb (say Web1, Web2, and Web3), and for which the LCM is set to ApplyAndAutocorrect. Come spring, the Information Management (IM) team at your organization undertakes a major cleanup project where they want to get rid of sites that have not been active in the past 6 months. There 3 SPWeb sites defined in the configuration, have been identified by the IM team to be deleted. The IM manager goes in and deletes the 3 sites, then sends an email to the IM director to let him know that the cleanup has been done. Two weeks after the IM director stumbles upon SPWeb2, which the IM Manager claimed to have deleted 14 days ago. Well, the moment the site was originally deleted by the IM Manager, 15 minutes after, the LCM detected that it was no longer in its desired state, and since its LCM is set to ApplyAndAutocorrect, it automatically recreated the site. Imagine the confusion this can cause.

this article will be updated on an on-going basis.

Reverse Engineer an Existing SharePoint Farm using PowerShell DSC

PowerShell Desired State Configuration (DSC) is a technology that allows you to define a configuration for an environment, and ensure it automatically gets configured tat way. It can also help you monitor the delta between the current state of the environment and what the defined configuration (a.k.a. Desired State) is. So as an example in the case of SharePoint, if you were to specify that you needed to register a Managed Account for user sp_services, and that someone was to delete that account, PowerShell DSC would automatically report the discrepancy in the logs or attempt to automatically recreated it based on how you configured your environment (Configuration Mode).

The SharePoint module for DSC is great to build new environments from the ground up. Simply specify what the Desired State should be (Web Applications, Site Collections, Service Applications, etc.) and let DSC do its job and automatically configure it. It acts as some kind of abstraction layer for the user, where they only need to define resources and their various settings for DSC to create and configure everything for them in the background. They don’t need to know the cmdlets to use, know what the objects’ properties are, and even less understand the object model behind it all. They only need to know what the DSC resource accepts.

Existing Environments

In many cases however, clients who want to get into DSC already have investments in SharePoint, where they have an existing SharePoint 2013 or 2016 farm that they would like to replicate somewhere else with DSC. Writing a DSC configuration script from scratch that represents their exact environment is a complex job and often results in the customer writing tens of thousands of lines of code. This is where the ReverseDSC orchestrator for SharePoint, called SharePointDSC.Reverse comes into play. SharePointDSC.Reverse is a PowerShell script (.ps1) that you execute against an existing SharePoint 2013 or 2016 farm to extract its PowerShell Desired State Configuration. The script will scan every component of the farm, down to the SPWeb level. This means that everything that can be defined in Central Administration, with the addition of Sites can be extracted with the SharePointDSC.Reverse. The output will be another .ps1 script that will contain the DSC configuration of your farm. That script can then be executed to compile a .MOF file that can be used to replicate your SharePoint environment elsewhere.

Other Scenarios

The ReverseDSC Orchestrator for SharePoint can also be used for several scenarios other than replicating a farm. It can be used to:

  • Extract a SharePoint 2013 Farm Configuration and replicate it as a SharePoint 2016 one;
  • Compare deltas between two extractions to see what changed between two point in time;
  • Create standalone copies of a Farm for developers;
  • Move an on-premises SharePoint Farm into Azure Infrastructure-as-a-Service;
  • On-board an existing farm onto PowerShell DSC to monitor it and ensure it remains in its desired state.

How to Use

The ReverseDSC Orchestrator for SharePoint is now officially available in the PowerShell Gallery. It can be installed, alongside all of its dependencies, by executing the following PowerShell one-liner from a machine that has internet connectivity:

Install-Script SharePointDSC.Reverse -Force 

Note that this has to be done on only one server in the farm; you don’t need to install it on all servers. If your SharePoint server doesn’t have internet connectivity, simply run the above line of PowerShell from a machine that does have internet connectivity, and manually copy the ReverseDSC, SharePointDSC from the PowerShell modules folder (C:\Program Files\WindowsPowerShell\Modules), and the SharePointDSC.Reverse.ps1 script from the PowerShell script folder (C:\Program Files\WindowsPowerShell\Scripts) onto the destination server.

Additional Resources

To learn more about the ReverseDSC Orchestrator for SharePoint, you can watch my Microsoft Virtual Academy session on the topic at the following URL: https://mva.microsoft.com/en-US/training-courses/sharepoint-automation-with-dsc-17843

PowerShell DSC at a Glance – Frequently asked Questions (FAQ)

PowerShell Desired State Configuration (DSC) is a great way to automate the deployment of any type of environments. The DSC engine has matured a lot over the past 2 years, and is now ready for prime time within the enterprises. However, I feel like this is still a component of PowerShell that is too little known in the industry. Be it because people have not yet heard of it (it was only introduced in WMF4 after all), or because people get scare by its apparent complexity, PowerShell DSC does not yet have the exposure it should. This article aims at answering the most frequent questions I get about PowerShell DSC when I try to introduce its concepts to some of my clients. The answer to the questions are mine, and I am trying to vulgarize the concepts as much as possible.

What is PowerShell DSC?

PowerShell Desired State Configuration (DSC) is an engine within PowerShell version 4 and greater that allows a user to specify an end result configuration (a Desired State) for a machine to be in, and have it automatically configure itself to match that end result configuration.

How does it work?

The Windows Management Framework (WMF) 4 and greater include a service component called the Local Configuration Manager (LCM) that is responsible to orchestrate the configuration of the machine into its Desired State. Via PowerShell, users will create what I refer to as a DSC Configuration Script (which you shouldthink of as a definition/description of what the Desired State should be), and pass it onto the LCM for it to start automating thr configuration.

Why not use a simple PowerShell script to automate the configuration?

Fair question indeed. In the past, we could simply create a .ps1 PowerShell script and execute it manually on a bunch of machines to automate their configuration in a end result state. However, what if that end result state was to change and be modified by somebody on the machine? How can we ensure the machine is always kept in the end result state then? PowerShell DSC tries to solve this by introducing the concept of Configuration Modes. The LCM can automatically detect whenever a machine has steered away from its Desired State and take action.

What type of action can the Local Configuration Manager (LCM) take if a machine steered away from its Desired State

There are 3 types of action the LCM can take if it ever detects that the machine steered away from its Desired State:

  • ApplyOnly: which tells the LCM to simply apply the desired configuration once, and then to do nothing even if the machine steers away from its Desired State.
  • ApplyAndMonitor: which tells the LCM to apply the desired configuration once, and then if the machinesteers away from the desired state, to simply reports discrepancies in the logs. We could then use a tool like System Center to send notifications to the IT team when a server node is no longer in the desired state, allowing them to go an contact the users who changed the Desired State to learn more about why a specific change was made.
  • ApplyAndAutocorrect: which tells the LCM to apply the esired configuration, and whenever it detects that the machine is no longer in a Desired State to automatically fix it so that it becomes compliant with the desired state. Using this mode, the LCM will still report all discrepancies in the logs.

To what frequency is the LCM checking for changes to the Desired State?

By default the LCM will check every 15 minutes to see if the machine steered away from its Desired Configuration, but this can be changed as part of your DSC Configuration Script (definition of the Desired State).

What is a Pull Server?

A pull server is a central repository for all of your DSC Configuration Scripts. When configured in DSC Pull mode, the LCM will ping the Pull Server on a regular basis to check if it Desired State has changed or not.

How can I install a PowerShell DSC Module?

Go to the PowerShell Gallery PowerShellGallery.com which is supported by Microsoft. The easiest way from there is to ensure your have the PowerShell Get features availble (included in WMF 5). There are instructions on the site on how to proceed from there.

What is a DSC Module?

Think of a PowerShell DSC resource as a software component that can be configured via PowerShell DSC. For example, if you are to build a new Domain Controller using DSC, once of the component you will need to configure is Active Directory. Well, there is a unique DSC Module for AD that allows you to configure things like Users, OU, etc. There are even DSC Modules for Firefox and Chrome, assuming you need to install and configure specific browsers on your machine using DSC. DSC Modules are made up of resources, that each take care of a specific component within the software piece being configured by the module.

Alright, this is normally the point where I’ve lost all of you, so let me try to summarize this further. If we take the Active Directory (AD) example, there is an AD DSC Module. The component of the AD DSC Module that allows us to create new users is a module called ADUser. This resource contains all the logic required to interact with a User object (CRUD).

How are Resources working internally?

Every resource needs to have at least 3 methods: Get-TargetResource, Set-TargetResource, and Test-TargetResource. There is nothing preventing a resource from having more than these 3 methods, but these need to exist for a resource to be valid.

Get-TargetResource: This method retrieves the current state of the machine. Let me vulgarize the process here a bit. The method performs a scan of the current environment and stores values in a variable (let’s assume it stores it in an XML format). So in our Active Directory example, it will scan all users in AD and will return the current list of users as XML. This method does nothing more than scanning the current environment and returning it CURRENT state.

Test-TargetResource: This method is being called by the LCM everytime it checks to see if the machine steered away from its Desired State. The LCM already knows how the machine should be configured (its Desired State), but it needs to compare it against the Current State to see if they match. To get the Current State, the Test-TargetResource method simply makes a call to the Get-TargetResource method. If the Current State and the Desired State match, then the machine is all configured properly, but if they don’t then that means the machine steered away from its Desired Configuration. The Test-TargetResource method simply returns True or False to the LCM. If the method returns a False, meaning the machine is no longer in its Desired State, then the LCM will need to take one of the 3 actions mentionned above (ApplyOnly, ApplyAndMonitor, or ApplyAndAutocorrect). In the case where the LCM is configured to ApplyAndAutocorrect, LCM will call into the Set-TargetResource method to bring the machine back in its Desired State.

Set-TargetResource: This method is responsible for bringing the machine to its Desired State Configuration based on the DSC Configuration Script (definition of what the Desired State is). When called, this method doesn’t care at all about the Current State. All it wants to do is to bring the environment back to its Desired State. In our Active Directory example, assume the Desired State mentions that a user named “John Smith” has to exist and be part of the Domain Admins group, if someone by mistakes deletes that user, when called this method will automatically recreate the user so that the environment is back to its Desired State.

dsc-resource

Installing SharePoint 2016 with PowerShell Desired State Configuration (DSC)

This article is deprecated. New information on how to use PowerShell DSC to install SharePoint 2016 is available Here.

This article is a step by step guide of how to configure a new SharePoint 2016 Single Server farm instance using PowerShell Desired State Configuration (DSC). The example covered in this tutorial is using an Azure Virtual Machine running the Windows Server 2012 R2 image.

Technical Specifications

  • Windows Server 2012 R2(x64)
  • Domain is contoso.com
  • D11 Azure VM (2 cores, 14GB of RAM)
  • SQL Server 2016 CTP 3

Prerequisites

1 – Download and configure the xSharePoint DSC Resource

The first thing you will need to do is go download and configure the xSharePoint DSC resource. While the official bits are officially hosted on the PowerShell Gallery (PowerShellGallery.org), the SharePoint 2016 bits are still only available on the Github repository at the time of writing this article.

1.1) Navigate to the Github Repository http://github.com/PowerShell/SharePointDSC

1.2) On the right hand side, click on the “Download ZIP” button

Download

1.3) Extract the xSharePoint folder (located in Zip at xSharePoint-dev > Modules) to C:\Program Files\WindowsPowerShell\Modules\

Extract

2 – Install PowerShell 5

In order to leverage the PowerShell Get features from the following sections, you will require that the Windows Management Framework 5.0 be installed on your server.

2.1) Download the WMF 5.0 package (February 2015 Preview) from Microsoft’s Download Center from here

2.2) Install the Windows Management Framework 5.0 on your server.

2.3) Reboot your server.

3 – Download the xDisk DSC resource

Because this resource is actually located in the PowerShell Gallery we can user OneGet to automatically download and configure the resource.

3.1) In a PowerShell console, execute the following line of code. When prompted to add the package provider and to install from an untrusted location, enter ‘Y’ on both occasions.

Install-Module -Name xDisk

Installxdisk

4 – Download the xCredSSP DSC Resource

Just like the xDisk resource, the xCredSSP resource is also available from the PowerShell Gallery.

4.1) To download and configure it automatically, run the following line of PowerShell. Again, when prompted to install from an untrusted repository, enter ‘y’.

Install-Module -Name xCredSSP

InstallxCredssp

5 – Download the xWebAdministration DSC Resource

The story repats itself once more. In order to properly configure your environment, you will also require the xWebAdministration DSC resource to be downloaded and configured.

5.1) To download and configure it automatically, simply run the following line of PowerShell. When prompted to install from an untrusted repository, enter ‘y’.

Install-Module -Name xWebAdministration

6 – SQL Server 2016 CTP 3

I am cheating a bit in this tutorial. Normally you would want to connect your SharePoint farm to a separate SQL server, but in my case to keep things simple, I will be running both the SharePoint 2016 and SQL Server 2016 bits on the same server. Therefore I will manually go and configure a new default instance of SQL Server 2016 using an account called contoso\sqlinstall

7 – Extract the SharePoint Binaries

7.1) Download the SharePoint 2016 Beta 2 https://www.microsoft.com/en-us/download/details.aspx?id=49961

7.2) Mount the SharePoint 2016 iso onto a drive, in my case F:\

8 – Unblock the DSC Resource Files

Very often, PowerShell modules downloaded from the internet will be blocked, meaning that the Server operating system will prevent their execution. In order to allow the DSC engine to properly configure our environment, we need to make sure all resource files are properly unlocked.

8.1) Run the following line of PowerShell:

Get-ChildItem -Path "C:\Program Files\WindowsPowershell\Modules\xSharePoint" -Recurse | Unblock-File

9 – Configure the WinRM

To allow DSC to properly execute remote commands (even though it will execute it locally under different credentials), we need to configure the WinRM protocol on our server.

9.1) Execute the following line of PowerShell as an administrator:

WinRM QuickConfig

10 – Write your Desired State Configuration (DSC) Script

10.1) Create the DSC Configuration Script. Copy the following lines of PowerShell code and save them in a file at C:\Scripts\SharePoint2016Config.ps1

Configuration SharePointServer
{
param (
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $CredSSPDelegates,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $SPBinaryPath,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $ULSViewerPath,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $SPBinaryPathCredential,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $FarmAccount,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $InstallAccount,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $ProductKey,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $DatabaseServer,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $FarmPassPhrase,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $WebPoolManagedAccount,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $ServicePoolManagedAccount,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $WebAppUrl,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $TeamSiteUrl,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $MySiteHostUrl,
[Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [int] $CacheSizeInMB
)
Import-DscResource -ModuleName xSharePoint
Import-DscResource -ModuleName xWebAdministration
Import-DscResource -ModuleName xCredSSP
Import-DscResource -ModuleName xDisk
node "localhost"
{
#**********************************************************
# Server configuration
#
# This section of the configuration includes details of the
# server level configuration, such as disks, registry
# settings etc.
#**********************************************************
xCredSSP CredSSPServer { Ensure = "Present"; Role = "Server" }
xCredSSP CredSSPClient { Ensure = "Present"; Role = "Client"; DelegateComputers = $CredSSPDelegates }
#**********************************************************
# Software downloads
#
# This section details where any binary downloads should
# be downloaded from and put locally on the server before
# installation takes place
#**********************************************************
File SPBinaryDownload
{
DestinationPath = "C:\SPInstall"
Credential = $SPBinaryPathCredential
Ensure = "Present"
SourcePath = $SPBinaryPath
Type = "Directory"
Recurse = $true
}
#**********************************************************
# Binary installation
#
# This section triggers installation of both SharePoint
# as well as the prerequisites required
#**********************************************************
xSPInstallPrereqs InstallPrerequisites
{
InstallerPath = "C:\SPInstall\Prerequisiteinstaller.exe"
OnlineMode = $true
SQLNCli = "C:\SPInstall\prerequisiteinstallerfiles\sqlncli.msi"
PowerShell = "C:\SPInstall\prerequisiteinstallerfiles\Windows6.1-KB2506143-x64.msu"
NETFX = "C:\SPInstall\prerequisiteinstallerfiles\dotNetFx45_Full_setup.exe"
IDFX = "C:\SPInstall\prerequisiteinstallerfiles\Windows6.1-KB974405-x64.msu"
Sync = "C:\SPInstall\prerequisiteinstallerfiles\Synchronization.msi"
AppFabric = "C:\SPInstall\prerequisiteinstallerfiles\WindowsServerAppFabricSetup_x64.exe"
IDFX11 = "C:\SPInstall\prerequisiteinstallerfiles\MicrosoftIdentityExtensions-64.msi"
MSIPCClient = "C:\SPInstall\prerequisiteinstallerfiles\setup_msipc_x64.msi"
WCFDataServices = "C:\SPInstall\prerequisiteinstallerfiles\WcfDataServices.exe"
KB2671763 = "C:\SPInstall\prerequisiteinstallerfiles\AppFabric1.1-RTM-KB2671763-x64-ENU.exe"
WCFDataServices56 = "C:\SPInstall\prerequisiteinstallerfiles\WcfDataServices56.exe"
Ensure = "Present"
}
xSPInstall InstallBinaries
{
BinaryDir = "C:\SPInstall"
ProductKey = $ProductKey
Ensure = "Present"
DependsOn = "[xSPInstallPrereqs]InstallPrerequisites"
}
#**********************************************************
# IIS clean up
#
# This section removes all default sites and application
# pools from IIS as they are not required
#**********************************************************
xWebAppPool RemoveDotNet2Pool { Name = ".NET v2.0"; Ensure = "Absent"; DependsOn = "[xSPInstallPrereqs]InstallPrerequisites" }
xWebAppPool RemoveDotNet2ClassicPool { Name = ".NET v2.0 Classic"; Ensure = "Absent"; DependsOn = "[xSPInstallPrereqs]InstallPrerequisites" }
xWebAppPool RemoveDotNet45Pool { Name = ".NET v4.5"; Ensure = "Absent"; DependsOn = "[xSPInstallPrereqs]InstallPrerequisites"; }
xWebAppPool RemoveDotNet45ClassicPool { Name = ".NET v4.5 Classic"; Ensure = "Absent"; DependsOn = "[xSPInstallPrereqs]InstallPrerequisites"; }
xWebAppPool RemoveClassicDotNetPool { Name = "Classic .NET AppPool"; Ensure = "Absent"; DependsOn = "[xSPInstallPrereqs]InstallPrerequisites" }
xWebAppPool RemoveDefaultAppPool { Name = "DefaultAppPool"; Ensure = "Absent"; DependsOn = "[xSPInstallPrereqs]InstallPrerequisites" }
xWebSite RemoveDefaultWebSite { Name = "Default Web Site"; Ensure = "Absent"; PhysicalPath = "C:\inetpub\wwwroot"; DependsOn = "[xSPInstallPrereqs]InstallPrerequisites" }
#**********************************************************
# Basic farm configuration
#
# This section creates the new SharePoint farm object, and
# provisions generic services and components used by the
# whole farm
#**********************************************************
xSPCreateFarm CreateSPFarm
{
DatabaseServer = $DatabaseServer
FarmConfigDatabaseName = "SP_Config"
Passphrase = $FarmPassPhrase
FarmAccount = $FarmAccount
InstallAccount = $InstallAccount
AdminContentDatabaseName = "SP_AdminContent"
DependsOn = "[xSPInstall]InstallBinaries"
}
xSPManagedAccount ServicePoolManagedAccount
{
AccountName = $ServicePoolManagedAccount.UserName
Account = $ServicePoolManagedAccount
Schedule = ""
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPManagedAccount WebPoolManagedAccount
{
AccountName = $WebPoolManagedAccount.UserName
Account = $WebPoolManagedAccount
Schedule = ""
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPDiagnosticLoggingSettings ApplyDiagnosticLogSettings
{
InstallAccount = $InstallAccount
LogPath = "C:\ULSLogs"
LogSpaceInGB = 10
AppAnalyticsAutomaticUploadEnabled = $false
CustomerExperienceImprovementProgramEnabled = $true
DaysToKeepLogs = 7
DownloadErrorReportingUpdatesEnabled = $false
ErrorReportingAutomaticUploadEnabled = $false
ErrorReportingEnabled = $false
EventLogFloodProtectionEnabled = $true
EventLogFloodProtectionNotifyInterval = 5
EventLogFloodProtectionQuietPeriod = 2
EventLogFloodProtectionThreshold = 5
EventLogFloodProtectionTriggerPeriod = 2
LogCutInterval = 15
LogMaxDiskSpaceUsageEnabled = $true
ScriptErrorReportingDelay = 30
ScriptErrorReportingEnabled = $true
ScriptErrorReportingRequireAuth = $true
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPUsageApplication UsageApplication
{
Name = "Usage Service Application"
DatabaseName = "SP_Usage"
UsageLogCutTime = 5
UsageLogLocation = "C:\UsageLogs"
UsageLogMaxFileSizeKB = 1024
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPStateServiceApp StateServiceApp
{
Name = "State Service Application"
DatabaseName = "SP_State"
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPDistributedCacheService EnableDistributedCache
{
Name = "AppFabricCachingService"
Ensure = "Present"
CacheSizeInMB = $CacheSizeInMB
ServiceAccount = $ServicePoolManagedAccount.UserName
InstallAccount = $InstallAccount
DependsOn = @('[xSPCreateFarm]CreateSPFarm','[xSPManagedAccount]ServicePoolManagedAccount')
CreateFirewallRules = $true
}
#**********************************************************
# Web applications
#
# This section creates the web applications in the
# SharePoint farm, as well as managed paths and other web
# application settings
#**********************************************************
xSPWebApplication HostNameSiteCollectionWebApp
{
Name = "SharePoint Sites"
ApplicationPool = "SharePoint Sites"
ApplicationPoolAccount = $WebPoolManagedAccount.UserName
AllowAnonymous = $false
AuthenticationMethod = "NTLM"
DatabaseName = "SP_Content_01"
DatabaseServer = $DatabaseServer
Url = $WebAppUrl
Port = 80
InstallAccount = $InstallAccount
DependsOn = "[xSPManagedAccount]WebPoolManagedAccount"
}
xSPManagedPath TeamsManagedPath
{
WebAppUrl = "http://$WebAppUrl"
InstallAccount = $InstallAccount
RelativeUrl = "teams"
Explicit = $false
HostHeader = $true
DependsOn = "[xSPWebApplication]HostNameSiteCollectionWebApp"
}
xSPManagedPath PersonalManagedPath
{
WebAppUrl = "http://$WebAppUrl"
InstallAccount = $InstallAccount
RelativeUrl = "personal"
Explicit = $false
HostHeader = $true
DependsOn = "[xSPWebApplication]HostNameSiteCollectionWebApp"
}
xSPCacheAccounts SetCacheAccounts
{
WebAppUrl = "http://$WebAppUrl"
SuperUserAlias = "DEMO\svxSPSuperUser"
SuperReaderAlias = "DEMO\svxSPReader"
InstallAccount = $InstallAccount
DependsOn = "[xSPWebApplication]HostNameSiteCollectionWebApp"
}
#**********************************************************
# Service instances
#
# This section describes which services should be running
# and not running on the server
#**********************************************************
xSPServiceInstance ClaimsToWindowsTokenServiceInstance
{
Name = "Claims to Windows Token Service"
Ensure = "Present"
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPServiceInstance UserProfileServiceInstance
{
Name = "User Profile Service"
Ensure = "Present"
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPServiceInstance SecureStoreServiceInstance
{
Name = "Secure Store Service"
Ensure = "Present"
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPServiceInstance ManagedMetadataServiceInstance
{
Name = "Managed Metadata Web Service"
Ensure = "Present"
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPServiceInstance BCSServiceInstance
{
Name = "Business Data Connectivity Service"
Ensure = "Present"
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPUserProfileSyncService UserProfileSyncService
{
UserProfileServiceAppName = "User Profile Service Application"
Ensure = "Present"
FarmAccount = $FarmAccount
InstallAccount = $InstallAccount
DependsOn = "[xSPUserProfileServiceApp]UserProfileServiceApp"
}
#**********************************************************
# Service applications
#
# This section creates service applications and required
# dependencies
#**********************************************************
xSPServiceAppPool MainServiceAppPool
{
Name = "SharePoint Service Applications"
ServiceAccount = $ServicePoolManagedAccount.UserName
InstallAccount = $InstallAccount
DependsOn = "[xSPCreateFarm]CreateSPFarm"
}
xSPUserProfileServiceApp UserProfileServiceApp
{
Name = "User Profile Service Application"
ApplicationPool = "SharePoint Service Applications"
MySiteHostLocation = "http://$MySiteHostUrl"
ProfileDBName = "SP_UserProfiles"
ProfileDBServer = $DatabaseServer
SocialDBName = "SP_Social"
SocialDBServer = $DatabaseServer
SyncDBName = "SP_ProfileSync"
SyncDBServer = $DatabaseServer
FarmAccount = $FarmAccount
InstallAccount = $InstallAccount
DependsOn = @('[xSPServiceAppPool]MainServiceAppPool', '[xSPManagedPath]PersonalManagedPath', '[xSPSite]MySiteHost', '[xSPManagedMetaDataServiceApp]ManagedMetadataServiceApp','[xSPSearchServiceApp]SearchServiceApp')
}
xSPSecureStoreServiceApp SecureStoreServiceApp
{
Name = "Secure Store Service Application"
ApplicationPool = "SharePoint Service Applications"
AuditingEnabled = $true
AuditlogMaxSize = 30
DatabaseName = "SP_SecureStore"
InstallAccount = $InstallAccount
DependsOn = "[xSPServiceAppPool]MainServiceAppPool"
}
xSPManagedMetaDataServiceApp ManagedMetadataServiceApp
{
Name = "Managed Metadata Service Application"
InstallAccount = $InstallAccount
ApplicationPool = "SharePoint Service Applications"
DatabaseServer = $DatabaseServer
DatabaseName = "SP_ManagedMetadata"
DependsOn = "[xSPServiceAppPool]MainServiceAppPool"
}
xSPSearchServiceApp SearchServiceApp
{
Name = "Search Service Application"
DatabaseName = "SP_Search"
ApplicationPool = "SharePoint Service Applications"
InstallAccount = $InstallAccount
DependsOn = "[xSPServiceAppPool]MainServiceAppPool"
}
xSPBCSServiceApp BCSServiceApp
{
Name = "BCS Service Application"
ApplicationPool = "SharePoint Service Applications"
DatabaseName = "SP_BCS"
DatabaseServer = $DatabaseServer
InstallAccount = $InstallAccount
DependsOn = @('[xSPServiceAppPool]MainServiceAppPool', '[xSPSecureStoreServiceApp]SecureStoreServiceApp')
}
#**********************************************************
# Site Collections
#
# This section contains the site collections to provision
#**********************************************************
xSPSite TeamSite
{
Url = "http://$TeamSiteUrl"
OwnerAlias = $InstallAccount.UserName
HostHeaderWebApplication = "http://$WebAppUrl"
Name = "Team Sites"
Template = "STS#0"
InstallAccount = $InstallAccount
DependsOn = "[xSPWebApplication]HostNameSiteCollectionWebApp"
}
xSPSite MySiteHost
{
Url = "http://$MySiteHostUrl"
OwnerAlias = $InstallAccount.UserName
HostHeaderWebApplication = "http://$WebAppUrl"
Name = "My Site Host"
Template = "SPSMSITEHOST#0"
InstallAccount = $InstallAccount
DependsOn = "[xSPWebApplication]HostNameSiteCollectionWebApp"
}
#**********************************************************
# Local configuration manager settings
#
# This section contains settings for the LCM of the host
# that this configuraiton is applied to
#**********************************************************
LocalConfigurationManager
{
RebootNodeIfNeeded = $true
}
}
}

10.2) Take a quick look at the DSC script. The first few lines are describing what mandatory parameters need to be passed on to the configuration template upon calling it. These parameters are:

Parameter Name Description My Value
$CredSSPDelegates Name of the delegated server *.contoso.com
$SPBinaryPath Absolute path to the SharePoint 2016 installer bits F:\
$SPBinaryPathCredential Account that has access to the location where the SharePoint 2016 installation bits are located. Any account with access will do. contoso\sp_install
$FarmAccount SharePoint 2016 Farm Account contoso\sp_farm
$InstallAccount Account used to install the SharePoint 2016 bits. contoso\sp_install
$ProductKey The SharePoint 2016 Product key NQGJR-63HC8-XCRQH-MYVCH-3J3QRTrial key for SharePoint 2016 Beta 2 (180 days)
$DatabaseServer Name of the associated SQL server. localhost
$FarmPassPhrase Passphrase used to configure the farm and add additional servers. pass@word1
$WebPoolManagedAccount Account used to configure the application pool in IIS for the Web Applications. contoso\sp_webapp
$ServicePoolManagedAccount Account used to configure the application pool in IIS for the Web Services. contoso\sp_serviceapps
$WebAppUrl URL of the first web application to be created in the farm. SP2016-DSCTBD
$TeamSiteUrl URL of the Root site collection associated with the Web Application. http://localhost/
$MySiteHostUrl URL of the My Site Host site collection. http://localhost/personnal/
$CacheSizeInMB Size of the Distributed Cache size in MB. 300

10.3) Let us now create a second PowerShell script that will be responsible for declaring our parameters, and for calling the actual DSC configuration method, generating the .MOF files for our server.

."C:\Scripts\SharePoint2016Config.ps1"
 $CredSSPDelegates = "*.contoso.com"
 $SPBinaryPath = "F:\"
 $SPBinaryPathCredential = Get-Credential -UserName "contoso\sp_install" -Message "SP_Install"
 $FarmAccount = Get-Credential -UserName "contoso\sp_farm" -Message "SP_Farm"
 $InstallAccount = Get-Credential -UserName "contoso\sp_install" -Message "SP_Install"
 $ProductKey ="NQGJR-63HC8-XCRQH-MYVCH-3J3QR"
 $DatabaseServer = "SP2016-DSCTBD"
 $FarmPassPhrase = "pass@word1"
 $WebPoolManagedAccount = Get-Credential -UserName "contoso\sp_webapp" -Message "SP_WebApp"
 $ServicePoolManagedaccount = Get-Credential -UserName "contoso\sp_serviceapps" -Message "SP_ServiceApps"
 $WebAppUrl = "SP2016-DSCTBD"
 $TeamSiteUrl = "/"
 $MySiteHostUrl = "/personnal/"
 $CacheSizeInMB = 300
 $ConfigData = @{
 AllNodes = @(
 @{
 NodeName = "SP2016-DSCTBD"
 PSDscAllowPlainTextPassword = $true
 })
 }
 SharePointServer -ConfigurationData $ConfigData -CredSSPDelegates $CredSSPDelegates -SPBinaryPath $SPBinaryPath -ULSViewerPath "c:\tools\ULSViewer.exe" -SPBinaryPathCredential $SPBinaryPathCredential -FarmAccount $FarmAccount -InstallAccount $InstallAccount -ProductKey $ProductKey -DatabaseServer $DatabaseServer -FarmPassPhrase $FarmPassPhrase -WebPoolManagedAccount $WebPoolManagedAccount -ServicePoolManagedAccount $ServicePoolManagedAccount -WebAppUrl $WebAppurl -TeamSiteUrl $TeamSiteUrl -MySiteHostUrl $MySiteHostUrl -CacheSizeInMB $CacheSizeInMB

10.4) Let us now execute our script . In my case, I named it Execute.ps1 and stored it under C:\Scripts\ as well. Executing the script should generate two files: localhost.MOF and localhost.meta.MOF.

Mof

11 – Execute the Start-DSCConfiguration cmdlet

Now that we’ve generated the MOF files that are required to configure our server, we need to initiate a process on the PowerShell Local Configuration Machine to tell it to start configuring our server based on the specifications we specified in our DSC configuration script.

11.1) In a PowerShell session, execute the following line of code:

Start-DSCConfiguration -Path C:\Scripts\SharePointserver\ -Wait -Verbose -Force

Start-DSC2

12 – Reboot

After a little while, the Local Configuration Machine will require you to restart your server.

12.1) Restart the server
Reboot