How to Configure PowerShell DSC for Configuration Management on Windows Server 2012 R2
PowerShell Desired State Configuration (DSC) is Microsoft’s built-in configuration management framework that allows you to define the intended state of a Windows system declaratively and have the system automatically enforce that state. On Windows Server 2012 R2, DSC is powered by the Local Configuration Manager (LCM), a component of the Windows Management Framework 4.0 that is built into the operating system. DSC integrates tightly with Group Policy, SCCM, Azure Automation, and third-party tools like Ansible, making it a foundational building block for configuration management in Windows-centric environments. This guide covers the complete DSC workflow: writing configurations, compiling them to MOF files, pushing and pulling configurations, configuring the LCM, and implementing drift remediation.
Prerequisites
- Windows Server 2012 R2 with PowerShell 4.0 (included by default)
- Local administrator access
- For pull server scenarios: a second WS2012 R2 server to act as the DSC pull server
- NuGet provider for installing DSC resources from the PowerShell Gallery (optional but recommended)
Step 1: Verify DSC Availability
DSC is built into PowerShell 4.0 on WS2012 R2. Verify the LCM is functional:
Get-DscLocalConfigurationManager
Key fields to note: ConfigurationMode (default is ApplyAndMonitor), RefreshMode (Push or Pull), and LCMState (should be Idle for a ready system). If the command is not recognized, ensure Windows Management Framework 4.0 is installed.
Step 2: Write Your First DSC Configuration
A DSC configuration is a PowerShell script block decorated with the Configuration keyword. It defines what resources should be in what state on one or more target nodes. Create a basic configuration file:
Configuration BaselineWebServer {
param (
[string[]]$ComputerName = "localhost"
)
Node $ComputerName {
# Ensure IIS is installed
WindowsFeature IIS {
Name = "Web-Server"
Ensure = "Present"
}
# Ensure ASP.NET 4.5 is installed
WindowsFeature ASPNET45 {
Name = "Web-Asp-Net45"
Ensure = "Present"
DependsOn = "[WindowsFeature]IIS"
}
# Ensure the IIS service is running
Service W3SVC {
Name = "W3SVC"
State = "Running"
StartupType = "Automatic"
DependsOn = "[WindowsFeature]IIS"
}
# Ensure a standard directory exists
File AppDirectory {
DestinationPath = "C:AppsWebRoot"
Type = "Directory"
Ensure = "Present"
}
# Disable SMBv1 via registry
Registry DisableSMBv1 {
Key = "HKLM:SYSTEMCurrentControlSetServicesLanmanServerParameters"
ValueName = "SMB1"
ValueData = "0"
ValueType = "Dword"
Ensure = "Present"
}
# Ensure Windows Firewall service is running
Service MPSSvc {
Name = "MpsSvc"
State = "Running"
StartupType = "Automatic"
}
}
}
# Compile the configuration to a MOF file
BaselineWebServer -ComputerName "localhost" -OutputPath "C:DSCConfigsBaselineWebServer"
Save this script as C:DSCScriptsBaselineWebServer.ps1 and execute it:
New-Item -ItemType Directory -Path "C:DSCScripts","C:DSCConfigs" -Force
Set-ExecutionPolicy RemoteSigned -Force
. "C:DSCScriptsBaselineWebServer.ps1"
This compiles the configuration and produces a MOF file at C:DSCConfigsBaselineWebServerlocalhost.mof. The MOF (Managed Object Format) file is the compiled form of the configuration that the LCM applies.
Step 3: Apply the Configuration (Push Mode)
In push mode, you manually send the configuration to the target node. For local application:
Start-DscConfiguration -Path "C:DSCConfigsBaselineWebServer" -Wait -Verbose -Force
The -Wait flag keeps the shell occupied until the configuration run completes. The -Verbose flag prints each resource action as it executes. The -Force flag applies the configuration even if the LCM is currently in a non-idle state.
To push a configuration to a remote node:
Start-DscConfiguration -Path "C:DSCConfigsBaselineWebServer" -ComputerName "webserver01.domain.local" -Credential (Get-Credential) -Wait -Verbose
Step 4: Configure the Local Configuration Manager
The LCM controls how and when configurations are applied. Create a meta-configuration to set the LCM to automatically re-apply the configuration and correct any configuration drift:
Configuration ConfigureLCM {
Node "localhost" {
LocalConfigurationManager {
ConfigurationMode = "ApplyAndAutoCorrect"
ConfigurationModeFrequencyMins = 30
RebootNodeIfNeeded = $false
RefreshMode = "Push"
AllowModuleOverWrite = $true
}
}
}
ConfigureLCM -OutputPath "C:DSCLCM"
Set-DscLocalConfigurationManager -Path "C:DSCLCM" -Verbose
ApplyAndAutoCorrect mode means the LCM will check the current state against the desired state every 30 minutes and correct any drift it finds. ApplyAndMonitor (the default) checks but does not correct; ApplyOnly applies once and never checks again.
Step 5: Test Configuration Compliance
Check whether the system is currently in the desired state without making any changes:
Test-DscConfiguration -Verbose
This returns True if all resources are in compliance, or False if any drift is detected. To get a detailed compliance report:
$result = Test-DscConfiguration -Detailed
$result.ResourcesInDesiredState | Select-Object ResourceId, InDesiredState
$result.ResourcesNotInDesiredState | Select-Object ResourceId, InDesiredState
Step 6: Install Additional DSC Resource Modules
The built-in DSC resources cover basic Windows features, files, services, and registry. For more advanced scenarios, install community resource modules. On WS2012 R2, the PackageManagement (formerly OneGet) module from WMF 5 is not available natively, so download modules manually or use NuGet directly:
# Download xWebAdministration module for IIS management via DSC
Invoke-WebRequest -Uri "https://www.powershellgallery.com/api/v2/package/xWebAdministration/3.3.0" -OutFile "C:TempxWebAdministration.nupkg"
# Rename to zip and extract
Rename-Item "C:TempxWebAdministration.nupkg" "C:TempxWebAdministration.zip"
[System.IO.Compression.ZipFile]::ExtractToDirectory("C:TempxWebAdministration.zip","C:TempxWebAdministration")
# Copy to PowerShell module path
$ModulePath = "$env:ProgramFilesWindowsPowerShellModulesxWebAdministration"
New-Item -ItemType Directory -Path $ModulePath -Force
Copy-Item "C:TempxWebAdministration*" $ModulePath -Recurse -Force
Step 7: View Configuration History and Status
# Get current configuration status
Get-DscConfigurationStatus
# Get history of all configuration runs
Get-DscConfigurationStatus -All | Select-Object Status, StartDate, Type, Mode | Format-Table -AutoSize
# Get the last applied configuration
Get-DscConfiguration | Format-List
Step 8: Remove or Reset DSC Configuration
To remove the current configuration and reset the LCM to a clean state:
Remove-DscConfigurationDocument -Stage Current,Pending,Previous -Force
Stop-DscConfiguration -Force
Start-Sleep -Seconds 5
Set-DscLocalConfigurationManager -Path "C:DSCLCM" -Verbose
Step 9: Create a Compliance Report Script
Automate compliance reporting across multiple servers and output results to a CSV:
$servers = @("server01","server02","server03")
$cred = Get-Credential
$results = foreach ($server in $servers) {
try {
$status = Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock {
$dscStatus = Get-DscConfigurationStatus -ErrorAction SilentlyContinue
$lcm = Get-DscLocalConfigurationManager
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
LCMState = $lcm.LCMState
ConfigMode = $lcm.ConfigurationMode
LastStatus = $dscStatus.Status
LastRun = $dscStatus.StartDate
Compliant = ($dscStatus.Status -eq "Success")
}
}
$status
} catch {
[PSCustomObject]@{
ComputerName = $server
LCMState = "Unreachable"
ConfigMode = "N/A"
LastStatus = "Error: $_"
LastRun = $null
Compliant = $false
}
}
}
$results | Export-Csv "C:ReportsDSC-Compliance-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
$results | Format-Table -AutoSize
Summary
PowerShell DSC on Windows Server 2012 R2 provides a native, agentless configuration management capability built directly into the operating system. You have written a DSC configuration covering Windows features, services, registry settings, and file system structure; compiled it to MOF format; applied it locally and remotely; configured the LCM for automatic drift correction; tested configuration compliance; and built compliance reporting tooling. DSC integrates seamlessly with the rest of the Windows Server toolchain and serves as the foundation for advanced configuration management scenarios including SCCM integration and Azure Automation DSC.