PowerShell DSC and the LCM on a Windows VPS: Configuration Drift That Stays Fixed

Configuration drift is what happens between the day you built the server and the day something stops working: a service was set to Manual by a vendor installer, a registry key was changed during a troubleshooting session, a firewall rule was added and never removed. PowerShell DSC exists to make the intended state explicit and to keep reasserting it.

On a single VPS the full pull-server architecture is overkill, but the Local Configuration Manager — the agent that actually applies configurations — is exactly the right tool. This covers how the LCM behaves, how to run push mode sensibly on one box, and what DSC will never notice for you.

How DSC and the LCM divide the work

A DSC configuration is a PowerShell script that compiles into a MOF file describing resources and their desired properties. The MOF is inert. The Local Configuration Manager is the service that reads it, compares it against the machine’s actual state, and applies the difference.

That split matters because it tells you where to look when things go wrong. If the MOF is wrong, the machine converges to the wrong state reliably. If the LCM is misconfigured, the MOF may be perfect but nothing gets applied, or gets applied on a schedule you did not intend. Most “DSC doesn’t work” reports are LCM settings, not resource bugs.

Get-DscLocalConfigurationManager | Format-List
Get-DscConfigurationStatus
Test-DscConfiguration -Detailed

The LCM settings that actually matter

Four properties control almost all behaviour. ConfigurationMode decides whether the agent only tests, applies once, or keeps re-applying. On a VPS you almost always want ApplyAndMonitor, which applies on first run and then reports drift without correcting it, or ApplyAndAutoCorrect, which actively fixes drift on every cycle.

ConfigurationModeFrequencyMins is how often the apply cycle runs; 15 to 30 minutes is sensible. RefreshFrequencyMins is how often it re-reads the MOF from its source. RebootNodeIfNeeded lets the agent restart when a resource requires it. A fifth setting, StatusRetentionTimeInDays, controls how much history you can inspect afterwards.

Setting Single-VPS value Why
ConfigurationMode ApplyAndAutoCorrect Keeps state fixed without a pull server
ConfigurationModeFrequencyMins 30 Balances responsiveness against CPU cost
RefreshFrequencyMins 30 Re-reads local MOF; no network dependency
RebootNodeIfNeeded True Lets WindowsFeature resources complete
StatusRetentionTimeInDays 30 Enough history to diagnose a drift event

Apply the settings with a meta-configuration, not by editing registry keys. The meta-config is itself a DSC configuration targeting PSDesiredStateConfiguration\Service and is compiled and applied with Set-DscLocalConfigurationManager.

Push mode on a single box, done properly

Push mode means you compile the MOF locally and call Start-DscConfiguration. There is no pull server, no SMB share, no certificates for transport. On one VPS that is the correct architecture: fewer moving parts, and the LCM still re-applies on its own schedule once the MOF is in place.

Configuration WebBaseline {
  Import-DscResource -ModuleName PSDesiredStateConfiguration
  Node 'localhost' {
    WindowsFeature IIS { Name = 'Web-Server'; Ensure = 'Present' }
    Service W3SVC { Name = 'W3SVC'; State = 'Running'; StartupType = 'Automatic' }
    File LogDir { DestinationPath = 'D:\logs'; Type = 'Directory'; Ensure = 'Present' }
  }
}
WebBaseline -OutputPath C:\DSC\WebBaseline
Start-DscConfiguration -Path C:\DSC\WebBaseline -Wait -Verbose -Force

Keep the compiled MOF under version control alongside the source script. When you change the configuration, recompile to a new folder and apply with -Force; do not hand-edit the MOF. The LCM records each apply in its status history, so you can see exactly which version ran and when.

Pull mode: when it earns its complexity

Pull mode has the node fetch its configuration from an HTTP or SMB endpoint. It exists so one source of truth can serve many nodes. On a single VPS it adds a web server, a registration key, and TLS certificate management for no operational gain.

The exception is when you already run several servers and want one place to change them. In that case, use an HTTPS pull server with a registration key, and note that the LCM must trust the pull server’s certificate — self-signed certificates need to be imported into the node’s Trusted Root store first, or every pull fails with a certificate error that reads like a network fault.

Credentials and certificates without leaking secrets

Plain-text credentials in a MOF are readable by anyone with file access. DSC encrypts them only when the MOF is encrypted with a certificate whose public key is on the authoring machine and private key is on the node. On a single VPS that means generating a self-signed certificate, exporting the public part, and referencing its thumbprint in the configuration data.

  • Never store the PFX password in the same script that compiles the MOF.
  • Restrict read access on C:\ProgramData\Microsoft\Windows\PowerShell\DSC to Administrators and SYSTEM.
  • Rotate the encryption certificate if the VPS is rebuilt from a snapshot taken before rotation.
  • Prefer PsDscRunAsCredential over embedding credentials in resource properties.

If certificate handling feels like too much for one box, the honest alternative is to keep secrets out of DSC entirely: let the resource reference a group Managed Service Account or a Windows Credential Manager entry, and manage the secret separately.

What DSC does not cover

DSC converges declared state; it does not detect anything you did not declare. That leaves real gaps on a production VPS.

It will not tell you that disk usage is at 96%, that a certificate expires in a week, that an application is throwing 500s, or that a process is consuming 100% CPU. It will not enforce a Windows Update schedule unless you model it as a resource, and the built-in resource for that is limited. It also will not notice a security regression in a setting no resource describes — which is most of them.

The practical split is DSC for what you can describe declaratively (features, services, files, registry keys, ACLs, scheduled tasks) and monitoring for everything else: performance counters, event log patterns, certificate expiry, backup success. Pair the two and drift becomes visible; rely on DSC alone and you will find out about the gaps from a customer. For the monitoring side, see our notes on Windows Server health monitoring on a VPS, and for the baseline you should be encoding as a configuration in the first place, the first-login hardening checklist for Windows VPS.

Leave a Comment