PowerShell Desired State Configuration (DSC) is Microsoft’s answer to infrastructure‑as‑code for Windows environments. It lets you declare the desired state of a server—services, files, registry keys, and more—and then automatically enforces that state, day after day. In this guide we’ll walk through everything you need to start using DSC in a real‑world setting, from installing the required modules to pushing configurations across multiple machines. By the end you’ll have a repeatable, version‑controlled process that keeps your infrastructure consistent and compliant.
What You’ll Need
- A Windows 10/11 workstation or Windows Server 2016+ with administrative rights.
- PowerShell 5.1 or PowerShell 7.x installed.
- Internet access to download the
PSDesiredStateConfigurationmodule (if not already present). - At least one target machine (physical or virtual) running Windows.
- A source‑control system (Git is recommended) for storing DSC scripts.
Step 1: Install the DSC Module and Verify the Environment
DSC ships with Windows PowerShell 5.1, but the newer PSDesiredStateConfiguration module provides cross‑platform cmdlets and improved performance. Open an elevated PowerShell session and run:
Install-Module -Name PSDesiredStateConfiguration -Repository PSGallery -Force After installation, confirm the version:
Get-Module -ListAvailable PSDesiredStateConfiguration | Select-Object Name,Version If you see a version number (e.g., 2.12.0), you’re ready. Also, enable the DSC engine on the target machines if it isn’t already:
Enable-PSRemoting -Force # required for remote push Running Get-DscConfiguration should now return either an empty configuration or the current state of the node.
Step 2: Create a Basic DSC Configuration Script
DSC configurations are written as PowerShell functions that output a Management Object Format (MOF) file. Create a new folder C:DSCDemo and a file called WebServerConfig.ps1 with the following content:
Configuration WebServerConfig {
param (
[string[]]$NodeName = 'localhost'
)
Import-DscResource -ModuleName PSDesiredStateConfiguration
Node $NodeName {
WindowsFeature IIS {
Ensure = 'Present'
Name = 'Web-Server'
}
File IndexPage {
DestinationPath = 'C:inetpubwwwrootindex.html'
Contents = "<h1>Welcome to DSC‑Managed IIS</h1>"
Ensure = 'Present'
Type = 'File'
}
}
}
# Compile the MOF for the local machine
WebServerConfig -OutputPath 'C:DSCDemoMOF'
This script declares two resources: the WindowsFeature resource to install IIS, and the File resource to drop a simple HTML page. The Configuration block is the heart of DSC; it’s where you describe the “desired state”.
Step 3: Compile the MOF Files
When you invoke the configuration function (as shown at the bottom of the script), PowerShell generates a .mof file for each node you specified. The MOF is a declarative representation that the DSC engine consumes. Verify the output:
Get-ChildItem 'C:DSCDemoMOF' -Filter *.mof You should see localhost.mof. Open it in a text editor to see the low‑level representation—don’t edit it manually; always regenerate from the PowerShell script.
Step 4: Apply the Configuration Locally
Now that the MOF exists, apply it to the node with Start-DscConfiguration:
Start-DscConfiguration -Path 'C:DSCDemoMOF' -Wait -Verbose -Force The -Wait flag pauses until DSC finishes, and -Verbose gives you a live view of each resource being evaluated. After it completes, verify the state:
Get-DscConfiguration -Detailed You should see IIS installed and the index.html file present. Open a browser to http://localhost to confirm the custom page is being served.
Step 5: Push the Configuration to Remote Nodes
In production you rarely apply configurations only to the local machine. Use PowerShell remoting to push the MOF to other servers. First, ensure the target node trusts the source machine (add it to the TrustedHosts list or use proper Kerberos delegation). Then run:
$Target = 'Server01'
Copy-Item -Path 'C:DSCDemoMOF$Target.mof' -Destination "\$Targetc$DSCMOF" -Force
Start-DscConfiguration -ComputerName $Target -Path "C:DSCMOF" -Wait -Verbose -Force
If you have many nodes, consider looping over an array of server names. DSC will automatically report back success or failure for each resource on each node.
Step 6: Monitor, Diagnose, and Remediate Drift
DSC keeps a local log at C:WindowsSystem32ConfigurationDSC. Use Get-DscConfigurationStatus to see recent operations:
Get-DscConfigurationStatus | Select-Object -First 5 | Format-Table -AutoSize If a resource drifts (e.g., someone manually deletes index.html), DSC will detect the change on the next refresh cycle (default every 15 minutes) and automatically restore compliance. You can also force a refresh with:
Invoke-DscResource -Name File -Method Test -Property @{ DestinationPath='C:inetpubwwwrootindex.html' }
For deeper troubleshooting, enable detailed logging by editing C:WindowsSystem32ConfigurationDSCDSCConfigurationStatus.log or using the Set-DscLocalConfigurationManager cmdlet to adjust the RefreshMode and RefreshFrequencyMins settings.
Step 7: Version Control Your DSC Scripts and Use a Pull Server (Optional)
Storing your DSC configurations in Git (or another VCS) gives you change history, code review, and easy rollback. A typical workflow:
- Clone a repository:
git clone https://github.com/yourorg/dsc-configs.git - Create a branch for a new feature (e.g., adding a firewall rule).
- Commit changes to
.ps1files and push. - On a build server, run the configuration script to generate MOFs and publish them to a DSC Pull Server.
A Pull Server (often IIS hosting a simple file share) lets nodes pull their configuration on a schedule, removing the need for you to push each time. To set one up quickly:
Install-WindowsFeature -Name DSC-Service
New-Item -Path 'C:DSCPullServer' -ItemType Directory
Set-ItemProperty -Path 'HKLM:SoftwareMicrosoftWindowsCurrentVersionDSC' -Name 'PullServerUrl' -Value 'http://pullserver:8080/PSDSC'
Configure each node’s Local Configuration Manager (LCM) to use the Pull Server:
[DSCLocalConfigurationManager()]
configuration LCMConfig {
Node "*" {
Settings {
RefreshMode = 'Pull'
RefreshFrequencyMins = 30
PullServerUrl = 'http://pullserver:8080/PSDSC'
}
}
}
LCMConfig -OutputPath 'C:DSCLCM'
Set-DscLocalConfigurationManager -Path 'C:DSCLCM' -Verbose
From this point forward, each node will check the Pull Server every 30 minutes, download the latest MOF (if version has changed), and apply it automatically.
Common Mistakes to Avoid
1. Editing MOF files directly. MOFs are generated artifacts; manual edits are overwritten the next time you compile the configuration.
2. Forgetting to import required resources. If you use a custom resource module, add Import-DscResource -ModuleName MyCustomModule at the top of the configuration.
3. Mismatched node names. The node name in the Node block must match the computer’s hostname or the name you use with -ComputerName. Otherwise DSC will think it’s a different node and create duplicate entries.
4. Incorrect execution policy. DSC scripts need at least RemoteSigned. Run Set-ExecutionPolicy RemoteSigned -Scope Process -Force if you hit a policy error.
5. Neglecting to test idempotence. Run Start-DscConfiguration -WhatIf or invoke each resource with -Method Test before applying changes to ensure the script won’t cause unintended side effects.
Tips and Tricks
– Use composite resources. Combine multiple built‑in resources into a single reusable block to keep your configurations DRY.
– Leverage partial configurations. Split large configurations into logical parts (e.g., WebServer.ps1, Database.ps1) and then compose them in a master configuration.
– Enable detailed logging. Add ConfigurationMode = 'ApplyAndAutoCorrect' in the LCM settings for aggressive drift correction.
– Store secrets securely. Use the Credential resource with encrypted credentials or integrate with Azure Key Vault for password‑protected services.
– Automate MOF generation in CI/CD. Include a PowerShell step in your pipeline that runs the configuration script, archives the MOFs, and publishes them to the Pull Server.
Frequently Asked Questions
Can DSC manage Linux machines?
Yes. Starting with PowerShell 7, DSC supports cross‑platform resources via the PSDesiredStateConfiguration module. You’ll need to install the DSC for Linux package on the target and use the Linux resource set.
What’s the difference between Push and Pull modes?
Push mode sends the MOF from a management workstation directly to each node using PowerShell remoting. Pull mode relies on a central Pull Server; nodes periodically request their configuration. Pull scales better for large farms, while Push gives you immediate control.
How does DSC handle configuration drift?
When a node’s actual state diverges from the declared state, the DSC engine re‑applies the resource during the next refresh cycle (or immediately if you run Start-DscConfiguration -Force). This self‑healing behavior is the core benefit of DSC.
Conclusion
PowerShell Desired State Configuration transforms manual server administration into a repeatable, code‑first process. By installing the DSC module, writing clear configuration scripts, compiling MOF files, and choosing the right deployment mode, you can guarantee that every server in your environment stays exactly the way you intended. Remember to version‑control your scripts, monitor compliance regularly, and avoid the common pitfalls outlined above. With these practices in place, DSC becomes a powerful ally in your quest for reliable, automated infrastructure.
Photo by Microsoft Copilot on Unsplash





