Building a Windows 11 gold template
Learn how to create a Windows 11 gold template in Proxmox for VDI environments, allowing for efficient desktop pool management. This guide is aimed at engineers and includes steps for setting up, configuring, and testing the template.
1. How it fits together
You build and keep two things in Proxmox:
| Item | Example name | What it is |
|---|---|---|
| Master VM | w11-office-master |
A normal VM where you install and update software. It is never sysprepped, so you can keep using it to make new versions. |
| Gold template | gold-w11-office-v1 |
A sysprepped copy of the master, converted to a Proxmox template. SDE VDI makes linked clones of it. You enter this name in the SDE VDI admin UI. |
Each new version (v2, v3…) is a fresh copy of the updated master. Old templates stay until no pool uses them.
When SDE VDI creates a desktop from the template, it:
- Makes a linked clone, named after the pool (for example
W11-OFF-007). - Starts it. Windows finishes setup on its own and comes up with a new security identity (SID) and a temporary random name.
- Uses the QEMU guest agent to rename it and, where Active Directory is configured, join it to the domain. It then restarts.
- Waits for Remote Desktop to answer, then marks it as a spare desktop.
2. Before you start
| You need | Details |
|---|---|
| Windows 11 ISO | Dev: Windows 11 Enterprise Evaluation (90 days) from the Microsoft Evaluation Center. Live: Windows 11 Enterprise from your volume licensing portal. |
| VirtIO drivers ISO |
|
| Both ISOs in Proxmox | Upload them to an ISO storage: Datacenter → node → storage (e.g. local) → ISO Images → Upload, or Download from URL. On a cluster, use shared ISO storage or upload to the node you build on. |
| Software installers | For example the Office Deployment Tool (section 7) and any specialist applications. |
| A VM ID range | Suggested: 8000–8099 for master VMs, 9000–9099 for gold templates. That keeps them apart from the clones SDE VDI creates. |
3. Choose where the template lives
Linked clones are created on the same storage as the template. Pick the storage first, because it decides which nodes can run the pool:
| Template storage | Clones can run on | Use when |
|---|---|---|
| Shared (Ceph RBD, NFS with qcow2) | Any node in the cluster | Dev cluster with shared storage. This is best for scaling. |
| Local (LVM-thin, ZFS) | Only the node that holds the template | Single-node client sites, or a cluster without shared storage. |
Local dir with raw disks |
Can't make linked clones | Don't use for templates. |
4. Create the master VM
In the Proxmox web UI, select Create VM and use these settings. Anything not listed can stay at its default.
| Tab | Setting | Value |
|---|---|---|
| General | VM ID / Name | 8001 / w11-office-master |
| OS | ISO image | The Windows 11 ISO |
| Guest OS | Microsoft Windows, version 11/2022/2025 | |
| Add additional drive for VirtIO drivers | Ticked, and select virtio-win.iso |
|
| System | Machine | q35 |
| BIOS | OVMF (UEFI). Add EFI Disk, on your template storage, with Pre-Enroll keys ticked | |
| SCSI Controller | VirtIO SCSI single | |
| Qemu Agent | Ticked | |
| Add TPM | Ticked, on your template storage, version v2.0 | |
| Disks | Bus / Size | SCSI, 64 GB (80 GB or more with Office or large applications), on your template storage |
| Discard / SSD emulation / IO thread | All ticked | |
| CPU | Cores | 4 |
| Type | x86-64-v2-AES (the default). Use host only if every node in the cluster has the same CPU. |
|
| Memory | Memory | 8192 MiB |
| Network | Bridge / Model | The bridge (and VLAN tag) the desktops will use; model VirtIO (paravirtualized) |
Don't start the VM from the summary screen yet. Check that Hardware lists two CD drives (Windows and VirtIO), an EFI disk and a TPM state disk.
Or create it with one command
Quicker and harder to get wrong. In the Shell of the node the template will live on, first check the ISO file names (ls /var/lib/vz/template/iso/) and the bridge name (node → System → Network, usually vmbr0), then run, swapping in your ISO name, bridge and storage:
qm create 8001 --name w11-office-master --ostype win11 \
--machine q35 --bios ovmf \
--efidisk0 datastore01:1,efitype=4m,pre-enrolled-keys=1 \
--tpmstate0 datastore01:1,version=v2.0 \
--scsihw virtio-scsi-single --scsi0 datastore01:64,iothread=1,discard=on,ssd=1 \
--cpu x86-64-v2-AES --cores 4 --memory 8192 --balloon 0 \
--net0 virtio,bridge=vmbr0 --agent enabled=1 \
--ide2 local:iso/YOUR-WIN11.iso,media=cdrom \
--ide0 local:iso/virtio-win.iso,media=cdrom \
--boot order='ide2;scsi0'
--balloon 0 turns memory ballooning off so Windows sees all of its memory. On a cluster short of memory, --memory 4096 is the Windows 11 minimum and fine for testing.
5. Install Windows
- Start the VM and open the Console. Press a key when you see Press any key to boot from CD or DVD. If you miss it, reset the VM and try again.
- Choose your language, English (United Kingdom) time format and the United Kingdom keyboard, then select Install.
- At Select location to install Windows 11 no disk is listed yet. Select Load driver → Browse, open the VirtIO CD, and choose
vioscsi\w11\amd64. Install the Red Hat VirtIO SCSI pass-through controller. - Select Load driver again and choose
NetKVM\w11\amd64. This adds the network driver now, so Windows has a network during setup. - Select the unallocated disk and continue. Windows installs and restarts a few times.
- In the out-of-box screens, choose region United Kingdom and keyboard United Kingdom.
- When it asks for a Microsoft account, select Sign-in options → Domain join instead. This creates a local account.
- If that option is missing, press Shift+F10 and run
start ms-cxh:localonly.
- If that option is missing, press Shift+F10 and run
- Create the local administrator
vdiadminwith a strong password. Record the password in the password manager. - Turn every privacy option off and finish setup.
6. Configure Windows
Sign in as vdiadmin. Run the commands in an elevated PowerShell window (right-click Start → Terminal (Admin)).
6.1 Install the VirtIO guest tools and QEMU guest agent
- In File Explorer, open the VirtIO CD and run
virtio-win-guest-tools.exe. Accept the defaults. It installs all VirtIO drivers and the QEMU guest agent. - Check that the agent is running:
It should showGet-Service QEMU-GARunning. - In Proxmox, open the VM's Summary. After a minute, IPs shows the VM's address instead of Guest Agent not running.
6.2 Stop Store apps updating themselves
Store apps that update for one user break sysprep later, so do this before running Windows Update.
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsStore' -Force | Out-Null
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsStore' -Name AutoDownload -Value 2 -Type DWord
6.3 Windows Update
Open Settings → Windows Update and install everything. Restart and check again until no updates are left, including optional driver updates you want in the image.
6.4 Remote Desktop
# Allow Remote Desktop with Network Level Authentication, and open the firewall
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnections -Value 0
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication -Value 1
Enable-NetFirewallRule -DisplayGroup 'Remote Desktop'
6.5 Test user (dev only, no Active Directory)
Dev desktops aren't joined to a domain, so users sign in with a local account built into the image. Skip this in live, where a domain group is given Remote Desktop rights by Group Policy.
$pw = Read-Host -AsSecureString 'Password for vdiuser'
New-LocalUser -Name vdiuser -Password $pw -PasswordNeverExpires -FullName 'VDI test user'
Add-LocalGroupMember -Group 'Remote Desktop Users' -Member vdiuser
6.6 Power settings
A pool desktop must never sleep or hibernate, or it drops out of the pool.
powercfg /hibernate off
powercfg /change standby-timeout-ac 0
powercfg /change monitor-timeout-ac 0
6.7 Session time limits
SDE VDI only recycles a desktop once the user has signed out. These limits make sure an abandoned session eventually signs out. In live, the same settings come from a Group Policy on the pool's OU; on dev, set them locally.
- Run
gpedit.msc. - Go to Computer Configuration → Administrative Templates → Windows Components → Remote Desktop Services → Remote Desktop Session Host → Session Time Limits.
- Set time limit for disconnected sessions: Enabled, 30 minutes.
- End session when time limits are reached: Enabled.
- Optional: Set time limit for active but idle Remote Desktop Services sessions, for example 2 hours.
6.8 Make sure BitLocker is off
Windows 11 can turn on device encryption by itself. Sysprep refuses to run on an encrypted disk, and the clones can't use it anyway.
manage-bde -status C:
# If "Protection Status" is On, or "Conversion Status" isn't "Fully Decrypted":
manage-bde -off C:
# Prevent it switching back on:
Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\BitLocker' -Name PreventDeviceEncryption -Value 1 -Type DWord
Wait for decryption to finish (manage-bde -status C: shows Fully Decrypted) before going on.
6.9 Optional: optimise for VDI
An optimisation tool such as the Omnissa OS Optimization Tool turns off background tasks, visual effects and scheduled jobs that waste CPU across many desktops. Run it last, after all software is installed, and keep a note of the template you applied.
7. Install software
Install the applications this pool needs. Install them for all users (per-machine) where the installer offers a choice.
Microsoft 365 Apps (Office)
Office in a pool must use Shared Computer Activation. Otherwise each new desktop uses up one of a user's five activations.
- Download the Office Deployment Tool from Microsoft and extract it to
C:\ODT. - Save this as
C:\ODT\vdi.xml:<Configuration> <Add OfficeClientEdition="64" Channel="MonthlyEnterprise"> <Product ID="O365ProPlusRetail"> <Language ID="en-gb" /> <ExcludeApp ID="Groove" /> <ExcludeApp ID="Lync" /> </Product> </Add> <Property Name="SharedComputerLicensing" Value="1" /> <Property Name="FORCEAPPSHUTDOWN" Value="TRUE" /> <Updates Enabled="FALSE" /> <Display Level="None" AcceptEULA="TRUE" /> </Configuration> - Run:
It finishes silently after several minutes.cd C:\ODT .\setup.exe /configure vdi.xml - Don't sign in to Office in the master. On dev without licences, Office runs unlicensed, which is fine for testing.
Product ID and Channel for that edition and drop SharedComputerLicensing.8. Add the unattend file
The unattend file answers every Windows setup question on each clone, so a new desktop goes straight to the sign-in screen. Store it in the master so every version uses it.
- Open Notepad as administrator.
- Paste the following and save as
C:\Windows\System32\Sysprep\unattend.xml. Set Save as type to All files so Notepad doesn't add.txt.
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<settings pass="specialize">
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<!-- Random temporary name; SDE VDI renames the clone afterwards -->
<ComputerName>*</ComputerName>
<TimeZone>GMT Standard Time</TimeZone>
</component>
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager" processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<fDenyTSConnections>false</fDenyTSConnections>
</component>
<component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UserAuthentication>1</UserAuthentication>
</component>
<component name="Networking-MPSSVC-Svc" processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<FirewallGroups>
<FirewallGroup wcm:action="add" wcm:keyValue="RemoteDesktop">
<Active>true</Active>
<Group>Remote Desktop</Group>
<Profile>all</Profile>
</FirewallGroup>
</FirewallGroups>
</component>
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<InputLocale>0809:00000809</InputLocale>
<SystemLocale>en-GB</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-GB</UserLocale>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<OOBE>
<HideEULAPage>true</HideEULAPage>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<ProtectYourPC>3</ProtectYourPC>
</OOBE>
<TimeZone>GMT Standard Time</TimeZone>
</component>
</settings>
</unattend>
UILanguage must be a display language that is installed. The evaluation ISO is normally en-US, which is why the display language is en-US while locale and keyboard are en-GB. If you installed from an en-GB ISO, change it to en-GB.Shut the master down: Stop-Computer. This is the end of the master build.
9. Release a template version
To keep the master reusable, you sysprep a copy of it. Do this for v1 and for every later version.
- With the master shut down, select it and choose Snapshots → Take Snapshot. Name it
v1and add a description of what's in this version. You can return to it if a later update goes wrong. - Right-click the master → Clone.
- Mode: Full Clone.
- VM ID:
9001; Name:gold-w11-office-v1. - Target storage: your template storage (section 3).
- On a cluster, Target node: the node the template should live on.
- On the new VM, open Hardware → Network Device → Edit and tick Disconnect. This stops it fetching updates or clashing with the master's name during sysprep.
- Start it, open the Console and sign in as
vdiadmin. - In an elevated PowerShell window, run sysprep:
The VM shuts itself down after a minute or two. If it stays on with an error, see Troubleshooting.C:\Windows\System32\Sysprep\sysprep.exe /generalize /oobe /shutdown /mode:vm /unattend:C:\Windows\System32\Sysprep\unattend.xml - Don't start it again. Starting it would use up the generalised state, and you'd have to clone and sysprep again.
- Prepare its hardware:
- Network Device → Edit: untick Disconnect. Clones inherit this setting.
- Both CD/DVD drives → Edit: Do not use any media.
- Options: check that QEMU Guest Agent is Enabled.
- On its Summary page:
- Add the tag
sde-gold. - In Notes, record the version, the date and what changed.
- Add the tag
- Right-click it → Convert to template.
The template gold-w11-office-v1 is ready. This is the name you choose in the SDE VDI admin UI.
10. Test the template
Do what SDE VDI will do, by hand, once.
- Right-click the template → Clone. Mode: Linked Clone; Name:
W11-TEST-001. Start it. - Watch the Console. It shows Getting ready, may restart once, then stops at the sign-in screen without asking any setup questions. This normally takes 2–4 minutes.
- The clone's Summary shows an IP address, which confirms the guest agent works.
- Rename it through the guest agent, the same way SDE VDI does. In the Proxmox node Shell, replace
<vmid>with the clone's ID:
The clone restarts.qm guest exec <vmid> -- powershell -NoProfile -Command "Rename-Computer -NewName W11-TEST-001 -Force -Restart" - From a PC on the same network, connect with Remote Desktop to the clone's IP as
vdiuser. Check that the computer name isW11-TEST-001(runhostname) and that your applications open. - Sign out. Then delete the test clone: stop it, then right-click → Remove.
11. Updating the image later
- Start the master (
w11-office-master), not a template. - Run Windows Update and add or update software.
- Check that BitLocker is still off (6.8).
- Shut it down.
- Follow section 9 again with the next version: snapshot
v2, full clone togold-w11-office-v2, sysprep, convert to template. - In the SDE VDI admin UI, publish v2 to the pool. Desktops on v1 are replaced as their users sign out.
- Delete the v1 template once no pool uses it and no desktops are still based on it. Proxmox refuses to delete a template that still has linked clones.
12. Troubleshooting
| Problem | Fix |
|---|---|
| No disk at "Select location" | Load the vioscsi\w11\amd64 driver from the VirtIO CD (section 5, step 3). |
| "This PC can't run Windows 11" (TPM, memory) | The VM is missing UEFI, Secure Boot keys or the TPM, or Windows sees under 4 GB. Check: BIOS OVMF, machine q35, EFI disk with Pre-Enroll keys, TPM v2.0, memory at least 4096 MiB with ballooning off. Recreating the VM with the qm create command in section 4 fixes all of these. Dev-only fallback: on that screen press Shift+F10, run reg add HKLM\SYSTEM\Setup\LabConfig /v BypassTPMCheck /t REG_DWORD /d 1 /f and the same with BypassRAMCheck, then go back one step and forward again. |
| Summary says "Guest Agent not running" | Check that Options → QEMU Guest Agent is Enabled (this needs a full VM stop and start, not a restart) and that the QEMU-GA service is running inside Windows. |
| Sysprep: "was not able to validate your Windows installation" | Open C:\Windows\System32\Sysprep\Panther\setupact.log and search for Error.
|
| Sysprep: "a fatal error occurred" | Usually a pending update or restart. Discard this clone, start the master, finish Windows Update and restart it, then release again from section 9. |
| Clone stops at a setup screen | The unattend file wasn't used or has a typo. Check that sysprep was run with the /unattend: path and that the file is named unattend.xml, not unattend.xml.txt. |
| "Linked clone" option is greyed out | The template is on storage that can't do linked clones, or one of its disks (EFI, TPM) is on different storage. See section 3. |
| Every clone gets the same IP | The DHCP server is keying on something other than the MAC address, or a static IP was set in the master. Set the master's network adapter back to DHCP and release a new version. |
| RDP connects but rejects the sign-in | On dev, use the local account vdiuser, prefixed with .\ if asked (.\vdiuser). Check it's in Remote Desktop Users. |
13. Final checklist
Before entering the template's name in the SDE VDI admin UI, check that:
- It is a template named
gold-<os>-<variant>-v<N>and taggedsde-gold. - All of its disks (main, EFI, TPM) are on storage that supports linked clones.
- The QEMU Guest Agent option is enabled, and a test clone shows its IP in Proxmox.
- A test clone boots to the sign-in screen without any setup questions.
- Renaming through
qm guest execworks. - RDP with NLA works (dev: as
vdiuser). - The network device is connected and the CD drives are empty.
- BitLocker is off; sleep and hibernation are off.
- The session time limits are set (dev: local policy; live: GPO on the pool OU).
- Office, if installed, uses Shared Computer Activation.
- The master VM is shut down, and has a snapshot for this version.
person people found this useful.