Anatomy of a DSC Configuration

A Guide to the DSL

Tommy Becker
- Wed Nov 01 2023

In the world of PowerShell, Desired State Configuration (DSC) is the primary tool for implementing “Configuration as Code.” It allows you to define the state of a machine declaratively, and let PowerShell’s Local Configuration Manager (LCM) do the work of making it so.

Like Pester, DSC has its own Domain-Specific Language (DSL) that looks like PowerShell but has a specific structure and vocabulary. Understanding this DSL is the first step to writing robust, self-healing configurations.

Let’s break down the anatomy of a DSC configuration.

Configuration: The Blueprint

The Configuration block is the outermost container. It acts as a blueprint for the desired state of your environment. You give it a name, and inside it, you define the nodes (machines) and the resources you want to configure on them.

When you run this script block, it doesn’t execute the configuration immediately. Instead, it compiles the blueprint into one or more .mof (Managed Object Format) files. These MOF files are the actual configuration documents that the target machines will use.

Configuration MyWebApp {
    # Node and resource definitions go here
}

Node: The Target Machine

Inside a Configuration block, the Node block specifies which machine(s) you are targeting. You can target a single machine by name or IP address, or provide a comma-separated list to apply the same configuration to multiple machines.

Configuration MyWebApp {
    Node 'WebServer01', 'WebServer02' {
        # Resources for these two servers go here
    }

    Node 'DatabaseServer01' {
        # Resources for the database server go here
    }
}

Import-DscResource: Loading the Tools

Before you can use a resource, you often need to tell your configuration where to find it. Import-DscResource is used at the top of a Configuration block to load resources from installed PowerShell modules. This makes the resources available for use within your Node blocks.

Configuration MyWebApp {
    Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
    Import-DscResource -ModuleName 'xWebAdministration' # A common community module
    # ...
}

Resource Blocks: The Desired State

This is the heart of DSC. A resource block defines the state of a specific component on a node. Each resource has a type (like File, Service, WindowsFeature) and a unique name you provide.

Inside the block, you set properties that declare the state you want.

  • Ensure: The most common property. It typically accepts Present or Absent. Do you want this file/service/feature to exist or not?
  • State: For services, this can be Running or Stopped.
  • Path / DestinationPath: For files and directories.
  • DependsOn: This powerful property lets you define dependencies. For example, you can tell DSC not to configure a website until the IIS feature is installed.
# Example of a Service resource block
Service 'W3SVC' {
    Name      = 'W3SVC'   # The name of the service
    State     = 'Running' # The desired state
    Ensure    = 'Present' # The service should exist
}

Putting It All Together

Here’s a complete example that configures a simple web server. It ensures the IIS feature is installed, a web page exists with specific content, and the web service is running.

Configuration EnsureWebServer {
    # Import resources from the built-in module
    Import-DscResource -ModuleName 'PSDesiredStateConfiguration'

    Node 'WebServer01' {
        # 1. Ensure the IIS feature is installed
        WindowsFeature 'IIS' {
            Ensure = 'Present'
            Name   = 'Web-Server'
        }

        # 2. Ensure the default website content is in place
        File 'DefaultWebPage' {
            Ensure          = 'Present'
            DestinationPath = 'C:\inetpub\wwwroot\index.html'
            Contents        = '<h1>Hello, World from DSC!</h1>'
            DependsOn       = '[WindowsFeature]IIS' # Don't run this until IIS is installed
        }

        # 3. Ensure the World Wide Web Publishing Service is running
        Service 'W3SVC' {
            Name      = 'W3SVC'
            State     = 'Running'
            DependsOn = '[WindowsFeature]IIS' # Also depends on IIS
        }
    }
}

# --- Execution ---

# 1. Compile the configuration into a MOF file
EnsureWebServer -OutputPath C:\DSC_Configs

# 2. Apply the configuration to the local machine
Start-DscConfiguration -Path C:\DSC_Configs -Wait -Verbose

By using this declarative DSL, you’re no longer writing a script of how to set up a server. Instead, you’re creating a robust, readable, and idempotent blueprint of what a configured server looks like. This is a fundamental shift in thinking that leads to more reliable and maintainable infrastructure automation.