Create a Windows 11 VM in Hyper-V with Packer

Some people ask if it is possible to create a Windows 11 VM in Hyper-V with Packer. The answer is YES. The Packer plugin that makes this possible is called “Hyperv”. Version 1.1.1 supports TPM. Enabling TPM in the Hyper-V VM makes it possible to install Windows 11 without any registry hacks.

So I decided to test Packer with Hyper-V and Windows 11 and create a blog post about it.

So what are the prerequisites?

  • Make sure the Hyper-V role is enabled in Windows 10/11
  • Download the Windows 11 ISO and save the ISO to the following location: c:\iso
    An example of downloading and creating a Windows 10/11 ISO can be found here: https://www.ivobeerens.nl/2021/05/19/quick-tip-download-the-latest-windows-10-iso-file/
  • Install the Windows Assessment and Deployment Kit (32-bit version). https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install#download-the-adk-for-windows-11-version-22h2
  • Add the following location the the system path variable: C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\x86\Oscdimg

When the prerequisites are met you can go further with the rest. To make it easy I created a PowerShell script called _1.build.ps1 (link) that does all the work for you.

# Enable TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Speed up the invoke-webrequest command
$ProgressPreference = 'SilentlyContinue'

# Variables
$downloadfolder = "C:\temp\" # Packer location installed
$win11_downloadfolder = "C:\Temp\packer-main\hyper-v\windows11\"
$packer_config = "windows.json.pkr.hcl" #Packer config file
$packer_variable = "windows.auto.pkrvars.hcl" # Packer variable file
$github = "https://github.com/ibeerens/packer/archive/refs/heads/main.zip"
$product = "packer"
$packer_uri = "https://developer.hashicorp.com/packer/downloads"

# Check if the temp folder exist
If(!(test-path -PathType container $downloadfolder))
    {
      New-Item -ItemType Directory -Path $downloadfolder
}

# Go to the Packer download folder
Set-Location $downloadfolder

# Download Github files
Invoke-WebRequest -Uri $github -OutFile ${downloadfolder}packer.zip
Expand-Archive ${downloadfolder}packer.zip -DestinationPath $downloadfolder -Force

# Remove zip file
Remove-Item -Path ${downloadfolder}packer.zip 

# Download the latest version of Packer
$packurl = Invoke-WebRequest -Uri $packer_uri| Select-Object -Expand links | Where-Object href -match "//releases\.hashicorp\.com/$product/\d.*/$product_.*_windows_amd64\.zip$" | Select-Object -Expand href
$packdown = $packurl | Split-Path -Leaf
$packdownload = $downloadfolder + $packdown
Invoke-WebRequest $packurl -outfile $packdownload

# Unzip Packer 
Expand-Archive $packdownload -DestinationPath $win11_downloadfolder -Force
# Remove the Packer ZIP file
Remove-Item $packdownload

# Go to the Packer download folder
Set-Location $win11_downloadfolder

  • Line 7-13: This is the variable block. Change if needed
  • Line 13-19: Here are the variables located. Change if needed
  • Line 21-25: The script creates a c:\temp folder if it does not exist
  • Line 30-32: Downloads the GitHub files for creating a Windows 11 VM
  • Line 37-41: Downloads the latest version of Packer

After running the _1.build.ps1 script it is time to change the variables:

  • Get the hash of the ISO file with the Powershell Get-Filehash command and change the variable in the windows-auto-pkvars.hcl file
  • Change the other variables in the windows-auto-pkvars.hcl such as win_iso for the exact iso name
  • Run the following _2.run_packer.ps1 script
# Show Packer Version
.\packer.exe -v

# Download Packer plugins
.\packer.exe init "${$win11_downloadfolder}${packer_config}"

# Packer Format configuration files (.pkr.hcl) and variable files (.pkrvars.hcl) are updated.
.\packer.exe fmt -var-file="${$win11_downloadfolder}{$packer_variable}" "${$win11_downloadfolder}${packer_config}"

# Packer validate
.\packer.exe validate .

