What is PowerShell Desired State Configuration?

PowerShell Desired State Configuration (DSC) is a declarative configuration management platform built into Windows PowerShell. Instead of writing procedural scripts that describe how to configure a system, DSC allows you to declare what state you want a system to be in, and PowerShell handles the implementation details.

DSC operates on a simple principle: you define the desired configuration state, and DSC ensures that target systems maintain that state. If a system drifts from the desired configuration, DSC can automatically detect and correct it.

Using Desired State Configuration (DSC) in PowerShell: Complete Guide to Infrastructure Automation

Core DSC Concepts

Resources

DSC Resources are the building blocks of DSC configurations. Each resource manages a specific aspect of system configuration, such as files, services, registry keys, or software installations. PowerShell includes built-in resources like File, Service, Registry, and WindowsFeature.

Configurations

A Configuration is a PowerShell function that defines how resources should be configured. Configurations are written in a declarative syntax and compiled into Managed Object Format (MOF) files.

Local Configuration Manager (LCM)

The LCM is the DSC engine that runs on each target node. It processes MOF files, applies configurations, and monitors system state. The LCM can operate in different modes: Push, Pull, or Push-Pull hybrid.

Using Desired State Configuration (DSC) in PowerShell: Complete Guide to Infrastructure Automation

Creating Your First DSC Configuration

Let’s create a basic DSC configuration that ensures a specific file exists with particular content:

# Define the configuration
Configuration EnsureWebConfig {
    # Input parameters for the configuration
    param (
        [string]$NodeName = 'localhost',
        [string]$FilePath = 'C:\inetpub\wwwroot\web.config'
    )
    
    # Import DSC resources
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    
    # Node block specifies target systems
    Node $NodeName {
        # File resource ensures the file exists
        File WebConfigFile {
            DestinationPath = $FilePath
            Contents = @"


    
        
            
                
            
        
    

"@
            Ensure = 'Present'
            Type = 'File'
        }
        
        # Ensure the parent directory exists
        File WebRoot {
            DestinationPath = 'C:\inetpub\wwwroot'
            Ensure = 'Present'
            Type = 'Directory'
        }
    }
}

# Compile the configuration to generate MOF file
EnsureWebConfig -OutputPath "C:\DSC\Configurations"

Output:

    Directory: C:\DSC\Configurations

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          10/22/2025  3:45 PM           2156 localhost.mof

The configuration compiles into a MOF file that contains the declarative instructions for the target system.

Applying DSC Configurations

Once you’ve compiled a configuration, apply it using the Start-DscConfiguration cmdlet:

# Apply the configuration
Start-DscConfiguration -Path "C:\DSC\Configurations" -Wait -Verbose -Force

Output:

VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply
VERBOSE: An LCM method call arrived from computer SERVER01 with user sid S-1-5-21-xxx
VERBOSE: [SERVER01]: LCM:  [ Start  Set      ]
VERBOSE: [SERVER01]: LCM:  [ Start  Resource ]  [[File]WebRoot]
VERBOSE: [SERVER01]: LCM:  [ Start  Test     ]  [[File]WebRoot]
VERBOSE: [SERVER01]:                            [[File]WebRoot] The system cannot find the path specified.
VERBOSE: [SERVER01]: LCM:  [ End    Test     ]  [[File]WebRoot]  in 0.0320 seconds.
VERBOSE: [SERVER01]: LCM:  [ Start  Set      ]  [[File]WebRoot]
VERBOSE: [SERVER01]: LCM:  [ End    Set      ]  [[File]WebRoot]  in 0.0940 seconds.
VERBOSE: [SERVER01]: LCM:  [ End    Resource ]  [[File]WebRoot]
VERBOSE: [SERVER01]: LCM:  [ Start  Resource ]  [[File]WebConfigFile]
VERBOSE: [SERVER01]: LCM:  [ Start  Test     ]  [[File]WebConfigFile]
VERBOSE: [SERVER01]: LCM:  [ End    Test     ]  [[File]WebConfigFile]  in 0.0150 seconds.
VERBOSE: [SERVER01]: LCM:  [ Start  Set      ]  [[File]WebConfigFile]
VERBOSE: [SERVER01]: LCM:  [ End    Set      ]  [[File]WebConfigFile]  in 0.0780 seconds.
VERBOSE: [SERVER01]: LCM:  [ End    Resource ]  [[File]WebConfigFile]
VERBOSE: [SERVER01]: LCM:  [ End    Set      ]
VERBOSE: Operation 'Invoke CimMethod' complete.

