Day 1: Intro to PowerShell DSC and Configuring Your First Pull Server

Welcome to Day 1 of the “100 Days of DevOps with PowerShell”! For background on our goals in this series, see Announcing the “100 Days of DevOps with PowerShell” Series here on SCC.

Today, I am going to introduce you to PowerShell Desired State Configuration (DSC) and demonstrate how it enables DevOps through a hands-on example. I’ll endeavor to be thorough for those who are relatively new to PowerShell DSC, but also very brief, so you can easily work through the concepts and example in a few minutes time. We will build on this foundation through varied (and sometimes more complex) examples as the series continues.

I submit for your review, PowerShell DSC concepts and pull server in less than 2,000 words.

What is PowerShell DSC?

Desired State Configuration (DSC) is a feature in PowerShell 4.0 and Windows Server 2012 R2 that helps Windows administrators manage and deploy software services’ configuration data and the environment the services run in.

DSC provides a set of PowerShell language extensions, cmdlets and a process called declarative scripting. The goal of DSC is to provide administrators with a method for maintaining consistent configuration sets across computers or devices.  You can write an expression describing a system configuration, and the system will evaluate and apply the configuration. Common use cases for PowerShell DSC include (but are not limited to):

  • Enabling or disabling server roles and features (like IIS)
  • Deploying new software
  • Deploy an IIS website (including the site content)
  • Managing registry settings
  • Running Windows PowerShell scripts
  • Managing files and directories
  • Starting, stopping, and managing processes and services
  • Managing groups and user accounts
  • Managing environment variables
  • Fixing a configuration that has drifted away from the desired state
  • Discovering the actual configuration state on a given node

The bottom line is PowerShell DSC enables IT Pros to support consistent, standardized configuration and continuous deployment, both core goals of DevOps.

How PowerShell DSC Works (high level)

With DSC, you start by writing a configuration script in Windows PowerShell. This script doesn’t do anything. It doesn’t install, configure, provision, or anything else. It simply lists the elements you want configured, and how you want them configured. The configuration also specifies the machines to which it applies. When you run the configuration, PowerShell produces a Management Object Format (MOF) file for each targeted machine, or node. MS chose the MOF format in part because it’s a widely accepted standard, you can create them with a variety of tools…even Notepad (but don’t create MOF files in Notepad).

1. Write a configuration script in PowerShell.

2. Run that script, which creates one or more MOF files, depending on how many machines (called nodes). If your configuration is written to target multiple nodes, you’ll get a MOF file for each one. Machines with the same configuration (like members of a web farm) can use the same MOF file and DSC configuration ID.

3. MOF files are distributed to the machines (nodes) for which they are intended. Each node can have only one MOF file.

4. Nodes start configuring themselves to match what is defined in the MOF file.

There are two ways to distribute the files to the nodes (step 3):

  • Push mode is basically a manual file copy via Windows Remote Management (WinRM) remoting
  • Pull mode configures nodes to check in to a special web server (called a pull server) retrieve their MOF configuration files automatically every few minutes. And once configured, the node will recheck its configuration every few minutes to ensure its configuration matches the settings in the MOF file.

Pull mode is the way the vast majority of enterprises in the real world will use DSC and thus is the method we will typically use in this series. When you use the pull server method, the nodes will not only recheck their configuration every few minutes, but they will also check the pull server for an updated MOF file to ensure they checking for your current intended configuration.

Sample Environment (for this tutorial)

The sample environment used in this tutorial consists of two machines:

  • Server1.contoso.com – A Windows Server 2012 R2 system with about 2 GB of ram (size A1 in Microsoft Azure) that we will configure as a Pull Server.
  • Server2.contoso.com – Another Windows 2012 R2 system just like the first. This system will serve as a managed system (node) that will retrieve its configuration file from the pull server.

NOTE: Yes, my machines are Azure VMs (IaaS), but yours do not have to be. You can use PowerShell DSC on physical or virtual machines, on-premises or in the cloud, running Windows or even Linux (more on this on day 2 of DevOps on Monday).

Configuring the pull server

You can configure a pull server to use HTTP, HTTPS, or SMB. For ease of use in your first experience with DSC, we will use HTTP (keeping it simple on day 1). The easiest method for creating a pull server is probably the xPSDesiredStateConfiguration module, in the PowerShell DSC Resource Kit created by Microsoft and published to the TechNet Gallery. In this step, you are going to use a pre-created configuration script that will create a MOF file to configure server1 as our pull server. You will then tell server1 to apply that MOF file, effectively configuring server1 as a DSC pull server.

Perform the following steps on Server1.contoso.com (or your equivalent)

