Want to Automatically Configure Your Machines Using DSC at Initial Boot-up?

Want to Automatically Configure Your Machines Using DSC at Initial Boot-up?

Rate This
  • Comments 19

Often times, IT Pros want to automate software installation and configuration upon a machine’s initial boot-up. This blog will walk you through how to use Windows PowerShell Desired State Configuration (DSC) to do this. We will show you how to prepare and inject DSC configurations into your bootable media (such as VHDs), so that they are executed during the initial boot-up process. We will discuss three approaches to this process, and give a VHD example for each one.

Prerequisites:

  • Windows Server 2012 R2 with update KB2883200You can use Get-HotFix -Id KB2883200 to check whether it's installed.

Option 1 – Inject a DSC configuration (.ps1) into a VHD

Our first approach will be to inject a .ps1 with a DSC configuration directly into a VHD. This approach leverages “Unattended Windows Setup” to automatically run an inserted configuration. For information about running Windows Setup, see the reference here.

  • First, we need to write a configuration to inject. This configuration will be run when the machine boots up. For example, this sample configuration ensures that IIS is installed. Note: feel free to replace this configuration with your own. The xComputer page has more samples for common tasks including renaming your computer, joining a domain, etc.

 

powershell -c {

    configuration SampleIISInstall

    {

        node ("localhost")

        {

            WindowsFeature IIS

            {

                Ensure = "Present"

                Name = "Web-Server"                      

            }

        }

    }

  

    # Compile the configuration file to a MOF format

    SampleIISInstall

 

    # Run the configuration on localhost

    Start-DscConfiguration -Path .\SampleIISInstall -ComputerName localhost -Wait -Force -Verbose

}

 

  • Save the above to SampleIISInstall.ps1. This file will be injected to your bootable VHD.
  • Next, we need to create a unattend.xml file. Below is a snippet from a sample unattend.xml (the whole document is attached at the bottom of this blog). Under the “specialize” pass, a part of Windows installation, the RunSynchronous command gets invoked. In turn a command file (in this case RunDSC.cmd) is called.

<settings pass="specialize">

        <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" …>

            <RunSynchronous>

                <RunSynchronousCommand>

                    <Order>1</Order>

                    <Path>%SystemDrive%\DSC\RunDSC.cmd</Path>

                </RunSynchronousCommand>

            </RunSynchronous>

        </component>

</settings>

  • The content of RunDSC.cmd looks something like the following. It uses Windows Task Scheduler to schedule a task that invokes SampleIISInstall.ps1.

schtasks.exe /Create /SC ONSTART /TN "\Microsoft\Windows\Desired State Configuration\DSCRestartBootTask" /RU System /F /TR "PowerShell.exe -ExecutionPolicy RemoteSigned -File c:\dsc\SampleIISInstall.ps1"

  • We have all necessary files ready. Now inject SampleIISInstall.ps1, RunDSC.cmd, and unattend.xml to the VHD. In our case, unattend.xml is copied under root directory while SampleIISInstall.ps1 and RunDSC.cmd are put under %SystemDrive%\DSC. If you boot up from the VHD, or create a VM from the VHD, you will see that IIS gets installed at first boot-up.

Option 2 – Inject a compiled DSC configuration (.mof) into a VHD

Imagine we need to customize the installation for large-scale rollouts so that we achieve consistency in the configuration of each target node. The method described in Option 1 does not seem to be efficient; it requires the compilation of the DSC configuration on each node. In the following approach, we inject an already compiled configuration into the VHD.

There are two ways to inject a complied DSC configuration to VHD. Let’s go through them.

2.1 Inject a DSC configuration (.mof) document

  • To generate a compiled configuration, let’s compile the above SampleIISInstall configuration. A localhost.mof file is generated after the compilation as below:

PS C:\> SampleIISInstall

 

 

    Directory: C:\SampleIISInstall

 

 

Mode       LastWriteTime            Length Name

----       -------------            ------ ----

