PowerShell Script to build your Nano Server Image

This script is now retired! It has been replaced with the NanoServerImageGenerator.psm1 module on the latest Windows Server Technical Preview media. See Getting Started with Nano Server for instructions.

 

Update

We’ve modified the script to ask for a SecureString as a means of accepting a password, as opposed to plain-text input. Instead of specifying a password string in the parameter list, the script will now prompt for a password securely. This follows more closely the security guidelines for PowerShell scripts and secure handling of credentials. Having said that, it is important to keep in mind that the mechanism via which the Administrator account’s password is set is still an Unattend.xml file. This means that the password for the Administrator account is stored in it, in plain-text, in the %WINDIR%\Panther directory after the script is finished. The password will remain there, in plain-text, until the first boot, when Nano Server will process the Unattend.xml file and delete the password from it.

Nano Server Image Manipulation

For our next installment in this series, we’re happy to announce a script that automates the customization of Nano Server images. This new PowerShell script allows you to convert a Nano Sever WIM image into a VHD disk, add packages to it, drivers and set configuration options. In this post, we’ll explore the script and what you can do with it.

Getting Started

First and foremost, the script is available for download as an attachment to this blog post. You will also need a companion script, which is available here (TechNet). Place these two scripts in the same directory and fire up PowerShell as administrator. Next, change directory into the folder where you’ve placed the scripts and dot-source the NanoServer.ps1 script:

. .\NanoServer.ps1

This will instruct PowerShell to read the contents of NanoServer.ps1 and allow access to its functionality within the current session. You’re now all set! The script ships with its own help, which you may access at any time (you may omit the window, of course):

Get-Help New-NanoServerImage -ShowWindow

First Steps

Let’s begin with a simple example. Suppose you have your Nano Server installation media on a network share and would like to create an image with a given computer name, the Hyper-V guest drivers as well as have Nano Server print its IP configuration to the screen on every boot. Here is how you can achieve that using the script:

. .\Nano.ps1

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\FirstSteps
-ComputerName FirstStepsNano
-GuestDrivers
-EnableIPDisplayOnBoot

The script will proceed as follows:

  1. Prompt for the Administrator password

  2. Copy the installation media from \\Path\To\Media\en_us into .\Base

  3. Convert the WIM image into a VHD

  4. Copy that VHD into .\FirstSteps

  5. Set that image’s administrator password as specified

  6. Set that image’s computer name to FirstStepsNano

  7. Install the Hyper-V guest drivers

  8. Make that image display the output of ipconfig on every boot.

The resulting image will be .\FirstSteps\FirstSteps.vhd. In addition, the script generates a log every time it runs; the script will let you know where it has placed it when it finishes. Similarly, since the WIM to VHD conversion is performed by the companion script, its own log can be found in %TEMP%\Convert-WindowsImage\<GUID> (where GUID is a unique identifier per conversion session). Lastly, when you run the script, assuming you always use the same base path, the conversion from WIM to VHD will occur only once. Further invocations of the script make copies of that VHD, so you can create as many custom images as necessary without having to wait for the conversion each time (unless the source WIM changes). Also, if your media does not change from invocation to invocation, you may omit the media path; the script will automatically make use of the files already present in the base path.

Including Workloads

Nano Server ships with several packages that enable additional functionality, such as acting as a Hyper-V host or as a storage server. With the new PowerShell script, these packages are easy to install. For instance, let’s inject the Hyper-V guest drivers and the storage package into a Nano Server image:

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\IncludingWorkloads
-GuestDrivers
-Storage

In this case, the script will include the two specified packages as well as their corresponding language packages. These ship in the installation media in a subfolder whose name corresponds to the locale of the image, such as en_us, tr_tr, etc. By default, the script will attempt to install the language packages corresponding to the locale of the administrator account. So if your locale is fr_fr but are operating on a Swedish image, sv_se, the script will exit reporting that the French France packages are not there. To tell the script to use a different language, all you need to do is:

New-NanoServerImage
<...>
-Language sv_se

Package Support

Here is a list of the switches and the corresponding workload packages:

-Storage

File Server role and other storage components

-Compute

Hyper-V Role

-Clustering

Failover Clustering

-OEMDrivers

Variety of network and storage controller drivers.

-GuestDrivers

Drivers for running Nano Server as a Hyper-V virtual machine.

-ReverseForwarders

Reverse forwarders allow you to run some software on Nano Server that is not explicitly made for Nano Server.

Extra Packages

If you happen to have additional packages that you would like to include in your Nano Server image, you may use the following syntax:

New-NanoServerImage
<...>
-ExtraPackages .\Extras\Pack1.cab, .\Extras\Pack2.cab, .\Extras\ru_ru\LangPack1.cab

In the case of extra packages, the script will not attempt to install corresponding language packages. Thus, if you have language packages, remember to include them explicitly in the list, too. Also, make sure that the extra language packages that you install are the same language as the workload packages; the script won’t check.

Joining Domains

The script provides two ways of joining a domain. Both of them rely on offline domain provisioning, but the difference lies in the collection of the domain join blob. Let’s try an example where you’d like to join a Nano Server machine to a domain and see what happens:

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\JoiningDomainsHarvest
-ComputerName JoiningDomainsHarvest
-DomainName Contoso

For this command, the script will proceed as follows with regards to domain provisioning:

  1. Harvest the domain join blob for the Contoso domain from the local machine (the local machine must be joined to the Contoso domain)

  2. Perform an offline provisioning of the image using that blob.