1) Download the xPSDesiredStateConfiguration module from http://gallery.technet.microsoft.com/xPSDesiredStateConfiguratio-417dc71d. Unzip the module to the %programfiles%\WindowsPowerShell\modules directory.

image

 

2) Use the Add Roles and Features Wizard to add the Windows PowerShell Desired State Configuration feature.

image

When you check the box by the feature, the wizard will prompt you to accept installation of all the required components, which includes Windows Communication Foundation (WCF). Click Add Features and complete the wizard.

image

Notes:

  • You will need the above on any system where you intend to author DSC configurations.
  • You can also add this feature via PowerShell with this one-liner:

Add-WindowsFeature Dsc-Service

3) Enable a WS Management listener if not already enabled.

winrm quickconfig

This was not enabled by default in the standard Windows Server 2012 gallery images I used for this tutorial. If you don’t know, you can simply run the command and if already configured, you will receive a message to that effect.

4) Run the script to create the configuration MOF file for the pull server. This script creates a file named server1.contoso.com.mof.

NOTE: I ran the script below in the PowerShell ISE, but if you prefer, you could save it as a PowerShell script (.ps1) and run from a PowerShell prompt.

 

configuration NewPullServer
{
param
(
[string[]]$ComputerName = ‘localhost’
)

    Import-DSCResource -ModuleName xPSDesiredStateConfiguration

    Node $ComputerName
{
WindowsFeature DSCServiceFeature
{
Ensure = “Present”
Name   = “DSC-Service”
}

        xDscWebService PSDSCPullServer
{
Ensure                  = “Present”
EndpointName            = “PSDSCPullServer”
Port                    = 8080
PhysicalPath            = “$env:SystemDrive\inetpub\wwwroot\PSDSCPullServer”
CertificateThumbPrint   = “AllowUnencryptedTraffic”
ModulePath              = “$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules”
ConfigurationPath       = “$env:PROGRAMFILES\WindowsPowerShell\DscService\Configuration”
State                   = “Started”
DependsOn               = “[WindowsFeature]DSCServiceFeature”
}

        xDscWebService PSDSCComplianceServer
{
Ensure                  = “Present”
EndpointName            = “PSDSCComplianceServer”
Port                    = 9080
PhysicalPath            = “$env:SystemDrive\inetpub\wwwroot\PSDSCComplianceServer”
CertificateThumbPrint   = “AllowUnencryptedTraffic”
State                   = “Started”
IsComplianceServer      = $true
DependsOn               = (“[WindowsFeature]DSCServiceFeature”,”[xDSCWebService]PSDSCPullServer”)
}
}
}

#This line actually calls the function above to create the MOF file.

NewPullServer –ComputerName server1.contoso.com

 

The output of the configuration script is the MOF file mentioned above (and shown below).

image

 

5) Next, run the following command, which tells server1 to apply the configuration MOF file, configuring server1 as a pull server.

Start-DscConfiguration .\NewPullServer –Wait

 

===============================================================

SIDEBAR: In my case, I actually received the error below on the first attempt:

“The WinRM client sent a request to an HTTP server and got a response saying the requested HTTP URL was not available.”

I disabled IPv6 on server1.contoso.com (as it was not enabled elsewhere) and then re-attempted step 5, which ran successfully on the second attempt.

image

===============================================================

 

After the configuration process reported as successful, I checked my pull server by first looking in IIS Manager

image

And then by checking the web service to ensure the pull server was responding as expected.

image

How that your pull server is ready, you are ready to test pulling a configuration to a node (server2.contoso.com) to verify your pull server is functional.

Create a Configuration for a Node

1) First, you will create a configuration for server2. This very common sample ensures the IIS Web Server feature is enabled on a server.

However, you will run this configuration script from the pull server (server1 in this example)

Configuration ContosoWebsite
{
param ($MachineName)
Node $MachineName
{
#Install the IIS Role
WindowsFeature IIS
{
Ensure = “Present”
Name = “Web-Server”
}
#Install ASP.NET 4.5
WindowsFeature ASP
{
Ensure = “Present”
Name = “Web-Asp-Net45”
}
}
}

ContosoWebsite –MachineName “server2.contoso.com”

The snippet above creates a MOF file named server2.contoso.com.mof in the c:\users\<LoggedOnUser>\ContosoWebsite directory (c:\users\administrator\ContosoWebsite in my environment).

2) Generate the GUID that will be used to name the mof file for server2.contoso.com

[guid]::NewGuid()

image

3) Rename the file above to <GUID>.mof, where <GUID> is your GUID from step 2. Then, copy the renamed file to the folder below.

\\server1\c$\program files\windowspowershell\dscservice\configuration

 

You can accomplish steps 2 and 3 above with the following PowerShell code snippet:

$Guid= [guid]::NewGuid()

$source = “ContosoWebsite\server2.contoso.com.mof”

$target= “\\server1\c$\program files\windowspowershell\dscservice\configuration\$Guid.mof”

copy $source $target

 

4) With the MOF in place, you now need to generate a checksum file (for the server2.contoso.com.mof file ) for the pull server. When computers attempt to pull their configuration, they use the checksum to ensure the integrity of the mof file. You create the checksum file in the same PowerShell session with the one-liner:

New-DSCChecksum $target

The checksum file should appear in the same folder as the mof file, as shown below. The file as the same name as the MOF, but with a .checksum on the end.

image

 

Test Pulling the Configuration

By default, Windows computers wait for you to push a configuration to them, and then they re-check it every 15 minutes. We’re going to reconfigure server2.contoso.com to pull its configuration (the one we just created) from our pull server using the default refresh interval of 30 minutes. To do that, we will use the pull server (server1) to create another configuration file:

But before you do, logon to server2 and just verify that the IIS web server role is not already installed by running the following one-liner at a PowerShell prompt:

Get-WindowsFeature web-server

If IIS is not installed, the Install State should show as Available.

image

Okay, return to server1 and perform the following steps:

1) Run the following script at a PowerShell prompt or in the ISE.

Configuration SetPullMode
{
param([string]$guid)
Node server2.contoso.com
{
LocalConfigurationManager
{
ConfigurationMode = ‘ApplyOnly’
ConfigurationID = $guid
RefreshMode = ‘Pull’
DownloadManagerName = ‘WebDownloadManager’
DownloadManagerCustomData = @{
ServerUrl = ‘
http://server1:8080/PSDSCPullServer.svc’;
         AllowUnsecureConnection = ‘true’ }
}
}
}
SetPullMode –guid $Guid
Set-DSCLocalConfigurationManager –Computer server2.contoso.com

-Path ./SetPullMode –Verbose

 

2) Once the prompt returns success, verify the Web Server role is installed by running the following one-liner on server2 as you did before.

Get-WindowsFeature -Name Web-server

The the Install State should show as Installed.

image

Done! You have now successfully configured and tested your pull server to support PowerShell DSC.

Conclusion

I hope you’ve found this article useful. Please post comments and errata in the comments below. Join us on Monday for Day 2 of the 100 Days of DevOps with PowerShell!

