Microsoft Windows Nano mass deployment using VMware

Microsoft Windows Nano mass deployment using VMware

Last year Microsoft released Windows 2016, which contained Windows Nano 2016. Nano is the answer to the market need for a lightweight system. In other words, Nano Server is a very fast and powerful tool for remote administration of Windows Servers.

How Nano can be used in CI

The whole concept allows to build VM from scratch. This will help to avoid potential bugs related to previous test scenarios, remaining or third-party software. This lets you to set solid, predictable and reliable initial testbed. Picture below shows a simple example of usage in CI:

Windows Nano features and limitations

Nano allows you to install roles such as:

  • Containers,
  • Hyper-V,
  • IIS,
  • DNS,
  • File server,
  • and more.

However, there are important differences in Nano Server compared to Windows Server 2016.

Nano Server, as a lightweight operating system, is optimized for running “cloud-native” applications based on containers and microservices. It can also be used as an agile and cost-effective datacenter host. Nano Server differs significantly from Server Core or Server with Desktop Experience installations:

  • Nano Server is “headless;” there is no local logon capability or graphical user interface,
  • Only 64-bit applications, tools, and agents are supported,
  • Nano Server cannot serve as an Active Directory domain controller,
  • Group Policy is not supported,
  • Nano Server cannot be configured to use a proxy server to access the internet,
  • NIC Teaming (specifically, load balancing and failover or LBFO) is not supported,
  • System Center Configuration Manager and System Center Data Protection Manager are not supported,
  • Nano Server doesn’t need to be activated with a product key. When functioning as a Hyper-V host, Nano Server doesn’t support Automatic Virtual Machine Activation (AVMA). Virtual machines running on the Nano Server host can be activated by using Key Management Service (KMS) with a generic volume license key,
  • All operations are performed remotely by PowerShell Session and/or MMC plugins applicable for the installed module.

Nano became an ideal solution for reliable and fast CI component, which allows to build a VM from scratch in a quick way. This requires a few adjustments shown below.

How to build an image

To build a Nano Image, you need to take a look on several points:

  • Prerequisites,
  • Additional drivers,
  • Building WIM for WDS,
  • Changes in the Image (adjustments).


Test Equipment specification and software set which you are about to use, require basic, already existing infrastructure such as:

  • Active Directory,
  • WDS (Windows Deployment Services),
  • DHCP,
  • VMware vCenter.

Additional drivers for VMware

In this particular case we need to have VMware Drivers included in the image, otherwise the newly created VM will come up with errors related to HDD I/O or network connectivity. You need to extract the drivers from VMTools. This can be achieved in a few steps:

  • Load the VMware Tools ISO into the virtual CD/DVD drive (for example, D:),
  • Browse to the C: drive (that is, the system or data drive) and create a folder named Extract,
  • Open a command prompt and change directory to the D: drive,
  • Run the command: setup.exe /A /P C:Extract
  • If you are prompted to provide the location for the installation/extraction, enter C:Extract (the folder you created in step 2),
  • When the process is complete, click Finish,
  • Browse to the C:Extract folder to access the extracted drivers.

You need to point to extracted drivers while creating the image.

Building WIM for WDS

Building the image requires installing the PowerShell module, which is delivered with the ISO image of Windows Server 2016.
Launch PowerShell as Administrator.
Navigate to the mounted nanoServerNanoServerImageGenerator and execute the command:

Import-Module .NanoServerImageGenerator.psd1

Next, check if the module is installed by typing:

Get-Module. NanoServerImageGenerator

It should be listed as on the image above.
After that, we are ready to prepare a WIM (Windows Imaging Format) file.
There are 2 ways of doing this:

  1. Using Server Image Builder: you can find the manual here: – this is not a perfect tool –  unfortunately encountered some issues with displaying the package list and that’s why I decided to write a custom command.
  2. Writing a command is more flexible than using Image Builder, which as the matter of fact is generating and executing command in PowerShell either way.

Since we are planning to use VMware – the drivers from VMware Tools are mandatory, otherwise Nano won’t start and there might be a problem with virtual hardware compatibility with Hypervisor Hosts. It’s a good idea to prepare VM Drivers before creating the image by extracting VM Tools for x64 systems.

New-NanoServerImage -Edition DataCenter -OEMDrivers -MediaPath 'd:' -TargetPath '.nano1.4.wim' -EnableRemoteManagementPort -AdministratorPassword (ConvertTo-SecureString -String "LetMeiN!@#$" -AsPlainText -Force) -Compute -Containers -DeploymentType HOST -DriverPath ('.Nano_drvvm3d.inf_x64vm3d.inf','.Nano_drvvmaudio.inf_x64vmaudio.inf','.Nano_drvvmci.inf_x64vmci.inf','.Nano_drvvmmouse.inf_x64vmmouse.inf','.Nano_drvvmusbmouse.inf_x64vmusbmouse.inf','.Nano_drvvmxnet3ndis6.inf_x64vmxnet3ndis6.inf')

Changes in the image

Before you put the image on the WDS server you need to make some changes. Not all options are included and available in the image.
The tool which allows to mount an offline image – dism.exe – is included in Windows.
To mount the image, execute the command:

Dism /Mount-Image /ImageFile:<pathyournanoimage.wim> /MountDir: /index:1

More details about dism can be found here.
From now on, you can browse the image in the folder pointed to.

