# Build a pre-installed Windows qcow2 image using QEMU unattended install. # Boots into Audit Mode after install and shuts down. # Apply templates via customizeImageFold to install software (auditScript) # and customize registry (windowsRegistry), then generalize when done. { pkgs, lib, drivers, makeWinISO, makeAuditModeAutounattend, ... }: { name ? "windows", upstreamISO, productKey ? "", imageIndex ? 1, diskSize ? "64G", bypassRequirements ? false, locale ? "en-US", efi ? true, smp ? 4, memSize ? 4096, vncDisplay ? null, # e.g. ":10" to enable VNC on port 5910 for monitoring windowsVersionForVirtioDrivers ? "w10", # "w10", "w11", "2k22", "2k19", etc. }: let AutounattendedXml = makeAuditModeAutounattend { inherit locale productKey imageIndex efi bypassRequirements windowsVersionForVirtioDrivers; diskIndex = 0; virtioDriverLetter = "E"; }; iso = makeWinISO { iso = upstreamISO; inherit AutounattendedXml; }; drv = pkgs.runCommand "${name}-vmix.qcow2" { __noChroot = true; requiredSystemFeatures = [ "kvm" ]; nativeBuildInputs = with pkgs; [ qemu ]; } '' # create empty disk qemu-img create -f qcow2 disk.qcow2 ${diskSize} # writable UEFI NVRAM so boot order persists across reboots cp ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd vars.fd chmod +w vars.fd echo "=== Starting Windows unattended install (this takes 15-30 minutes) ===" # Windows installs unattended, reboots into Audit Mode, # deletes cached Autounattend, shuts down → QEMU exits. timeout 3600 qemu-system-x86_64 \ ${if vncDisplay != null then "-vnc ${vncDisplay}" else "-nographic"} \ -accel kvm \ -m ${toString memSize} \ -smp ${toString smp} \ -cpu host \ -machine type=q35 \ -drive if=pflash,format=raw,readonly=on,file=${pkgs.OVMF.fd}/FV/OVMF_CODE.fd \ -drive if=pflash,format=raw,file=vars.fd \ -rtc base=localtime,clock=host \ -device qemu-xhci -device usb-tablet \ -global ICH9-LMB.disable_s3=1 -global ICH9-LMB.disable_s4=1 \ -drive file=disk.qcow2,format=qcow2,if=virtio \ -drive file=${iso},media=cdrom,readonly=on \ -drive file=${drivers.virtio-iso},media=cdrom,readonly=on \ -nic user,model=virtio-net-pci echo "=== Windows install complete (Audit Mode image) ===" mv disk.qcow2 $out ''; in drv // { _vmixOsType = "windows"; }