I’ve been setting up automated Windows 11 Enterprise VMs using antifob/incus-windows on Incus 6.22 (Zabbly stable, Debian Trixie). The goal was to get incus exec working so we can manage VMs without relying on WinRM or ssh.
Documenting the steps here because I hit a few non-obvious gaps and I hope I haven’t done something with difficulty that should have been easier and supported out of the box.
Anyone who need to use Windows in incus who has not checked out antifob/incus-windows, should do so. It’s a great project!
Environment
- Host: Debian Trixie, Incus 6.22 (Zabbly stable repo)
- Guest: Windows 11 Enterprise (evaluation)
- Image builder: antifob/incus-windows mainline
- virtio-win: 0.1.285-1
What incus-windows gives you out of the box
IT automates the downloading of the Windows iso from Microsoft (uses evaluation isos) and setting them up. The main build.sh produces a base image with:
- Virtio drivers (net, block, GPU, serial, input, balloon, RNG)
- incus-agent installed as a Windows service (
Incus-Agent) - SPICE guest tools
- WinRM (via
ConfigureRemotingForAnsible.ps1) requirements.cdrom_agent: "true"in image metadata
After building and importing:
sh build.sh 11e
sh tools/import.sh ./output/win11e/
You can launch a VM and the agent service exists. But incus exec doesn’t work yet.
The two missing pieces
1. virtio-vsock driver (viosock)
Incus 6.22 switched the Windows agent transport from TCP to vsock (release notes). The agent communicates with the host over AF_VSOCK instead of a network connection. This requires the virtio-vsock kernel driver on the Windows side.
The problem: the viosock driver was only added to virtio-win in version 0.1.285-1. The incus-windows project pins to 0.1.248 (because 0.1.262 breaks Windows Server 2012). If you’re only building Win10/Win11, you can safely override:
export VIRTIO_VERSION=0.1.285-1
export VIRTIO_SHA256=e14cf2b94492c3e925f0070ba7fdfedeb2048c91eea9c5a5afb30232a3976331
sh build.sh 11e
This gets the viosock driver into the ISO used during the unattended install, but it won’t be auto-installed by Windows because there’s no matching device present at install time. You need to install it manually after boot:
# Extract viosock files from the virtio-win ISO to C:\Temp\viosock, then:
pnputil /add-driver C:\Temp\viosock\viosock.inf /install
The driver INF references these files which must all be in the same directory:
viosock.inf,viosock.sys,viosock.catviosocklib_x64.dll,viosocklib_x86.dllviosockwspsvc.exe
2. Agent service start type
The incus-agent-setup.ps1 script (installed by the agent’s install.ps1 from the config ISO) sets the service to Manual start. For incus exec to work on boot without intervention:
Set-Service -Name "Incus-Agent" -StartupType Automatic
Complete setup sequence
After building the base image with incus-windows and launching a VM:
# Create and start
incus create win11e myvm
incus config device add myvm incusagent disk source=agent:config
incus start myvm
Then via WinRM (or VGA console, or however you can reach the VM initially):
# 1. Install viosock driver (files must be on the VM already)
pnputil /add-driver C:\Temp\viosock\viosock.inf /install
# 2. Set agent to auto-start
Set-Service -Name "Incus-Agent" -StartupType Automatic
# 3. Restart the agent
Restart-Service Incus-Agent
After that:
$ incus exec myvm -T -- cmd /c "echo hello"
hello
If you bake these steps into your image customization before publishing, every VM launched from that image will have incus exec working on first boot.
Things that confused me along the way
Phantom devices: After publishing and re-launching, Get-PnpDevice showed SCSI controllers and CD-ROMs in “Unknown” state. These turned out to be phantom devices (CM_PROB_PHANTOM) left over from the image build, not real hardware. Filter with Where-Object { $_.Problem -ne "CM_PROB_PHANTOM" }.
No CD-ROM for agent config: On 6.22, the agent:config disk is no longer presented as a CD-ROM ISO (as it was in 6.0.x). The agent communicates directly via vsock. The incus-agent-setup.ps1 still looks for a CD-ROM labeled “incus-agent” and calls ExitSetup if not found, but the agent binary and certs are already in C:\ProgramData\Incus-Agent\ from the initial install.
Host dependencies: The Incus host needs xorriso (for incus-windows ISO repacking) and genisoimage (for Incus to generate the agent:config ISO). Neither is installed by default on Debian Trixie.
Questions for the community
-
Is the Manual start type on the Incus-Agent service intentional? It seems like Automatic would be the right default for the vsock transport since there’s no CD-ROM to trigger setup on each boot.
-
Should incus-windows be updated to use virtio-win 0.1.285+ by default (at least for Win10/Win11 targets) now that vsock is the transport?
-
Is there a way to make Windows auto-install the viosock driver during the unattended install, even though the vsock PCI device isn’t present at that stage? We’re currently doing it as a post-install step.