-a---      2/14/2014   4:12 PM      1086   localhost.mof

 

  • Copy the localhost.mof to pending.mof.
  • Make sure you inject the pending.mof to your VHD under the DSC Local Configuration Manager (LCM) dedicated folder: %systemdrive%\Windows\System32\Configuration.
  • As in Option 1, we will use a unattend.xml. As before, the unattend.xml will invoke a command like RunDSC.cmd.
  • The content of RunDSC.cmd should look something like the following. It schedules a task:

schtasks.exe /Create /SC ONSTART /TN "\Microsoft\Windows\Desired State Configuration\DSCRestartBootTask" /RU System /F /TR "PowerShell.exe -NonInt -Command 'Invoke-CimMethod -Namespace root/Microsoft/Windows/DesiredStateConfigurationClassName MSFT_DSCLocalConfigurationManager -MethodName PerformRequiredConfigurationChecks -Arg @{Flags = [System.UInt32]3 }'"

The above process will make localhost.mof the pending configuration in the LCM. The scheduled task then tells the LCM to process the pending configuration (“Flag 3” means to apply the configuration). Through this mechanism, localhost.mof will be applied.

2.2 Inject a “meta-configuration” to download a document

In the above we discussed how to apply configurations using the “push model” of DSC. That is to say, we “pushed” the configuration onto the machine. We can also leverage the “pull model” of DSC to apply a configuration. To do this, we must configure the node to “pull” it’s configuration from a DSC “pull server” and then apply it. We do this by configuring the Local Configuration Manager with a “meta-configuration.”

We describe the steps as below:

1. Deploy your configuration files to the pull server (see this blog for more information)

  • Copy the localhost.mof created in Option 2.1 to 43d4995d-3199-4e0d-aef5-d52d3b681ac4.mof
  • Run “New-DSCCheckSum” to generate 43d4995d-3199-4e0d-aef5-d52d3b681ac4.mof.checksum.
  • Copy the above two files to your pull server under the following folder: $env:programfiles\WindowsPowerShell\DSCService\Configuration.

Now we have the configuration files ready on the pull server. Next, we will create a DSC meta-configuration to be injected to the VHD.

2. Prepare the meta-configuration for target node

Configuration SampleConfiguration

{

    Node "localhost"

    {

        LocalConfigurationManager

        {   

            ConfigurationID ="43d4995d-3199-4e0d-aef5-d52d3b681ac4";          

            DownloadManagerName ="WebDownloadManager";

            DownloadManagerCustomData = @{ ServerUrl="http://Pullserver:8080/PSDSCPullServer/PSDSCPullServer.svc" ; AllowUnsecureConnection= "True"}

            RefreshMode ="PULL";

            ConfigurationMode ="ApplyAndAutoCorrect";

            RebootNodeIfNeeded = $true;

            RefreshFrequencyMins = 15;

            ConfigurationModeFrequencyMins = 30;

        }

    }

}

 

  • After compiling the above meta configuration, you will see a localhost.meta.mof file is generated. The content of localhost.meta.mof looks like below:

instance of MSFT_KeyValuePair as $keyvaluepair1

{

    key = "ServerUrl";

    value = "http://pullserver:8080/PSDSCPUllServer/PSDSCPullServer.svc";

};

 

 

instance of MSFT_KeyValuePair as $keyvaluepair2

{

    key = "AllowUnsecureConnection";

    value = "true";

};

 

 

instance of MSFT_DSCMetaConfiguration

{

      ConfigurationID ="43d4995d-3199-4e0d-aef5-d52d3b681ac4";

      RefreshMode ="PULL";

      ConfigurationMode ="ApplyAndAutoCorrect";

      DownloadManagerName ="WebDownloadManager";

      DownloadManagerCustomData = {$keyvaluepair1,$keyvaluepair2};

      RebootNodeIfNeeded = True;

      RefreshFrequencyMins = 15;

      ConfigurationModeFrequencyMins = 30;

};

 

  • Rename the localhost.meta.mof as metaconfig.mof and inject it to your VHD under the %systemdrive%\Windows\System32\Configuration folder. Please note your metaconfig.mof should only contain MSFT_DSCMetaConfiguration and MSFT_KeyValuePair instances. You may need to manually remove OMI_ConfigurationDocument if it exists.
  • The rest of the steps regarding unattend.xml and RunDSC.cmd are similar to what we mentioned in Option 2.1.