# Packer build
.\packer.exe build -force -var-file="${$win11_downloadfolder}${packer_variable}" "${$win11_downloadfolder}${packer_config}"
  • Line 2: Show the Packer version
  • Line 5: Download Packer plugins such as the hyper-v and Windows update plugin
  • Line 8: Formats the config and variable HCL file syntax
  • Line 11: Performs a validation to make sure the variable and config file are ok
  • Line 15: Starts Packer to create a Windows 11 VM

The creation of a Windows 11 VM starts. When the image is created it is stored and needs to be imported in the Hyper-V manager.

  • Start the Hyper-V Manager
  • Select Import Virtual Machine
  • Browse to the created image folder C:\Temp\packer-main\hyper-v\windows11\output-windows11\
  • Select the VM
  • Register the VM in-place
  • Start the VM

On my laptop, I have in 35 minutes a fresh copy of Windows 11 running with the latest updates installed running in Hyper-V. How cool is that! The scripts can be found on my GitHub page (link). Have fun creating Windows 11 VMs.

 

Build a Windows 10 image with Packer using VMware Workstation

Most of the time I use Packer against a VMware vSphere and Microsoft Azure environment. But sometimes it’s useful to use VMware Workstation for local testing purposes. For building Windows 10 images with Packer and using VMware Workstation there is not much information available. In this blog post, I show how to build a Windows 10 image with Packer and VMware Workstation.

With Packer, the vmware-iso builder is used for creating images with VMware Workstation/Fusion.  In this example I create a Windows 10 image with the latest VMware Tools installed, the installation of the Evergreen module, and automatically install the latest Windows updates.

Pre-requisites

  • Windows a 10 ISO file. You can use this link for downloading the latest Windows 10 ISO for example
  • Install VMware Workstation. I use VMware Workstation Pro 16.x
  • The newly created image must be able to access the internet for  downloading the latest VMware Tools version
  • During my first deployment, the following build issue occurred Build “Could not determine network mappings from files in the path: C:/Program Files (x86)/VMware/VMware Workstation“. Colin Westwater of vGemba.net has blogged about a solution that can be found here, link.
  • Use NAT in VMware Workstation.

Steps

  • Run the following PowerShell script (link). This script does the following things:
    • Create a download folder such as c:\Packer (line 6-17)
    • Download the latest Packer version and unzip the package (line 19-30)
    • Download my Github Packer repository to the local download folder (line 35-39)
    • Create within the download folder the Packer folder structure (line 41-45)
# $ErrorActionPreference = "SilentlyContinue"
# Enable TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# Variables
$downloadfolder = 'C:\packer\'
$github = 'https://github.com/ibeerens/Packer/archive/refs/heads/main.zip'

# Create Folder
$checkdir = Test-Path -Path $downloadfolder
if ($checkdir -eq $false){
    Write-Verbose "Creating '$downloadfolder' folder"
    New-Item -Path $downloadfolder -ItemType Directory | Out-Null
}
else {
    Write-Verbose "Folder '$downloadfolder' already exists."
}

# Download the latest Packer version
$product='packer'
$packurl = Invoke-WebRequest -Uri https://www.$product.io/downloads.html | Select-Object -Expand links | Where-Object href -match "//releases\.hashicorp\.com/$product/\d.*/$product_.*_windows_amd64\.zip$" | Select-Object -Expand href
$packdown = $packurl | Split-Path -Leaf
$packdownload = $downloadfolder + $packdown
$webclient = New-object -TypeName System.Net.WebClient
$webclient.DownloadFile($packurl, $packdownload)

# Unzip Packer
Expand-Archive $packdownload -DestinationPath $downloadfolder
# Remove the Packer ZIP file
Remove-Item $packdownload

# Go to the Packer download folder
Set-Location $downloadfolder

# Download Github files
Invoke-WebRequest -Uri $github -OutFile ${downloadfolder}packer.zip
Expand-Archive ${downloadfolder}packer.zip -DestinationPath $downloadfolder
# Remove the packer.zip
Remove-Item -Path ${downloadfolder}packer.zip 

# Create the folder structure
Move-Item ${downloadfolder}Packer-main\workstation\windows10\setup -Destination $downloadfolder
Move-Item ${downloadfolder}Packer-main\workstation\windows10\*.* -Destination $downloadfolder
# Remove the Github structure
Remove-Item -Path ${downloadfolder}Packer-main -Recurse -Confirm:$false -Force
  • Browse to the download folder
  • Open the “win10-std-.auto-pkvars.hcl” file and edit the variables for your needs such as:
    • Line 2: The VM name
    • Line 17: The ISO location
    • Line 19: The ISO checksum. Use the PowerShell Get-Filehash command to get the checksum of the ISO
