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 {
configurationSampleIISInstall
{
node ("localhost")
{
WindowsFeatureIIS
{
Ensure ="Present"
Name ="Web-Server"
}
}
}
# Compile the configuration file to a MOF format
SampleIISInstall
# Run the configuration on localhost
Start-DscConfiguration-Path.\SampleIISInstall-ComputerNamelocalhost-Wait-Force-Verbose
}
- Save the above to SampleIISInstall.ps1. This filewill 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 -ExecutionPolicyRemoteSigned -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/DesiredStateConfiguration–ClassNameMSFT_DSCLocalConfigurationManager -MethodNamePerformRequiredConfigurationChecks -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
- Create a meta-configuration. The following is a sample meta-configuration. It instructs the LCM to download a configuration file: 43d4995d-3199-4e0d-aef5-d52d3b681ac4.mof from the pull server via the URL http://pullserver:8080/PSDSCPUllServer/PSDSCPullServer.svc. For information about meta-configuration, please refer to this blog.
ConfigurationSampleConfiguration
{
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=1;
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 = 1;
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