How to Configure Desired State Configuration (DSC) on Windows Server 2012 R2
PowerShell Desired State Configuration (DSC) is a management platform introduced in PowerShell 4.0 that allows administrators to define the intended state of a server — which Windows features are installed, which services are running, which files exist, and how the system is configured — in a declarative configuration document. The Local Configuration Manager (LCM) on each server then enforces this desired state, either continuously monitoring for drift and correcting it automatically, or applying the configuration on demand.
DSC fundamentally changes how Windows Server 2012 R2 configurations are managed. Instead of writing procedural scripts that execute a sequence of steps, you write a configuration document describing what the end state should look like, and DSC handles the “how.” This approach makes server configurations repeatable, auditable, and version-controllable. This guide covers configuring the LCM, writing basic configuration documents, using built-in resources, and applying configurations in both push and pull modes.
Prerequisites
– Windows Server 2012 R2 with PowerShell 4.0 (included by default)
– Administrative access on target nodes
– Basic PowerShell scripting knowledge
– For Pull mode: a DSC Pull Server configured on the network (also WS2012 R2)
– Network connectivity between the pull server and managed nodes
– Understanding of MOF (Managed Object Format) files
Step 1: Verify DSC is Available
Confirm DSC and the Local Configuration Manager are available on the target server:
Get-DscLocalConfigurationManager
This returns the current LCM settings including ConfigurationMode, RefreshMode, and RebootNodeIfNeeded. On a fresh WS2012 R2 installation, the default mode is ApplyAndMonitor.
List all built-in DSC resources available:
Get-DscResource | Select-Object Name, Module, Version | Sort-Object Name
Step 2: Write Your First DSC Configuration
A DSC configuration is a PowerShell script with a special Configuration keyword block. This example ensures the Web Server role is installed, IIS is running, and a specific directory exists:
Configuration WebServerState {
param (
[string[]]$NodeName = 'localhost'
)
Node $NodeName {
# Ensure IIS is installed
WindowsFeature IIS {
Ensure = "Present"
Name = "Web-Server"
}
# Ensure the default app pool is running
Service W3SVC {
Name = "W3SVC"
State = "Running"
StartupType = "Automatic"
DependsOn = "[WindowsFeature]IIS"
}
# Ensure a web content directory exists
File WebRoot {
Ensure = "Present"
Type = "Directory"
DestinationPath = "C:inetpubwwwrootapp"
}
}
}
# Compile the configuration to a MOF file
WebServerState -OutputPath "C:DSCConfigs"
Run this script in PowerShell. It will create a MOF file at C:DSCConfigslocalhost.mof. The MOF file is the compiled, machine-readable version of your configuration that the LCM processes.
Step 3: Apply the Configuration (Push Mode)
In Push mode, the administrator manually pushes configurations to target nodes. This is the simplest mode and suitable for small environments. Apply the compiled MOF to the local machine:
Start-DscConfiguration -Path "C:DSCConfigs" -Wait -Verbose -Force
The -Wait parameter keeps the command running until the configuration is fully applied. -Verbose shows detailed progress. Without -Wait, the configuration runs as a background job.
To push a configuration to a remote server:
# The MOF file must be named after the target computer
WebServerState -NodeName "WebServer01" -OutputPath "C:DSCConfigs"
# Push to the remote server
Start-DscConfiguration -Path "C:DSCConfigs" -ComputerName "WebServer01" -Wait -Verbose -Credential (Get-Credential)
Step 4: Configure the Local Configuration Manager
The LCM controls how DSC behaves on a node. Configure it using a special DSC configuration with the LocalConfigurationManager block:
Configuration LCMSettings {
Node "localhost" {
LocalConfigurationManager {
# How to apply config: ApplyOnly, ApplyAndMonitor, ApplyAndAutoCorrect
ConfigurationMode = "ApplyAndAutoCorrect"
# How often to check for drift (minutes) - requires ApplyAndMonitor or ApplyAndAutoCorrect
ConfigurationModeFrequencyMins = 30
# Refresh mode: Push or Pull
RefreshMode = "Push"
# Automatically reboot if required by a resource
RebootNodeIfNeeded = $false
# Allow the LCM to be told to apply a new configuration
AllowModuleOverwrite = $true
}
}
}
# Compile the meta-configuration
LCMSettings -OutputPath "C:DSCLCM"
# Apply the meta-configuration
Set-DscLocalConfigurationManager -Path "C:DSCLCM" -Verbose
Verify the LCM settings were applied:
Get-DscLocalConfigurationManager | Select-Object ConfigurationMode, RefreshMode, RebootNodeIfNeeded, ConfigurationModeFrequencyMins
Step 5: Set Up a DSC Pull Server
In Pull mode, nodes periodically contact a central Pull Server to check for new or updated configurations. This is the preferred approach for managing many servers. Install the DSC service on a designated server:
# Install required features on the Pull Server
Install-WindowsFeature DSC-Service, Web-Server -IncludeManagementTools
# Install the xPSDesiredStateConfiguration module (download from PSGallery or copy manually)
# For WS2012 R2 without internet, copy the module to C:Program FilesWindowsPowerShellModules
# Configure the Pull Server
Configuration PullServerConfig {
param (
[string]$NodeName = "localhost",
[string]$RegistrationKey = "5b83440d-8cc4-4e4f-8dfe-e8f23bbc5c39"
)
Import-DSCResource -ModuleName xPSDesiredStateConfiguration
Node $NodeName {
WindowsFeature DSCService {
Ensure = "Present"
Name = "DSC-Service"
}
xDscWebService PullServerEndpoint {
Ensure = "Present"
EndpointName = "DSCPullServer"
Port = 8080
PhysicalPath = "$env:SystemDriveinetpubDSCPullServer"
CertificateThumbprint = "AllowUnencryptedTraffic"
ModulePath = "$env:PROGRAMFILESWindowsPowerShellDscServiceModules"
ConfigurationPath = "$env:PROGRAMFILESWindowsPowerShellDscServiceConfiguration"
State = "Started"
RegistrationKeyPath = "$env:PROGRAMFILESWindowsPowerShellDscService"
UseSecurityBestPractices = $false
DependsOn = "[WindowsFeature]DSCService"
}
}
}
PullServerConfig -OutputPath "C:DSCPullServer"
Start-DscConfiguration -Path "C:DSCPullServer" -Wait -Verbose -Force
Step 6: Register Nodes with the Pull Server
Configure a managed node’s LCM to use the Pull Server. Each node needs a configuration ID (GUID) that maps to the MOF file stored on the pull server:
Configuration PullNodeLCM {
Node "WebServer01" {
LocalConfigurationManager {
RefreshMode = "Pull"
ConfigurationMode = "ApplyAndAutoCorrect"
ConfigurationModeFrequencyMins = 30
RefreshFrequencyMins = 30
RebootNodeIfNeeded = $false
ConfigurationID = "a3e7c4f1-2b5d-4e6f-9a1b-3c7d8e2f1a4b"
DownloadManagerName = "WebDownloadManager"
DownloadManagerCustomData = @{
ServerUrl = "http://PullServer01:8080/PSDSCPullServer.svc"
AllowUnsecureConnection = "true"
}
}
}
}
PullNodeLCM -OutputPath "C:DSCNodeLCM"
Set-DscLocalConfigurationManager -Path "C:DSCNodeLCM" -ComputerName "WebServer01" -Verbose
Step 7: Using Common DSC Resources
DSC ships with several built-in resources for common configuration scenarios. Here are practical examples using the most important ones:
Configuration ServerBaseline {
Node "localhost" {
# Registry resource - configure a registry key
Registry DisableSMBv1 {
Ensure = "Present"
Key = "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesLanmanServerParameters"
ValueName = "SMB1"
ValueData = "0"
ValueType = "Dword"
}
# WindowsProcess resource - ensure a process is or isn't running
# (typically used with Service resource instead)
Service RemoteRegistry {
Name = "RemoteRegistry"
State = "Stopped"
StartupType = "Disabled"
}
# Environment resource - set an environment variable
Environment AppPath {
Ensure = "Present"
Name = "APP_HOME"
Value = "C:ApplicationsMyApp"
}
# Script resource - run arbitrary PowerShell for complex scenarios
Script ConfigureAuditPolicy {
GetScript = { return @{ Result = (auditpol /get /category:"Logon/Logoff") } }
TestScript = { (auditpol /get /category:"Logon/Logoff") -match "Success and Failure" }
SetScript = { auditpol /set /category:"Logon/Logoff" /success:enable /failure:enable }
}
}
}
ServerBaseline -OutputPath "C:DSCBaseline"
Start-DscConfiguration -Path "C:DSCBaseline" -Wait -Verbose
Step 8: Check DSC Configuration Status
After applying configurations, verify the current state and check for any drift:
# Get the current configuration applied to this node
Get-DscConfiguration
# Test whether the node is in the desired state (returns $true if compliant)
Test-DscConfiguration -Verbose
# Get detailed status including each resource's state
Get-DscConfigurationStatus | Select-Object Status, StartDate, DurationInSeconds, NumberOfResources
Force the LCM to immediately apply the stored configuration (useful after changes):
Update-DscConfiguration -Wait -Verbose
Step 9: Managing DSC Configuration History
DSC stores a history of configuration runs on the node. Review this to audit changes and diagnose failures:
# View the last 10 configuration events
Get-DscConfigurationStatus -All | Select-Object -First 10 Status, StartDate, Type, DurationInSeconds, Error
Review DSC-related events in the Windows event log:
Get-WinEvent -LogName "Microsoft-Windows-Desired State Configuration-LCMEventSource/Operational" -MaxEvents 25 | Select-Object TimeCreated, Id, LevelDisplayName, Message
Step 10: Handle Configuration Dependencies
Use DependsOn to define the order in which DSC resources are applied. This prevents a service from starting before its prerequisite feature is installed:
Configuration OrderedConfig {
Node "localhost" {
WindowsFeature SMTP {
Ensure = "Present"
Name = "SMTP-Server"
}
WindowsFeature SMTPConsole {
Ensure = "Present"
Name = "Web-Mgmt-Console"
DependsOn = "[WindowsFeature]SMTP"
}
Service SMTPSvc {
Name = "SMTPSVC"
State = "Running"
DependsOn = "[WindowsFeature]SMTP","[WindowsFeature]SMTPConsole"
}
}
}
OrderedConfig -OutputPath "C:DSCOrdered"
Start-DscConfiguration -Path "C:DSCOrdered" -Wait -Verbose
Summary
PowerShell Desired State Configuration on Windows Server 2012 R2 provides a declarative, repeatable approach to server configuration management. By writing configuration documents that describe the desired state, compiling them to MOF files, and using either Push mode for direct application or Pull mode for scalable centralized management, administrators can enforce consistent configurations across entire server fleets. The LCM’s ApplyAndAutoCorrect mode continuously monitors for configuration drift and automatically remediates deviations, reducing the risk of configuration rot over time. DSC integrates naturally with version control systems, making server configurations as auditable and manageable as application code.