Windows Server

PowerShell DSC: Desired State Configuration for Windows

PowerShell DSC: Desired State Configuration for Windows Server

Introduction

PowerShell Desired State Configuration (DSC) enables declarative infrastructure management for Windows Server environments. Instead of writing imperative scripts that describe how to configure a server, DSC lets you declare what the configuration should be — and the DSC engine ensures the system matches that desired state, automatically correcting drift.

Introduction

This guide covers DSC fundamentals, configuration authoring, Pull Server deployment, Azure Automation DSC integration, and best practices for enterprise environments.

Prerequisites

  • Windows Server 2019/2022 with PowerShell 5.1+
  • Local Administrator privileges on target nodes
  • Understanding of PowerShell scripting basics
  • For Azure DSC: Azure subscription with Automation account

Prerequisites

DSC Architecture

DSC Architecture

Figure: Enterprise architecture – integrated components with data flow.

Architecture Overview: Configuration Authoring

Writing DSC Configurations

Web Server Configuration

Writing DSC Configurations

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

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

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

        WindowsFeature IISManagement {
            Ensure    = 'Present'
            Name      = 'Web-Mgmt-Tools'
            DependsOn = '[WindowsFeature]IIS'
        }

        WindowsFeature ASPNet45 {
            Ensure    = 'Present'
            Name      = 'Web-Asp-Net45'
            DependsOn = '[WindowsFeature]IIS'
        }

        # Configure website
        xWebsite DefaultSite {
            Ensure       = 'Present'
            Name         = 'Default Web Site'
            State        = 'Started'
            PhysicalPath = 'C:\inetpub\wwwroot'
            BindingInfo  = @(
                MSFT_xWebBindingInformation {
                    Protocol = 'HTTP'
                    Port     = 80
                }
                MSFT_xWebBindingInformation {
                    Protocol  = 'HTTPS'
                    Port      = 443
                    CertificateThumbprint = $Node.CertThumbprint


                }
            )
            DependsOn    = '[WindowsFeature]IIS'
        }

        # Security: Disable unnecessary services
        Service TelnetService {
            Name   = 'TlntSvr'
            State  = 'Stopped'
            Ensure = 'Present'
        }

        # Firewall rules
        Script ConfigureFirewall {
            SetScript = {
                New-NetFirewallRule -DisplayName "Allow HTTP" -Direction Inbound -Port 80 -Protocol TCP -Action Allow
                New-NetFirewallRule -DisplayName "Allow HTTPS" -Direction Inbound -Port 443 -Protocol TCP -Action Allow
            }
            TestScript = {
                $http = Get-NetFirewallRule -DisplayName "Allow HTTP" -ErrorAction SilentlyContinue
                $https = Get-NetFirewallRule -DisplayName "Allow HTTPS" -ErrorAction SilentlyContinue
                return ($null -ne $http -and $null -ne $https)
            }
            GetScript = { return @{ Result = "Firewall rules configured" } }
        }
    }
}

# Compile and apply
WebServerConfig -NodeName 'WebServer01' -OutputPath './WebConfig'
Start-DscConfiguration -Path './WebConfig' -Wait -Verbose -Force

Security Hardening Configuration

Configuration SecurityBaseline {
    Import-DscResource -ModuleName PSDesiredStateConfiguration
    Import-DscResource -ModuleName SecurityPolicyDsc
    Import-DscResource -ModuleName AuditPolicyDsc

    Node $AllNodes.NodeName {
        # Password policy
        AccountPolicy PasswordPolicy {
            Name                             = 'PasswordPolicy'
            Minimum_Password_Length           = 14
            Password_must_meet_complexity    = 'Enabled'
            Maximum_Password_Age             = 60
            Minimum_Password_Age             = 1
            Enforce_password_history         = 24
        }

        # Audit policy
        AuditPolicySubcategory LogonAudit {
            Name      = 'Logon'
            AuditFlag = 'Success'
            Ensure    = 'Present'
        }

        AuditPolicySubcategory LogonFailureAudit {
            Name      = 'Logon'
            AuditFlag = 'Failure'
            Ensure    = 'Present'
        }

        # Registry settings for security
        Registry DisableRemoteDesktopNLA {
            Key       = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'
            ValueName = 'UserAuthentication'
            ValueData = '1'
            ValueType = 'Dword'
            Ensure    = 'Present'
        }
    }
}