Working with DSC Resources

Built-in Resources

PowerShell includes numerous built-in DSC resources. Here’s an example using multiple resources to configure a web server:

Configuration WebServerConfig {
    param (
        [string]$NodeName = 'localhost'
    )
    
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    
    Node $NodeName {
        # Ensure IIS Windows Feature is installed
        WindowsFeature IIS {
            Name = 'Web-Server'
            Ensure = 'Present'
        }
        
        # Ensure IIS Management Console is installed
        WindowsFeature IISManagementConsole {
            Name = 'Web-Mgmt-Console'
            Ensure = 'Present'
            DependsOn = '[WindowsFeature]IIS'
        }
        
        # Ensure W3SVC service is running
        Service W3SVC {
            Name = 'W3SVC'
            State = 'Running'
            StartupType = 'Automatic'
            DependsOn = '[WindowsFeature]IIS'
        }
        
        # Configure default website directory
        File WebsiteContent {
            DestinationPath = 'C:\inetpub\wwwroot\index.html'
            Contents = '

DSC Configured Web Server

' Ensure = 'Present' Type = 'File' DependsOn = '[WindowsFeature]IIS' } # Set registry key for logging Registry IISLogging { Key = 'HKLM:\SOFTWARE\Microsoft\InetStp' ValueName = 'LoggingEnabled' ValueData = '1' ValueType = 'Dword' Ensure = 'Present' } } } # Compile the configuration WebServerConfig -OutputPath "C:\DSC\WebServer"

Notice the DependsOn property that establishes resource dependencies, ensuring resources are applied in the correct order.

Custom DSC Resources

You can create custom DSC resources for specialized configuration needs. Here’s a script-based custom resource:

# Create a custom resource module structure
$modulePath = "$env:ProgramFiles\WindowsPowerShell\Modules\CustomAppConfig"
$resourcePath = "$modulePath\DSCResources\CustomAppConfig"

New-Item -Path $resourcePath -ItemType Directory -Force

# Create the resource schema file
$schemaPath = "$resourcePath\CustomAppConfig.schema.mof"
@"
[ClassVersion("1.0.0"), FriendlyName("CustomAppConfig")]
class CustomAppConfig : OMI_BaseResource
{
    [Key, Description("Application name")] String AppName;
    [Write, Description("Configuration value")] String ConfigValue;
    [Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
};
"@ | Out-File -FilePath $schemaPath -Encoding ascii

# Create the resource module
$modulePath = "$resourcePath\CustomAppConfig.psm1"
@"
function Get-TargetResource {
    param (
        [Parameter(Mandatory)]
        [string]$AppName
    )
    
    $configFile = "C:\AppConfigs\$AppName.config"
    $exists = Test-Path $configFile
    
    if ($exists) {
        $content = Get-Content $configFile -Raw
        return @{
            AppName = $AppName
            ConfigValue = $content
            Ensure = 'Present'
        }
    }
    else {
        return @{
            AppName = $AppName
            ConfigValue = $null
            Ensure = 'Absent'
        }
    }
}

function Test-TargetResource {
    param (
        [Parameter(Mandatory)]
        [string]$AppName,
        
        [string]$ConfigValue,
        
        [ValidateSet('Present','Absent')]
        [string]$Ensure = 'Present'
    )
    
    $currentState = Get-TargetResource -AppName $AppName
    
    if ($Ensure -eq 'Present') {
        return ($currentState.Ensure -eq 'Present' -and $currentState.ConfigValue -eq $ConfigValue)
    }
    else {
        return ($currentState.Ensure -eq 'Absent')
    }
}

function Set-TargetResource {
    param (
        [Parameter(Mandatory)]
        [string]$AppName,
        
        [string]$ConfigValue,
        
        [ValidateSet('Present','Absent')]
        [string]$Ensure = 'Present'
    )
    
    $configFile = "C:\AppConfigs\$AppName.config"
    
    if ($Ensure -eq 'Present') {
        New-Item -Path 'C:\AppConfigs' -ItemType Directory -Force
        Set-Content -Path $configFile -Value $ConfigValue
        Write-Verbose "Configuration file created for $AppName"
    }
    else {
        if (Test-Path $configFile) {
            Remove-Item $configFile -Force
            Write-Verbose "Configuration file removed for $AppName"
        }
    }
}

Export-ModuleMember -Function *-TargetResource
"@ | Out-File -FilePath $modulePath -Encoding utf8

Configuring the Local Configuration Manager

The LCM controls how DSC operates on a node. Configure it using a meta-configuration:

[DSCLocalConfigurationManager()]
Configuration LCMConfig {
    Node localhost {
        Settings {
            # Set refresh mode to Push (default) or Pull
            RefreshMode = 'Push'
            
            # How often to check configuration (in minutes)
            RefreshFrequencyMins = 30
            
            # How often to reapply current configuration
            ConfigurationModeFrequencyMins = 15
            
            # What to do if configuration drift is detected
            # ApplyOnly, ApplyAndMonitor, or ApplyAndAutoCorrect
            ConfigurationMode = 'ApplyAndAutoCorrect'
            
            # Allow module overwrite during configuration
            AllowModuleOverwrite = $true
            
            # Reboot if needed
            RebootNodeIfNeeded = $true
            
            # Action after reboot
            ActionAfterReboot = 'ContinueConfiguration'
        }
    }
}

# Generate the meta-configuration MOF
LCMConfig -OutputPath "C:\DSC\LCM"

# Apply the LCM configuration
Set-DscLocalConfigurationManager -Path "C:\DSC\LCM" -Verbose

Output:

VERBOSE: Performing the operation "Start-DscConfiguration: SendMetaConfigurationApply" on target "MSFT_DSCLocalConfigurationManager".
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendMetaConfigurationApply
VERBOSE: An LCM method call arrived from computer SERVER01 with user sid S-1-5-21-xxx
VERBOSE: [SERVER01]: LCM:  [ Start  Set      ]
VERBOSE: [SERVER01]: LCM:  [ End    Set      ]
VERBOSE: Operation 'Invoke CimMethod' complete.

DSC Configuration Modes

Using Desired State Configuration (DSC) in PowerShell: Complete Guide to Infrastructure Automation

Push Mode

In Push mode, administrators manually push configurations to target nodes using Start-DscConfiguration. This is ideal for small environments or one-time configurations.

# Push configuration to remote computer
Start-DscConfiguration -Path "C:\DSC\Configurations" `
    -ComputerName "Server01", "Server02" `
    -Credential (Get-Credential) `
    -Wait -Verbose

Pull Mode

Pull mode is designed for enterprise environments. Nodes periodically check a pull server for configuration updates and apply them automatically.

# Configure LCM for Pull mode
[DSCLocalConfigurationManager()]
Configuration PullClientConfig {
    Node localhost {
        Settings {
            RefreshMode = 'Pull'
            RefreshFrequencyMins = 30
            ConfigurationMode = 'ApplyAndAutoCorrect'
        }
        
        ConfigurationRepositoryWeb PullServer {
            ServerURL = 'https://dscpull.contoso.com:8080/PSDSCPullServer.svc'
            RegistrationKey = 'your-registration-key-here'
            ConfigurationNames = @('WebServerConfig')
        }
        
        ReportServerWeb PullServerReports {
            ServerURL = 'https://dscpull.contoso.com:8080/PSDSCPullServer.svc'
            RegistrationKey = 'your-registration-key-here'
        }
    }
}

PullClientConfig -OutputPath "C:\DSC\PullClient"
Set-DscLocalConfigurationManager -Path "C:\DSC\PullClient" -Verbose

Advanced DSC Patterns

Parameterized Configurations

Create flexible configurations using parameters and configuration data:

Configuration EnvironmentConfig {
    param (
        [Parameter(Mandatory)]
        [string]$Environment,
        
        [Parameter(Mandatory)]
        [hashtable]$ConfigurationData
    )
    
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    
    Node $AllNodes.NodeName {
        $nodeConfig = $ConfigurationData.AllNodes | Where-Object { $_.NodeName -eq $Node.NodeName }
        
        File AppConfig {
            DestinationPath = "C:\Apps\config.json"
            Contents = @"
{
    "environment": "$Environment",
    "databaseServer": "$($nodeConfig.DatabaseServer)",
    "apiEndpoint": "$($nodeConfig.ApiEndpoint)",
    "logLevel": "$($nodeConfig.LogLevel)"
}
"@
            Ensure = 'Present'
            Type = 'File'
        }
        
        Registry EnvironmentKey {
            Key = 'HKLM:\SOFTWARE\MyApp'
            ValueName = 'Environment'
            ValueData = $Environment
            ValueType = 'String'
            Ensure = 'Present'
        }
    }
}

# Define configuration data
$configData = @{
    AllNodes = @(
        @{
            NodeName = 'WebServer01'
            DatabaseServer = 'sqlprod.contoso.com'
            ApiEndpoint = 'https://api.contoso.com'
            LogLevel = 'Warning'
        },
        @{
            NodeName = 'WebServer02'
            DatabaseServer = 'sqlprod.contoso.com'
            ApiEndpoint = 'https://api.contoso.com'
            LogLevel = 'Warning'
        }
    )
}

# Compile for production environment
EnvironmentConfig -Environment 'Production' -ConfigurationData $configData `
    -OutputPath "C:\DSC\Production"

Composite Resources

Combine multiple resources into reusable composite resources:

Configuration WebApplication {
    param (
        [Parameter(Mandatory)]
        [string]$WebsiteName,
        
        [Parameter(Mandatory)]
        [string]$ApplicationPath,
        
        [Parameter(Mandatory)]
        [string]$ApplicationPool
    )
    
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    
    # Ensure application directory exists
    File ApplicationDirectory {
        DestinationPath = $ApplicationPath
        Ensure = 'Present'
        Type = 'Directory'
    }
    
    # Ensure web.config exists
    File WebConfig {
        DestinationPath = "$ApplicationPath\web.config"
        Contents = ''
        Ensure = 'Present'
        Type = 'File'
        DependsOn = '[File]ApplicationDirectory'
    }
    
    # Configure folder permissions
    Script FolderPermissions {
        GetScript = {
            return @{ Result = (Get-Acl $using:ApplicationPath).AccessToString }
        }
        TestScript = {
            $acl = Get-Acl $using:ApplicationPath
            $permission = "IIS_IUSRS", "ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow"
            $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
            return $acl.Access | Where-Object { $_.IdentityReference -eq $accessRule.IdentityReference }
        }
        SetScript = {
            $acl = Get-Acl $using:ApplicationPath
            $permission = "IIS_IUSRS", "ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow"
            $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
            $acl.AddAccessRule($accessRule)
            Set-Acl $using:ApplicationPath $acl
        }
        DependsOn = '[File]ApplicationDirectory'
    }
}

# Use the composite resource in a configuration
Configuration DeployWebApps {
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    
    Node localhost {
        WindowsFeature IIS {
            Name = 'Web-Server'
            Ensure = 'Present'
        }
        
        WebApplication IntranetApp {
            WebsiteName = 'Intranet'
            ApplicationPath = 'C:\inetpub\wwwroot\intranet'
            ApplicationPool = 'IntranetAppPool'
            DependsOn = '[WindowsFeature]IIS'
        }
        
        WebApplication ApiApp {
            WebsiteName = 'API'
            ApplicationPath = 'C:\inetpub\wwwroot\api'
            ApplicationPool = 'ApiAppPool'
            DependsOn = '[WindowsFeature]IIS'
        }
    }
}

Testing and Validating Configurations

Test Current Configuration State

# Test if the current configuration matches desired state
Test-DscConfiguration -Verbose

Output:

VERBOSE: Perform operation 'Invoke CimMethod' with following parameters
VERBOSE: Test flag is True
VERBOSE: [SERVER01]: LCM:  [ Start  Test     ]
VERBOSE: [SERVER01]: LCM:  [ Start  Resource ]  [[File]WebConfigFile]
VERBOSE: [SERVER01]: LCM:  [ End    Resource ]  [[File]WebConfigFile]
VERBOSE: [SERVER01]: LCM:  [ End    Test     ]
VERBOSE: Operation 'Invoke CimMethod' complete.

True

Get Current Configuration Details

# Retrieve detailed configuration status
Get-DscConfiguration | Format-List

Output:

ConfigurationName    : EnsureWebConfig
DependsOn            :
ModuleName           : PSDesiredStateConfiguration
ModuleVersion        : 1.1
PsDscRunAsCredential :
ResourceId           : [File]WebConfigFile
SourceInfo           :
Contents             : ...
CreatedDate          :
DestinationPath      : C:\inetpub\wwwroot\web.config
Ensure               : Present
ModifiedDate         : 10/22/2025 3:45:00 PM
Type                 : File
PSComputerName       : localhost

Get LCM Configuration

# View LCM settings
Get-DscLocalConfigurationManager | Format-List

Output:

ActionAfterReboot              : ContinueConfiguration
AgentId                        : B5C6D8E9-F123-4567-89AB-CDEF01234567
AllowModuleOverWrite           : True
CertificateID                  :
ConfigurationDownloadManagers  : {}
ConfigurationID                :
ConfigurationMode              : ApplyAndAutoCorrect
ConfigurationModeFrequencyMins : 15
Credential                     :
DebugMode                      : {NONE}
DownloadManagerCustomData      :
DownloadManagerName            :
LCMCompatibleVersions          : {1.0, 2.0}
LCMState                       : Idle
LCMStateDetail                 :
LCMVersion                     : 2.0
MaximumDownloadSizeMB          : 500
PartialConfigurations          :
RebootNodeIfNeeded             : True
RefreshFrequencyMins           : 30
RefreshMode                    : Push
ReportManagers                 : {}
ResourceModuleManagers         : {}
SignatureValidationPolicy      : NONE
SignatureValidations           : {}
StatusRetentionTimeInDays      : 10

Troubleshooting DSC

View DSC Event Logs

# Get recent DSC operational events
Get-WinEvent -LogName "Microsoft-Windows-Dsc/Operational" -MaxEvents 20 | 
    Select-Object TimeCreated, Id, Message | 
    Format-Table -AutoSize -Wrap

Debug DSC Resources

# Enable debug mode for DSC
Set-DscLocalConfigurationManager -Path "C:\DSC\LCM" -Verbose -Force

# View detailed resource execution
$config = Get-DscConfiguration -ErrorAction SilentlyContinue
if (-not $config) {
    Write-Warning "No configuration currently applied"
}

# Check for errors
$errors = Get-WinEvent -LogName "Microsoft-Windows-Dsc/Operational" -MaxEvents 50 | 
    Where-Object { $_.LevelDisplayName -eq "Error" }

if ($errors) {
    $errors | Format-Table TimeCreated, Message -Wrap
}
else {
    Write-Host "No DSC errors found in event log"
}

Common Issues and Solutions

Configuration Not Applying:

  • Verify LCM is not in a pending state: Get-DscLocalConfigurationManager | Select-Object LCMState
  • Check for resource conflicts or missing dependencies
  • Ensure proper credentials for remote operations

Resource Not Found:

  • Verify the resource module is installed: Get-DscResource -Name ResourceName
  • Check module path and version compatibility
  • Import the resource explicitly in your configuration

MOF Compilation Errors:

  • Validate syntax in your configuration script
  • Ensure all required parameters are provided
  • Check for circular dependencies between resources

DSC Best Practices

Design Principles

  • Idempotence: Ensure configurations can be applied multiple times without adverse effects
  • Modularity: Break complex configurations into smaller, reusable components
  • Version Control: Store DSC configurations in source control systems
  • Testing: Test configurations in non-production environments first
  • Documentation: Document parameters, dependencies, and expected outcomes

Security Considerations

# Use credentials securely
Configuration SecureConfig {
    param (
        [Parameter(Mandatory)]
        [PSCredential]$ServiceCredential
    )
    
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    
    Node localhost {
        Service SecureService {
            Name = 'MyService'
            Credential = $ServiceCredential
            State = 'Running'
            StartupType = 'Automatic'
        }
    }
}

# Never hardcode credentials - use parameter or certificate-based authentication
$cred = Get-Credential
SecureConfig -ServiceCredential $cred -OutputPath "C:\DSC\Secure"

Performance Optimization

  • Use DependsOn to control execution order and reduce unnecessary checks
  • Implement proper Test-TargetResource logic to avoid redundant Set operations
  • Adjust LCM refresh frequencies based on environment needs
  • Leverage partial configurations for large-scale deployments

Real-World DSC Scenarios

Multi-Tier Application Deployment

Configuration ThreeTierApp {
    param (
        [Parameter(Mandatory)]
        [hashtable]$ConfigurationData
    )
    
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    
    Node $AllNodes.Where{$_.Role -eq 'WebServer'}.NodeName {
        WindowsFeature IIS {
            Name = 'Web-Server'
            Ensure = 'Present'
        }
        
        WindowsFeature AspNet45 {
            Name = 'Web-Asp-Net45'
            Ensure = 'Present'
        }
        
        File WebApp {
            SourcePath = '\\FileShare\WebApp'
            DestinationPath = 'C:\inetpub\wwwroot'
            Type = 'Directory'
            Recurse = $true
            Ensure = 'Present'
        }
    }
    
    Node $AllNodes.Where{$_.Role -eq 'AppServer'}.NodeName {
        WindowsFeature DotNet {
            Name = 'NET-Framework-45-Core'
            Ensure = 'Present'
        }
        
        Service AppService {
            Name = 'MyApplicationService'
            State = 'Running'
            StartupType = 'Automatic'
        }
        
        File AppConfig {
            DestinationPath = 'C:\Program Files\MyApp\config.json'
            Contents = ConvertTo-Json $Node.AppSettings
            Ensure = 'Present'
        }
    }
    
    Node $AllNodes.Where{$_.Role -eq 'Database'}.NodeName {
        WindowsFeature SQLEngine {
            Name = 'SQL-Server-Full'
            Ensure = 'Present'
        }
        
        Service MSSQLSERVER {
            Name = 'MSSQLSERVER'
            State = 'Running'
            StartupType = 'Automatic'
        }
    }
}

# Configuration data defining the architecture
$appConfigData = @{
    AllNodes = @(
        @{
            NodeName = 'WebServer01'
            Role = 'WebServer'
        },
        @{
            NodeName = 'WebServer02'
            Role = 'WebServer'
        },
        @{
            NodeName = 'AppServer01'
            Role = 'AppServer'
            AppSettings = @{
                DatabaseConnection = 'Server=DBServer01;Database=AppDB'
                CacheServer = 'redis.contoso.com'
            }
        },
        @{
            NodeName = 'DBServer01'
            Role = 'Database'
        }
    )
}

ThreeTierApp -ConfigurationData $appConfigData -OutputPath "C:\DSC\ThreeTier"

Using Desired State Configuration (DSC) in PowerShell: Complete Guide to Infrastructure Automation

DSC vs Configuration Management Alternatives

While DSC is native to Windows environments, understanding how it compares to other tools helps you choose the right solution:

  • DSC vs Ansible: DSC offers deeper Windows integration and is agentless using WinRM, while Ansible provides broader cross-platform support
  • DSC vs Chef: DSC uses declarative PowerShell syntax familiar to Windows admins, while Chef requires Ruby knowledge
  • DSC vs Puppet: DSC leverages existing Windows infrastructure, while Puppet provides more mature enterprise features and reporting
  • DSC vs Group Policy: DSC provides more granular control and better drift detection than traditional Group Policy

Integration with Azure Automation DSC

Azure Automation DSC extends on-premises DSC capabilities to the cloud:

# Register a node with Azure Automation DSC
$automationAccount = 'MyAutomationAccount'
$resourceGroup = 'MyResourceGroup'
$registrationUrl = (Get-AzAutomationRegistrationInfo -ResourceGroupName $resourceGroup `
    -AutomationAccountName $automationAccount).Endpoint
$registrationKey = (Get-AzAutomationRegistrationInfo -ResourceGroupName $resourceGroup `
    -AutomationAccountName $automationAccount).PrimaryKey

# Configure LCM for Azure Automation
[DSCLocalConfigurationManager()]
Configuration AzureAutomationConfig {
    Node localhost {
        Settings {
            RefreshMode = 'Pull'
            RefreshFrequencyMins = 30
            ConfigurationMode = 'ApplyAndMonitor'
        }
        
        ConfigurationRepositoryWeb AzureAutomation {
            ServerURL = $registrationUrl
            RegistrationKey = $registrationKey
        }
        
        ReportServerWeb AzureAutomation {
            ServerURL = $registrationUrl
            RegistrationKey = $registrationKey
        }
    }
}

AzureAutomationConfig -OutputPath "C:\DSC\Azure"
Set-DscLocalConfigurationManager -Path "C:\DSC\Azure" -Verbose

Conclusion

PowerShell Desired State Configuration provides a robust framework for managing infrastructure as code. By defining configurations declaratively, you ensure consistency across environments, reduce configuration drift, and automate complex deployment scenarios. Whether managing a handful of servers or thousands of nodes, DSC scales to meet your infrastructure automation needs.

The key to successful DSC implementation lies in understanding core concepts like resources, configurations, and the Local Configuration Manager. Start with simple configurations, leverage built-in resources, and gradually build more sophisticated solutions as your expertise grows. Combined with proper testing, version control, and monitoring, DSC becomes an invaluable tool in your DevOps toolkit.