CLI (nix run .#): - `vmix build` and `vmix copy` subcommands - --image, --generalize key=val, --to-disk, --to-remote-disk - SDL display auto-detected via DISPLAY temp file passthrough - --print-build-logs for visible build progress - -S 4k sparse writes for faster disk copy Images: - win10.laptop and win11.laptop bundles (no VirtIO, keeps defender/hibernation) - templates.bundles.laptop shared template list - win11 adds reg.disableUCPD on top Build improvements: - consistent === vmix: === log prefixes - SDL display via /tmp/.vmix-display-$$ temp file Env helpers: - .env-export-vmix-cli-local: vmix alias for local flake Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
80 lines
2.7 KiB
Nix
80 lines
2.7 KiB
Nix
# 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;
|
|
};
|
|
|
|
displayArg = if vncDisplay != null then "-vnc ${vncDisplay}" else null;
|
|
|
|
drv = pkgs.runCommand "${name}-vmix.qcow2" {
|
|
__noChroot = true;
|
|
requiredSystemFeatures = [ "kvm" ];
|
|
nativeBuildInputs = with pkgs; [ qemu ];
|
|
} ''
|
|
echo "=== vmix: creating ${diskSize} disk ==="
|
|
qemu-img create -f qcow2 disk.qcow2 ${diskSize}
|
|
|
|
cp ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd vars.fd
|
|
chmod +w vars.fd
|
|
|
|
echo "=== vmix: installing ${name} (unattended, 5-10 min) ==="
|
|
|
|
VMIX_DISPLAY="-nographic"
|
|
${lib.optionalString (displayArg != null) ''VMIX_DISPLAY="${displayArg}"''}
|
|
${lib.optionalString (displayArg == null) ''
|
|
VMIX_DF=$(ls -t /tmp/.vmix-display-* 2>/dev/null | head -1)
|
|
if [ -n "$VMIX_DF" ]; then
|
|
export DISPLAY=$(cat "$VMIX_DF")
|
|
VMIX_DISPLAY="-display sdl"
|
|
fi
|
|
''}
|
|
|
|
# Windows installs unattended, reboots into Audit Mode,
|
|
# deletes cached Autounattend, shuts down → QEMU exits.
|
|
timeout 3600 qemu-system-x86_64 \
|
|
$VMIX_DISPLAY \
|
|
-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 "=== vmix: ${name} install complete ==="
|
|
mv disk.qcow2 $out
|
|
'';
|
|
in drv // { _vmixOsType = "windows"; }
|