Back to Blog
3 min read

Azure Automation DSC: Desired State Configuration

Azure Automation DSC manages machine configuration declaratively. Define desired state, Azure ensures compliance—Windows and Linux servers.

DSC Configuration

# WebServerConfig.ps1
Configuration WebServerConfig
{
    param (
        [string]$NodeName = 'localhost'
    )

    Import-DscResource -ModuleName PSDesiredStateConfiguration
    Import-DscResource -ModuleName xWebAdministration

    Node $NodeName
    {
        # Ensure IIS is installed
        WindowsFeature WebServer
        {
            Ensure = 'Present'
            Name   = 'Web-Server'
        }

        WindowsFeature AspNet45
        {
            Ensure = 'Present'
            Name   = 'Web-Asp-Net45'
            DependsOn = '[WindowsFeature]WebServer'
        }

        # Create website directory
        File WebContent
        {
            Ensure = 'Present'
            Type = 'Directory'
            DestinationPath = 'C:\inetpub\mysite'
        }

        # Configure website
        xWebsite DefaultSite
        {
            Ensure = 'Present'
            Name = 'Default Web Site'
            State = 'Stopped'
            PhysicalPath = 'C:\inetpub\wwwroot'
            DependsOn = '[WindowsFeature]WebServer'
        }

        xWebsite MySite
        {
            Ensure = 'Present'
            Name = 'MySite'
            State = 'Started'
            PhysicalPath = 'C:\inetpub\mysite'
            BindingInfo = @(
                MSFT_xWebBindingInformation
                {
                    Protocol = 'HTTP'
                    Port = 80
                    HostName = 'mysite.company.com'
                }
            )
            DependsOn = '[File]WebContent', '[xWebsite]DefaultSite'
        }
    }
}

Upload to Azure Automation

# Connect to Azure
Connect-AzAccount

# Import configuration
Import-AzAutomationDscConfiguration `
    -SourcePath ".\WebServerConfig.ps1" `
    -ResourceGroupName "myRG" `
    -AutomationAccountName "my-automation" `
    -Published

Compile Configuration

# Compile with parameters
$ConfigData = @{
    AllNodes = @(
        @{
            NodeName = 'WebServer01'
            Role = 'Web'
        },
        @{
            NodeName = 'WebServer02'
            Role = 'Web'
        }
    )
}

Start-AzAutomationDscCompilationJob `
    -ConfigurationName "WebServerConfig" `
    -ConfigurationData $ConfigData `
    -ResourceGroupName "myRG" `
    -AutomationAccountName "my-automation"

Register Nodes

# Azure VM
Register-AzAutomationDscNode `
    -AzureVMName "WebServer01" `
    -AzureVMResourceGroup "myRG" `
    -NodeConfigurationName "WebServerConfig.WebServer01" `
    -ResourceGroupName "myRG" `
    -AutomationAccountName "my-automation" `
    -RebootNodeIfNeeded $true `
    -RefreshFrequencyMins 30 `
    -ConfigurationModeFrequencyMins 15 `
    -ConfigurationMode "ApplyAndAutoCorrect"

On-Premises Registration

# Generate registration key
$regInfo = Get-AzAutomationRegistrationInfo `
    -ResourceGroupName "myRG" `
    -AutomationAccountName "my-automation"

# On the target machine
[DscLocalConfigurationManager()]
Configuration LCMConfig
{
    Node localhost
    {
        Settings
        {
            RefreshMode = 'Pull'
            RefreshFrequencyMins = 30
            ConfigurationModeFrequencyMins = 15
            ConfigurationMode = 'ApplyAndAutoCorrect'
            RebootNodeIfNeeded = $true
        }

        ConfigurationRepositoryWeb AzureAutomation
        {
            ServerUrl = $regInfo.Endpoint
            RegistrationKey = $regInfo.PrimaryKey
            ConfigurationNames = @('WebServerConfig.localhost')
        }
    }
}

LCMConfig
Set-DscLocalConfigurationManager -Path .\LCMConfig

Check Compliance

# Get node status
Get-AzAutomationDscNode `
    -ResourceGroupName "myRG" `
    -AutomationAccountName "my-automation" |
    Select-Object Name, Status, LastSeen

# Get compliance report
Get-AzAutomationDscNodeReport `
    -ResourceGroupName "myRG" `
    -AutomationAccountName "my-automation" `
    -NodeId "node-guid" |
    Select-Object Status, StartTime, ReportFormatVersion

Linux Configuration

Configuration LinuxWebServer
{
    Import-DscResource -ModuleName nx

    Node 'LinuxServer01'
    {
        nxPackage nginx
        {
            Name = 'nginx'
            Ensure = 'Present'
            PackageManager = 'apt'
        }

        nxService nginxService
        {
            Name = 'nginx'
            State = 'running'
            Enabled = $true
            DependsOn = '[nxPackage]nginx'
        }

        nxFile webRoot
        {
            DestinationPath = '/var/www/html/index.html'
            Contents = '<html><body>Hello from DSC!</body></html>'
            Ensure = 'Present'
            Type = 'File'
            Owner = 'www-data'
        }
    }
}

DSC: configuration as code for infrastructure compliance.

Michael John Peña

Michael John Peña

Senior Data Engineer based in Sydney. Writing about data, cloud, and technology.