There are two different types of DSC pull server that you can implement: SMB-based and web-based. The SMB-based pull server approach is most useful on a private routable network, one where all nodes can reach the centralized configuration and resource pull server shares. For high availability, you could set up an SMB pull server on a clustered, scaled-out file server.
DSC uses MOF to communicate the desired state to a node. The LCM on a node, in effect, configures the node based on whatever the MOF file says. MOF files are, at rest, just plaintext documents, and are not encrypted or signed. If your private network is secure, then the SMB pull server is easier to set up and configure. If security is an issue, consider using the web server pull server approach and configure it with HTTPS (which you do in the Implementing a web-based DSC pull server recipe).
Since you may have used other recipes in this chapter—such as the Configuring the DSC local configuration manager recipe where you configured a node—you first need to clean out any existing DSC configuration details before carrying out this recipe.
When you deploy an SMB-based pull server, you place the configuration documents on the SMB share for the target nodes to pull and use. You also configure the LCM on a node to tell the node where and how to get the MOF files. To enable a node to identify which configuration document it should download and use, the node is configured with a GUID (the ConfigurationID
) and an SMB share path where the LCM can find configuration MOF files. The MOF file that you deploy to a node is named using the GUID (that is, <guid>.mof
).
In this recipe, you configure the LCM on SRV2
with a ConfigurationID
set to 5d79ee6e-0420-4c98-9cc3-9f696901a816
. The LCM configuration also specifies that the LCM on SRV2
should pull configurations from the SMB pull server located at \SRV1DSCConfiguration
. In this case, the LCM on SRV2
would look for the file named \SRV1DSCConfiguration5d79ee6e-0420-4c98-9cc3-9f696901a816.mof
plus the related checksum file.
This recipe uses another PS Gallery sourced module, the xSMBShare
module. This module is used to create a DSC configuration that creates necessary shares. In this case, you use DSC with this module to configure two shares on SRV1
, which DSC nodes (that is, SRV2
) use to pull configuration documents.
This recipe is run on SRV1
and provides a DSC configuration for SRV2
.
This recipe removes any DSC configuration documents on both SRV1
and SRV2
. Any configuration that was performed using previous recipes, for example adding the DNS Server service to SRV2
, remain in place with DSC only concerning itself with the new configuration document(s) you add to the pull server.
xSMBShare
module is installed on SRV1
and SRV2
and ensure that C:DSC
exists using the following code:$SB1 = { Install-Module xSMBShare -Force | Out-Null } Invoke-Command -ComputerName SRV1 -ScriptBlock $SB1 Invoke-Command -ComputerName SRV2 -ScriptBlock $SB1
SRV1
and SRV2
using the following code:$SB2 = { $RIHT = @{ Path = 'C:WindowsSystem32configuration*.mof' ErrorAction = 'SilentlyContinue' } Get-Childitem @RIHT | Remove-Item @RIHT -Force $EASC = @{ ErrorAction = 'SilentlyContinue' } New-Item -Path c:DSC -ItemType Directory @EASC | Out-Null Remove-DscConfigurationDocument -Stage Current } Invoke-Command -ComputerName SRV1 -ScriptBlock $SB2 Invoke-Command -ComputerName SRV2 -ScriptBlock $SB2
SRV2
that configures SRV2
to pull from SRV1
using the following code:$SB3 = { [DSCLocalConfigurationManager()] Configuration SetSRV2PullMode { Node localhost { Settings { ConfigurationModeFrequencyMins = '30' ConfigurationMode = 'ApplyAndAutoCorrect' RebootNodeIfNeeded = $true ActionAfterReboot = 'ContinueConfiguration' RefreshMOde = 'Pull' RefreshFrequencyMins = '30' AllowModuleOverwrite = $true ConfigurationID = '5d79ee6e-0420-4c98-'+ '9cc3-9f696901a816' } ConfigurationRepositoryShare PullServer { SourcePath = '\SRV1DSCConfiguration' } ResourceRepositoryShare ResourceServer { SourcePath = '\SRV1DSCResource' } } } } SetSRV2PullMode -OutputPath 'C:DSC' | Out-Null
SRV2
LCM using the following code:$DHT = @{ Path = 'C:DSC' } Set-DscLocalConfigurationManager -Path C:DSC Get-DscLocalConfigurationManager
SRV2
to pull via SMB from SRV1
using the following code:Invoke-Command -ScriptBlock $SB3 -ComputerName SRV2
SRV1
as a DSC pull server using the following code:Configuration PullSrv1 { Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -ModuleName xSmbShare File ConfigFolder { DestinationPath = 'C:DSCConfiguration' Type = 'Directory' Ensure = 'Present' } File ResourceFolder { DestinationPath = 'C:DscResource' Type = 'Directory' Ensure = 'Present' } xSmbShare DscConfiguration { Name = 'DSCConfiguration' Path = 'C:DscConfiguration' DependsOn = '[File]ConfigFolder' Description = 'DSC Configuration Share' Ensure = 'Present' } xSmbShare DscResource { Name = 'DSCResource' Path = 'C:DscResource' DependsOn = '[File]ResourceFolder' Description = 'DSC Resource Share' Ensure = 'Present' } }
SRV1
as a pull server using the following code:PullSRV1 -OutputPath C:DSC | Out-Null
SRV1
as a pull server using the following code:Start-DscConfiguration -Path C:DSC -Wait -Verbose -Force
SRV1
using the following code:Get-SMBShare -Name DSC*
SRV2
to pull from SRV1
that configures SRV2
to have a Telnet client feature using the following code:Configuration TelnetSRV2 { Import-DscResource –ModuleName 'PSDesiredStateConfiguration' Node SRV2 { WindowsFeature TelnetSRV2 { Name = 'Telnet-Client' Ensure = 'Present' } } }
SRV2
to have the Telnet client using the following code:TelnetSRV2 -OutputPath C:DSCConfiguration
$Guid = '5d79ee6e-0420-4c98-9cc3-9f696901a816' $RIHT = @{ Path = 'C:DSCConfigurationSRV2.mof' NewName = "C:DSCConfiguration$Guid.MOF" } Rename-Item @RIHT
New-DscChecksum -Path C:DSCConfiguration
Get-ChildItem -Path C:DSCConfiguration
SRV2
using the following code:Get-WindowsFeature -Name Telnet-Client -ComputerName SRV2
Start-Sleep -Seconds (30*60) Get-WindowsFeature -Name Telnet-Client -ComputerName SRV2
In step 1, you ensure that the xSMBShare
module is installed on SRV1
and SRV2
. In step 2, you remove both any existing MOF files and any DSC configurations from both SRV1
and SRV2
. In step 3, you create a script block that creates and deploys an LCM configuration that sets the LCM configuration and creates the related MOF file. These three steps produce no output, although depending on what other recipes you have run, you may get prompted to install the NuGet provider in Step 2.
In step 4, you create a script to run the script block you just created that configures the LCM on SRV2
(based on the configuration block you created in step 3) and returns the LCM configuration, which looks like this:
In step 5, you create and compile a configuration statement that configures SRV1
to be a DSC pull server. In step 6, you generate the MOF for this configuration. In step 7, you run the configuration block to produce the relevant MOF file These three steps produce no output.
In step 8, you run Start-DscConfiguration
to configure SRV1
based on the just-compiled MOF file, which looks like this:
In step 9, you get the SMB shares—created in the previous step—on SRV1
, which looks like this:
In step 10, you create the first partial configuration block, TelnetSRV2
, which creates no output. In step 11, you run this configuration block to produce SRV2.mof
, which looks like this:
In step 12, you rename the MOF file with the GUID name, and then in step 13, you create a MOF checksum file. These two steps produce no output.
In step 14, you view the MOF and checksum files, which looks like this:
In step 15, you view the current (uninstalled) state of the Telnet-client
on SRV2
, which looks like this:
In step 16, you wait for DSC operations to happen, then review the state of Telnet-Client
on SRV2
, which now looks like this:
In the last two steps in this recipe, you look at the state of the Telnet client on SRV2
. In step 15, you can see that DSC has not yet run the SRV2
configuration, and so the client is not installed. After waiting, in step 16, you can see that the Telnet client is now installed on SRV2
. Note that if adding this feature had required a reboot, SRV2
would have been rebooted some time after step 15 completed.
Setting up a pull server and getting it to configure another server is straightforward, although typos are often a challenge to troubleshoot. By default, Windows Server does not perform detailed DSC event logging; however, it is simple to turn logging on using the following code:
wevtutil.exe set-log "Microsoft-Windows-Dsc/Analytic" /q:true /e:true wevtutil.exe set-log "Microsoft-Windows-Dsc/Debug" /q:True /e:true
Once you turn on DSC analytic and debug logging, every DSC activity is logged in detail. In earlier recipes, you examined the verbose output of Start-DscConfiguration
, which shows the LCM getting and performing a configuration. That same amount of information, and more, is available from the event logs. From these logs, you can trace DSC's activities, see the configuration blocks and resources that are being downloaded, and see DSC enforce the configuration. For more detail on using DSC event logging for troubleshooting, see https://docs.microsoft.com/en-us/powershell/dsc/troubleshooting/troubleshooting.
18.191.176.5