// VM
vm_name					= 	"GI-W10-001" 
operating_system_vm 	= 	"windows9-64"
vm_firmware				=	"bios"
vm_cdrom_type			=	"ide"
vm_cpus					= 	"2"
vm_cores				= 	"1"
vm_memory				= 	"2048"
vm_disk_controller_type = 	"nvme"
vm_disk_size			= 	"32768"
vm_network_adapter_type =   "e1000e"
// Use the NAT Network
vm_network              =   "VMnet8"
vm_hardwareversion 		= 	"19"

// Removeable media
win10_iso				= 	"c:/iso/en-us_windows_10_business_editions_version_21h2_x64_dvd_ce067768.iso"
// In Powershell use the "get-filehash" command to find the checksum of the ISO
win10_iso_checksum      =   "1323FD1EF0CBFD4BF23FA56A6538FF69DD410AD49969983FEE3DF936A6C811C5"
  • Open the “autounattend.xml” file in the setup folder and check and edit the following lines as needed:
    • Language and keyboard settings
    • Line 84: Administrator Password (must be the same as the winrm_password)
    • Line 92: Autologon Password (must be the same as the winrm_password)
    • Line 141: The ComputerName
  • Edit the build.ps1 file and check the following lines:
    • Line 2: Packer folder location
    • Line 14: The winrm_password matches the administrator password in the autounattended.xml file
# Variables
$downloadfolder = 'C:\packer\'

# Go to the Packer download folder
Set-Location $downloadfolder

# Show Packer Version
.\packer.exe -v

# Download Packer plugins
.\packer.exe init "${downloadfolder}windows.json.pkr.hcl"

# Packer build
.\packer.exe build -force -var-file="${downloadfolder}win10-std.auto.pkrvars.hcl" -var "winrm_username=administrator" -var "winrm_password=ThisisagoodPassword!" "${downloadfolder}windows.json.pkr.hcl"
  • Execute the “build.ps1” file with PowerShell to start the Packer image build process.

  • After a while, the build process finishes and you have a new Windows 10 image deployed with Packer in VMware Workstation.

 

Packer has now virtual TPM (vTPM) device support

In an earlier blogpost called “Use Packer to install Windows 11 and enable vTPM and VBS” I highlighted a workaround for adding a virtual TPM (vTPM) device to a VM in a VMware vSphere environment. A vTPM device is needed for running Windows 11 (without using registry hacks to bypass the TPM device check).

The latest Packer Plugin for VMware vSphere (V1.0.3) has now support for adding a vTPM device. Default a vTPM device is not added to the VM deployed with Packer. So if you want to create a Windows 11 Golden Image for example you can use Packer with the VMware vSphere plugin with a vTPM device.

Here are the high over steps outlined to add a vTPM device when provisioning a new VM with Packer.

    • Download Packer 1.7.9  or later (https://www.packer.io/downloads).
    • Add the VMware vSphere plugin to the HCL configuration file (https://github.com/hashicorp/packer-plugin-vsphere)
packer {
  required_version = ">= 0.0.1"
  required_plugins {
    vsphere = {
      version = ">= 0.0.1"
      source  = "github.com/hashicorp/vsphere"
    }
  }
}
  • Add a variable to enable vTPM
variable "vm_tpm" {
  type = string
  default = "true"
}
  • In the vsphere-iso section, add the vTPM configuration parameter that uses the vm_tpm variable to enable the vTPM device (more options can be found here, link)
source "vsphere-iso" "win11basic" {
  vTPM = "${var.vm_tpm}"
}
  • Perform a packer init command to download the Packer plugin binaries define in the config file
    • packer init config.pkr.hcl
  • Run the packer build command to create the VM
    • packer build config.pkr.hcl

The VM will be created with a vTPM device.

With Packer and the VMware vSphere plugin, it is now possible to create a VM with a vTPM device which is needed for deploying Windows 11 VMs. This is a great improvement!