In this post, we discussed three approaches for DSC configuration installation during the initial boot up. You may follow these instructions to prepare your DSC configurations, unattend.xml, and command files. Once you have these files ready, you can use the xVhdFileDirectory samples from this site to inject them into your VHD. After that, you can create a VM from the VHD. If you do so, you will see that IIS is installed (or being installed as installing IIS takes time) when you log on to the VM.


Thanks,
Jianyun Tao
Microsoft Corporation

Attachment: unattend.xml
Leave a Comment
  • Please add 3 and 8 and type the answer here:
  • Post
  • Looks great. Did you forget to attach the unattend.xml to the post?

  • Elijah, Thanks for pointing that out. We have fixed this issue.

  • sounds great

    i know ill be very happy with the wat my labtop performs

  • Very useful info. Thanks.

  • Hello!  Regarding option #1, could you add the *.cmd file to the c:\windows\setup\scripts\setupcomplete.cmd file to have it run during setup rather than injecting a new unattend.xml?

  • Bob, you can add your *.cmd to SetupComplete.cmd to have it run after Windows Setup. This is another way to do it.

  • Very Useful!

  • Very Useful!

  • This has got to be one of the longest commands I've seen.  I'd hate to have to type it often!

    schtasks.exe /Create /SC ONSTART /TN "\Microsoft\Windows\Desired State Configuration\DSCRestartBootTask" /RU System /F /TR "PowerShell.exe -NonInt -Command 'Invoke-CimMethod -Namespace root/Microsoft/Windows/DesiredStateConfiguration –ClassName MSFT_DSCLocalConfigurationManager -MethodName PerformRequiredConfigurationChecks -Arg @{Flags = [System.UInt32]3 }'"

    This doesn't seem very simple to implement.

  • Good article. Just a couple questions:

    1. You've set  RefreshFrequencyMins = 1; Can we really set this value to 1 min ?

    2. Can you please mention and/or point me to the min values for RefreshFrequencyMins and ConfigurationModeFrequencyMins parameters.

  • Thank you Juris for finding the bug in my example. It has been updated now to 15 mins. The minimum value of RefreshFrequencyMins is 15 minutes. If you set it to any number < 15,  for example 12 minutes, the system will set it to 15 minutes instead. The minimum value of ConfigurationModeFrequencyMins is 30 minutes. You can find more info at technet.microsoft.com/.../dn249922.aspx  and this blog: blogs.msdn.com/.../understanding-meta-configuration-in-windows-powershell-desired-state-configuration.aspx .

  • Can you also explain a bit why exactly those minimal values have been chosen and why I can' lower them at least in my development environment, cause it's not very handy when you're writing resources/configuration and constantly pushing things out to pull server you have to wait up-to 30 min. I definitely agree, that lowering those values for production environment can have performance/other impact, but in labs this will allow test all stack much faster.

    Thanks in advance.

  • Yuris, you can rerun your task in your task scheduler (see 2.1 in this doc) or run “'Invoke-CimMethod -Namespace root/Microsoft/Windows/DesiredStateConfiguration –ClassName MSFT_DSCLocalConfigurationManager -MethodName PerformRequiredConfigurationChecks -Arg @{Flags = [System.UInt32]3” from the PowerShell console to force the target node to download a new configuration from the pull server and apply it.

  • I knew that. I've already used this approach. Anyway thanks for info.

  • sysprep seems to invalidate the private key of the certificate used to nu-encrypt the password so once DSC reaches the first MSFT_Credential it throws an error about missing keys.

Page 1 of 2 (19 items) 12