Windows Nano by design is executing a batch script, which is included in the image. To view the content, you can navigate to:


It contains information which we previously configured while creating the image:

For example:
Inserts cmdlets to open ports on firewall, which we defined in New-NanoImage cmdlet:
We prefer to use PowerShell to execute commands, because it is more flexible and reliable compared to old Command Prompt. To execute the PS scripts, we need to add an Execution Policy before we start:

PowerShell "Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force"

And here is the link to execution of the PS script:

PowerShell ". C:WindowsSetupScriptsJoinDomainNano.ps1"

Contents of JoinDomainNano.ps1:

set-item wsman:localhostclienttrustedhosts -value * -Force

$computerId = (Get-CimInstance Win32_ComputerSystemProduct | Select-Object -ExpandProperty UUID)
$filename = $computerId.Substring($computerId.Length -12)
$login = ""
$passwd = ""
$blobshare = ""
net use $blobshare $passwd /USER:$Login
Copy-Item -Path "$blobshare*$filename" -Destination C:WindowsSetupScriptsdjoin-file -Force
djoin /requestodj /loadfile C:WindowsSetupScriptsdjoin-file /windowspath C:Windows /localos
Restart-Computer -Force

Since GUID generated by WMware is NOT the exact match generated “inside” the VM, we take last 12 characters of a string to determine the proper blob file.
To save your changed image, execute the command:

Dism /Unmount-Image /MountDir: /Commit

Preparing test WDS


Before you start, you need to prepare several things:

  • AD Admin account, authorized to add/remove computers in the domain,
  • XML for WDS.

General overview of unattended installation

  1. The Server boots from PXE and gets an IP address from DHCP server,
  2. It downloads and boots the modified WinPE image from the WDS server,
  3. The image is selected from WDS (automated),
  4. The Server is partitioned (automated),
  5. WIM / VHD / VHDX & Unattend.xml are deployed,
  6. PowerShell executes and joins Nano Server to the domain with domain credentials,
  7. Server reboots and is fully provisioned, including joining the AD domain.

Creating XML file for WDS is crucial. It’s necessary to have Windows ADK installed to perform the task.
Windows ADK can be found here.
Open Windows System Image Manager from ADK
In the Windows Image section you need to select the newly created WIM image to choose available components for this image:

You need to choose components and assign them to schemas as shown below:

In addition, you need to configure these options with required fields with domain admin accounts, domain name, partition behaviour, image selection, etc.

After you’ve finished, you should get an XML file looking like this.

Save the file on the WDS server in RemoteInstall (remInst) folder (which was defined during WDS deployment).
Open WDS console.

WDS properties
Then you need to specify newly created answer file to x64 architecture:

Because Nano has a bit different compared to regular Windows 2016 policy regarding domain joining, mark “Do not join the client to a domain after an installation”.
More details can be found here.

Preparing vCenter

Preparing a template

First, it’s good to have a template with VM specification without installed OS. Create VM specification taking into consideration predicted tests load. You can refer to the Microsoft website to create a template.

Important fact that is to choose in the template – Network Card which driver you’ve installed before. Otherwise an connection errors may occur.

VM building scripts


  • Running VMWare environment,
  • Execution server,
  • PowerCLI installed on the execution server,
  • Domain admin permissions / technical account.


if (Get-Module -Name Hyper-V) {
Remove-Module Hyper-V
} else {
Write-Host "Hyper-V module does not exist"
if (Get-Module -Name VMWare*) {
& 'C:Program Files (x86)VMwareInfrastructurePowerCLIScriptsInitialize-PowerCLIEnvironment.ps1'
} else {
Write-Host "VMWare modules exist"
& 'C:Program Files (x86)VMwareInfrastructurePowerCLIScriptsInitialize-PowerCLIEnvironment.ps1'
function VMName {
$VMname = 'Nano' + '_'+ [string][guid]::NewGuid().guid[1..5]
$VMname.replace(' ','')
$Pool = Get-ResourcePool -Name Resou*
$NTmp = Get-Template -Name nano*
$vm = New-VM -name $NName -Template $NTmp -Datastore Storage -ResourcePool $Pool -Location Demo
[guid]$guid = (Get-View $
$testbed_ou = "OU=Virtual Machines,DC=example,DC=com"
New-ADComputer -Name "$NName" -SAMAccountName "$NName" -Path "$testbed_ou" -OtherAttributes @{'netbootGUID'=$guid} -Description "$guid"
Function New-DJoin{
[string] $ComputerName
Invoke-Command {Djoin.exe /provision /domain /machine $ComputerName /reuse /savefile $guid /ROOTCACERTS /MachineOU "$testbed_ou"}}
New-DJoin $NName
Start-VM -VM $NName -Confirm:$false -ErrorAction SilentlyContinue
Write-Host "$NName"

Note that due to the lack of compatibility it is required to remove the Hyper-V module. Some of the commands included in the module are the same and can invoke the Hyper-V context instead of PowerCLI.

In  part of the script a random name from GUID is generated. The script extracts a string from the GUID and uses it to create Active Directory Name and generate VM name. It’s worth mentioning that the script creates an AD account with the netbootguid attribute – which allows to match the newly created VM with the AD account.

Also, GUID is not the exact match with GUID generated inside VM, but it’s enough to find the generated blob file.

Image update

From time to time, it’s necessary to update your Nano image. It’s possible to download an offline package and edit the image.
More detailed information can be found here.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *