diff options
| author | Lena <lena@omega> | 2026-06-01 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-06-01 00:00:00 +0000 |
| commit | 9a0e81b32808cf0d6060f10cef66c400550eb5f4 (patch) | |
| tree | 417cb2a2a3a6ff5f3f09140ec8549f869fcec737 /README | |
| download | win11-qemu-install-9a0e81b32808cf0d6060f10cef66c400550eb5f4.tar.gz | |
Installing Windows 11 under QEMU by hand means clicking through all of
Setup and OOBE and bypassing the TPM and Secure Boot checks every time.
Automating what can be automated makes a throwaway lab VM reproducible.
Diffstat (limited to 'README')
| -rw-r--r-- | README | 133 |
1 files changed, 133 insertions, 0 deletions
@@ -0,0 +1,133 @@ +win11-qemu-install +================== +Mostly-unattended install of Windows 11 onto a disk image under QEMU/KVM. +The script generates an Autounattend.xml, hands it to Windows Setup on a +virtual floppy, and runs QEMU against the install ISO and a target disk +created beforehand with qemu-img. The answer file presets the en-US locale, +bypasses the TPM 2.0, Secure Boot, and minimum RAM checks via LabConfig, +creates one local administrator, and auto-logs in once. The pages it leaves +alone (EULA, edition, target disk) are clicked once over VNC. + +Whatever disk is picked on Setup's disk page is wiped. + + +Requirements +------------ + - qemu-system-x86_64 with KVM and seccomp sandbox support + - a POSIX shell, sed, id, and mktemp + - a Windows 11 install ISO and a disk image made with qemu-img + - a VNC client such as remote-viewer for the Setup pages + - optionally the VirtIO driver ISO + +Run as an unprivileged user with access to /dev/kvm. The script refuses to +run as root. + + +Usage +----- +Create a disk, then run the install: + + qemu-img create -f qcow2 win11.qcow2 64G + ./win11-qemu-install win11.iso win11.qcow2 + +QEMU runs in the foreground. Connect a VNC client and click through the +pages the answer file leaves alone: + + remote-viewer vnc://127.0.0.1:5900 + +A third argument names the VirtIO driver ISO. The install disk is then +attached over VirtIO, which is faster: + + ./win11-qemu-install win11.iso win11.qcow2 virtio-win.iso + +Setup shows an empty disk list until viostor is loaded by hand: + + Load driver -> virtio CD -> viostor -> w11 -> amd64 + +Without it the disk is attached over SATA/AHCI and Setup sees it with no +extra drivers. The same driver ISO covers network and balloon after the +install. + + +Configuration +------------- +Environment variables, all optional. + + - RAM_MB guest memory in MB during install (default 8192) + - SMP guest CPU count during install (default 8) + - IMAGE_FORMAT disk image format: qcow2 or raw (default qcow2) + - LOCAL_USER administrator account name (default user) + - LOCAL_PASS administrator account password (default 123456) + +Example: + + RAM_MB=16384 SMP=4 LOCAL_USER=admin LOCAL_PASS=hunter2 \ + ./win11-qemu-install win11.iso win11.qcow2 + + +Networking +---------- +The installer runs with -nic none. With no way to reach Microsoft, OOBE +settles for a local account instead of forcing an online one, and restarting +inside Setup changes nothing. Networking arrives when the installed image is +booted afterwards, with a NIC model Windows has an in-box driver for: + + qemu-system-x86_64 -enable-kvm -machine q35 -cpu host -m 8192 \ + -drive file=win11.qcow2,if=ide \ + -nic user,model=e1000e \ + -vnc 127.0.0.1:0 -usb -device usb-tablet + +Use if=virtio for the drive if the install ran in VirtIO mode. virtio-net +stays dead until NetKVM is installed from the driver ISO; e1000e works out +of the box. + + +Quirks +------ +The windowsPE pass is minimal on purpose. Automating the EULA, edition, and +disk pages with UserData, DiskConfiguration, and DriverPaths makes the +Windows 11 24H2 setup engine abort right after boot ("Windows installation +encountered an unexpected error", extend code 0x40031), so those pages are +left to the VNC session. + +The answer file is written to a per-run mktemp directory (mode 0700, under +TMPDIR), reaches the guest as fat:floppy:, and is removed by an EXIT trap. +SIGKILL and host failure cannot run the trap; remove stale +win11-qemu-install.* directories from TMPDIR after either. + +QEMU runs as a background command so HUP, INT, and TERM stop it and then +clean up, exiting 129, 130, or 143. In the foreground the trap would not run +until QEMU had already exited. + +LOCAL_USER and LOCAL_PASS are XML-escaped, so values containing & < > " ' +are safe. + + +Debugging +--------- +Watch the install over VNC. While QEMU runs the generated answer file can be +read at win11-qemu-install.*/Autounattend.xml under TMPDIR. + + - "must not contain a comma": QEMU separates drive options with commas; + use a path without one. + - Black VNC screen: Setup is still booting. + - Empty disk list in Setup: load the VirtIO driver as shown above, or + rerun without the VirtIO ISO for the SATA/AHCI path. + - "installation encountered an unexpected error" right after boot: the + answer file automates more of windowsPE than the setup engine accepts. + - KVM errors on start: check that /dev/kvm exists and is accessible. + + +Security +-------- +The default password is 123456 and the account is a local administrator, so +this is for throwaway lab VMs. Set LOCAL_PASS for anything kept. VNC has no +authentication and any local host user can reach the guest console; it is +bound to 127.0.0.1, and the QEMU monitor, serial port, and guest network are +not exposed. + +The answer file holds the password in plain text in the 0700 temp dir. QEMU +refuses to run as root and runs under its seccomp sandbox with privilege +elevation, process spawning, obsolete system calls, and resource-control +changes denied, but it still has the invoking user's file access. Use a +dedicated unprivileged account when installing untrusted media. |