At the end of this operation, you will see that a computer named JoiningDomainsHarvest has appeared in your Active Directory computer list.

If you want to run the script on a computer that is not joined to the Contoso domain, you may harvest the blob on a machine that is, and tell the script to use that blob instead:

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\JoiningDomainsNoHarvest
-DomainBlobPath .\Path\To\Domain\Blob\JoiningDomainsNoHarvestContoso.djoin

To harvest a domain provisioning blob, you may use the following command:

djoin
/Provision
/Domain Contoso
/Machine JoiningDomainsNoHarvest
/SaveFile JoiningDomainsNoHarvest.djoin

Bear in mind that if you harvest a provisioning blob from another machine, you will have already included the computer name in it. Hence, if you try to add the computer name parameter to the script, it will report the error and exit.

Reusing Nodes

In the case that you already have a node with the same computer name as your future Nano Server image and don’t want to have to delete the name from Active Directory, you may have the script reuse it:

New-NanoServerImage
<...>
-ReuseDomainNode

Injecting Drivers

Since Nano Server has no local facility to install drivers, it would be horrible if your exotic network adapter wasn’t supported. In order to include drivers of your choosing into a Nano Server image, you may use the following syntax:

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\InjectingDrivers
-DriversPath .\Extra\Drivers

The script will scout the directory for available drivers, recursively if necessary, and inject them into your image. In the folder where you keep your drivers, you will need the SYS files for the drivers as well as the corresponding INF files. You can have a look at an existing Windows installation under %WINDIR%\System32\DriverStore\FileRepository for inspiration. Note that Nano Server only supports 64-bit drivers, and they must be signed.

Connecting over WinRM

If you need to connect to your Nano Server computer over WinRM from a machine that is not in the same subnet, you will need to explicitly open port 5985 for inbound TCP traffic on the Nano Server image. The script helps you with that:

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\ConnectingOverWinRM
-EnableRemoteManagementPort

Bring your own VHD

In the case that you already have a VHD image that you would like to customize, you may have the script use it with the following syntax:

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\BYOVHD
-ExistingVHDPath .\MyImage.vhd

With this command, the script will behave the same way, but instead of converting the original WIM to a VHD, or using the VHD that it may have already converted in a previous invocation, it will use the VHD image that you specify.

Emergency Management Services

To enable EMS on a Nano Server image, all you need is:

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\EnablingEMS
-EnableEMS
-EMSPort 3
-EMSBaudRate 9600

This command will enable EMS on serial port 3 with a baud rate of 9600 bps. The port and baud rate parameters are optional, so if you don’t include them, they will be port 1 and 115200 bps respectively.

Kernel Debugging

In the hopes that you will never have to debug a live kernel, this section goes last. If you ever find yourself needing to do so, however, the script allows you to configure that option, too. There are four ways to debug a live kernel remotely: via serial port, over the network, 1394 (FireWire) and USB. If you need more information, please refer to this page. Let’s now have a look at each option.

Debugging over Serial Port

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\KernelDebuggingSerial
-DebugMethod Serial
-DebugCOMPort 1
-DebugBaudRate 9600

As you’d expect, this command will enable serial debugging over port 2 with a baud rate of 9600 bps. As with EMS, the port and baud rate parameters are optional, and they are port 2 and 115200 bps by default. Bear in mind that if you enable both EMS and Kernel Debugging on the same image, you will need two different serial ports.

Debugging over the Network

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\KernelDebuggingNetwork
-DebugMethod Net
-DebugRemoteIP 192.168.1.100
-DebugPort 64000

This command will enable kernel debugging over the network and the only computer that can connect has 192.168.1.100 as its IP address. In addition, all communications will take place over port 64000. Both the IP and port parameters are mandatory, and the port number must be 49152 or higher. Moreover, since kernel debugging over the network is susceptible to interception, communication must be encrypted. When configuring kernel debugging on an image, the script automatically generates a key that you will need in order to connect. The script will place that key in a file next to the resulting VHD, and it will tell you about it when it finishes.

If you want to use your own key, you can use the -DebugKey parameter, as follows:

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\KernelDebuggingNetwork
-DebugMethod Net
-DebugRemoteIP 192.168.1.100
-DebugPort 64000
-DebugKey 1.2.3.4

Debugging over 1394 (FireWire)

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\KernelDebuggingFireWire
-DebugMethod 1394
-DebugChannel 3

This command will enable 1394 (FireWire) debugging and you will have to connect the remote debugger on channel 3. The channel parameter is mandatory.

Debugging over USB

New-NanoServerImage
-MediaPath \\Path\To\Media\en_us
-BasePath .\Base
-TargetPath .\KernelDebuggingUSB
-DebugMethod USB
-DebugTargetName KernelDebuggingUSBNano

This command will enable debugging over USB. When you attempt to connect the remote debugger to the computer running the resulting image, you will need to specify the target name as it appears in the command.

Conclusion

This time around, we’ve introduced a PowerShell script that allows you to easily convert and customize Nano Server images. This script offers a variety of options, such as adding workload and extra packages, joining a domain, injecting drivers, opening a port for WinRM connections, customizing your own VHD, enabling EMS and enabling and configuring kernel debugging. All of these options can be mixed and matched to create the required configuration. The resulting VHD may be used without further effort.

We hope that you will find this tool useful and look forward to your feedback!

Hernan Gatta
Microsoft Intern