Push vs Pull Mode

Aspect Push Mode Pull Mode
Initiation Admin pushes to nodes Nodes pull from server
Scale Small environments (<50) Large environments
Setup complexity Minimal Requires Pull Server
Compliance reporting Manual Automatic
Self-healing On demand Continuous (configurable)

Push vs Pull Mode

Azure Automation DSC

Azure Automation DSC

Figure: Test Studio – recorded test cases, assertions, and execution results.

# Register a node with Azure Automation DSC
$RegistrationInfo = Get-AzAutomationRegistrationInfo -ResourceGroupName "rg-dsc" -AutomationAccountName "aa-dsc"

![Azure Automation DSC](/images/articles/windows-server/2025-10-27-powershell-dsc-desired-state-configuration-for-windows-server-sec6-workflow.jpg)


# Configure LCM on target node
[DSCLocalConfigurationManager()]
Configuration LCMConfig {
    Node 'localhost' {
        Settings {
            RefreshMode = 'Pull'
            RefreshFrequencyMins = 30
            ConfigurationMode = 'ApplyAndAutoCorrect'
            RebootNodeIfNeeded = $false
        }
        ConfigurationRepositoryWeb AzureAutomation {
            ServerURL = $RegistrationInfo.Endpoint
            RegistrationKey = $RegistrationInfo.PrimaryKey
        }
    }
}

LCMConfig -OutputPath './LCMConfig'
Set-DscLocalConfigurationManager -Path './LCMConfig' -Verbose

Best Practices

  1. Version control configurations: Store DSC configs in Git alongside your infrastructure code
  2. Use configuration data: Separate environment-specific values from configuration logic
  3. Test configurations: Use Pester tests to validate DSC resources before applying
  4. Monitor compliance: Use Azure Automation or custom reporting to detect configuration drift
  5. Modular design: Break large configurations into composites for reusability
  6. Credential management: Use certificates or Azure Key Vault — never embed passwords in configs

Best Practices

Architecture Decision and Tradeoffs

When designing server infrastructure solutions with Windows Server, consider these key architectural trade-offs:

Approach Best For Tradeoff
Managed / platform service Rapid delivery, reduced ops burden Less customisation, potential vendor lock-in
Custom / self-hosted Full control, advanced tuning Higher operational overhead and cost

Recommendation: Start with the managed approach for most workloads and move to custom only when specific requirements demand it.

Validation and Versioning

  • Last validated: April 2026
  • Validate examples against your tenant, region, and SKU constraints before production rollout.
  • Keep module, CLI, and SDK versions pinned in automation pipelines and review quarterly.

Security and Governance Considerations

  • Apply least-privilege access using RBAC roles and just-in-time elevation for admin tasks.
  • Store secrets in managed secret stores and avoid embedding credentials in scripts or source files.
  • Enable audit logging, data protection policies, and periodic access reviews for regulated workloads.

Cost and Performance Notes

  • Define budgets and alerts, then monitor usage and cost trends continuously after go-live.
  • Baseline performance with synthetic and real-user checks before and after major changes.
  • Scale resources with measured thresholds and revisit sizing after usage pattern changes.

Official Microsoft References

Public Examples from Official Sources

Key Takeaways

  • ✅ DSC enables declarative, idempotent infrastructure management for Windows Server
  • ✅ Configuration drift is automatically corrected in Pull mode with ApplyAndAutoCorrect
  • ✅ Azure Automation DSC scales management across hybrid cloud environments
  • ✅ Security baselines and compliance policies can be enforced consistently via DSC
  • ✅ Version-controlled configurations provide auditability and reproducibility

Key Takeaways

Additional Resources

AI Assistant
AI Assistant

Article Assistant

Ask me about this article

AI
Hi! I'm here to help you understand this article. Ask me anything about the content, concepts, or implementation details.