30 thoughts on “Day 1: Intro to PowerShell DSC and Configuring Your First Pull Server

  1. Profile photo of Anthony ChowAnthony Chow

    What happen if DSC conflict with group policy?  I will assume one will take precedence.  Is there documentation on this that I can lookup?  thanks.

  2. Profile photo of Jose SaenzJose Saenz

    I already performed all the steps, everything was executed without errors but configuration is not being to “Server2” applied. Checking the scritps (specifically the last one) I’m a little lost there. At the end you call the configuration piece with the following lines (by the way the second has an additional “-” before Computername parameter), and you specified “$Guid” as parameter.

    Where this variable was populated? where is taking the Guid? My guess is that this should be the Guid that we assigned to MOF file, but I don’t see where is assigned.

    I just modified the scripts to match the ServerNames in my lab.

     

  3. Profile photo of Pete ZergerPete Zerger Post author

    Hey Jose, looks like you have an extra dash (-) in front of -Computer. $Guid is populated here:

    You can accomplish steps 2 and 3 above with the following PowerShell code snippet:

    $Guid = [guid]::NewGuid()

    $source = “ContosoWebsite\server2.contoso.com.mof”

    $target= “\\server1\c$\program files\windowspowershell\dscservice\configuration\$Guid.mof”

    copy $source $target

  4. Profile photo of Tommy Gunn

    Day 2 – http://www.systemcentercentral.com/how-to-install-dsc-providers-for-linux-on-centos-6-2/

    Day 3 – http://www.systemcentercentral.com/powershell-team-foundation-server-2013-getting-started/

    day 4 comes today!

  5. Profile photo of MaekeeMaekee

    Thanks Tommy, is there a page where all the links for the days are Collector. Searching for the word “day” and only find Day 1.

  6. Profile photo of Daryl HarringtonDaryl Harrington

    It looks like your configuration script for the SetPullMode has an error in it that will cause it to fail.

    Set-DSCLocalConfigurationManager …. should be on a separate line.

    SetPullMode –guid $Guid

    Set-DSCLocalConfigurationManager –Computer server2.contoso.com `
    -Path ./SetPullMode –Verbose

    Thanks for the series. Looking forward to more.

  7. Profile photo of Tommy Gunn

    Dayrl, the little tick (`) Pete has at the end of the line allows you to break up a long one-liner into two lines and have it still run.

  8. Profile photo of Daryl HarringtonDaryl Harrington

    Quite aware of the tick and it’s use, however, not what I was referring to. There should be a space between $Guid and Set. The two words run together which fails.

  9. Profile photo of CNenadCNenad

    Hi Pete and thank you for good article.

    I need some info’s about lab setup for your DSC tutorial.

    I’ve used two azure vm with Win Svr Tech. preview. Should those vm’s have to be joined into domain (ie I need to setup also domain controller, how did you get them joined into contoso.com domain) ?

    In script NewPullConfiguration, in line: [string[]]$ComputerName = ‘localhost’ does need to be changed ‘localhost’ into  name of my test vm – my localhost which will be pull server ?

    Thank you. Keep up good work.

    Best regards

    Nenad

  10. Profile photo of Pete ZergerPete Zerger Post author

    CNenad, I appreciate the kind words….thank you! About localhost: I wrote the PowerShell snippets so all could be run from the DSC Pull Server. If you run them from elsewhere, make sure to replace localhost with the name of your Pull Server. Also, beware of “smart quotes” in the script, which are attributed to MS Word, but seem to pop up occassionally in WordPress code formatters. Basically, replace any occurrence of ’ with ‘.

    Let me know if you have trouble. Always happy to assist.

  11. Pingback: Solving the DSC Pull Chicken and Egg problem « FoxDeploy.com

  12. Profile photo of Benjamin HagelsBenjamin Hagels

    Hi!

    I did every step of day 1 and all looks fine. But when I set up the SetPullMode snippet nothing happens on my server2. Web-Server doesn´t install.

    Where can I have a look to find the error?

    Thanks for this great help to understand DSC =)

  13. Pingback: Déploiement et configuration en IAAS Azure | Nouvelles Chroniques d'Amethyste

  14. Pingback: PowerShell DSC | Vincent

  15. Pingback: Multiple team, component, environment deployment via DSC | ALM by Erick Segaar

  16. Pingback: Day 1: Intro to PowerShell DSC and Configuring Your First Pull Server – System Center Central | Soyka's Blog

  17. Profile photo of NNNN

    Test Pulling the Configuration : works fine with script as below

     

    Configuration SetPullMode
    {
    Node server2.contoso.com
    {
    LocalConfigurationManager
    {
    ConfigurationID = “e624ddc7-519e-4bbd-a7f7-4af4c76d9cbd”
    ConfigurationMode = “ApplyOnly”
    RefreshMode = “Pull”
    DownloadManagerName = “WebDownloadManager”
    DownloadManagerCustomData = @{
    ServerUrl = “http://server1:8080/PSDSCPullServer.svc”;
    AllowUnsecureConnection = “true” ;
    }
    }
    }
    }
    SetPullMode
    Set-DSCLocalConfigurationManager –Computer server2.contoso.com  -Path .\SetPullMode –Verbose

  18. Profile photo of danieldaniel

    Thanks, NN! Your revised script is clear on how the ConfigurationID (GUID) can be provided. Worked like a charm the first try.

  19. Profile photo of danieldaniel

    In my case I noticed that IIS was not installing on the target server after waiting over an hour, yet the last script ran without error. On the target server I checked the event log for DSC entries:

    get-WinEvent -LogName “Microsoft-Windows-Dsc/Operational” | ft -Wrap

    There I found an entry stating:

    4160 Information      Job {52D10F1B-23D5-11E6-80C0-00505698CA2F} :
                           Registering the task with task scheduler after rebooting the
                           machine

    I rebooted the machine and after about 20 minutes, IIS was installed on the target server.

  20. Profile photo of dragon788dragon788

    For anyone running into issues with this complaining about the IsCompliance portion, they appear to have removed it sometime around March of 2016 after version 3.8.0.0.

  21. Pingback: Ansible + Windows: o básico, NTLM, DSC e mais. – Do. Automate. Repeat.

  22. Profile photo of Adam BranhamAdam Branham

    I am having a problem that I can not seem to find an answer to.  While running the initial setup script for the pull server I am getting some errors like below.

    Resource ‘xDSCWebService’ requires that a value of type ‘Boolean’ be provided for property ‘UseSecurityBestPractices’.

    Have the commands changes since this publication?

  23. Profile photo of Preetam ZarePreetam Zare

    @Adam: Just add ‘UseSecurityBestPractices = $true’ under xDSCWebService if you are configuring Https or else put it $false if you are configuring Http. Hope it help

  24. Profile photo of Preetam ZarePreetam Zare

    @Adam: Just add ‘UseSecurityBestPractices = $true’ under xDSCWebService if you are configuring Https or else put it $false if you are configuring Http. Hope it helps.

Leave a Reply