Copy Xauthority to a world-readable temp file so nix build users (nixbld*) can authenticate to X11. Add --option sandbox relaxed so __noChroot derivations can access the X11 socket and xauth file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
89 lines
3.3 KiB
Nix
89 lines
3.3 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
|
|
useAHCI ? false, # use AHCI storage instead of VirtIO (for physical hardware deployment)
|
|
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=$(sed -n '1p' "$VMIX_DF")
|
|
export XAUTHORITY=$(sed -n '2p' "$VMIX_DF")
|
|
export HOME=$(mktemp -d)
|
|
export XDG_RUNTIME_DIR=$HOME
|
|
export SDL_VIDEODRIVER=x11
|
|
VMIX_DISPLAY="-display sdl"
|
|
fi
|
|
''}
|
|
|
|
# Windows installs unattended, reboots into Audit Mode,
|
|
# deletes cached Autounattend, shuts down → QEMU exits.
|
|
QEMU_ARGS="-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 \
|
|
${if useAHCI
|
|
then "-drive file=disk.qcow2,format=qcow2,if=none,id=disk0 -device ide-hd,drive=disk0"
|
|
else "-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=${if useAHCI then "e1000" else "virtio-net-pci"}"
|
|
|
|
timeout 3600 qemu-system-x86_64 $VMIX_DISPLAY $QEMU_ARGS || \
|
|
if [[ "$VMIX_DISPLAY" == "-display sdl" ]]; then
|
|
echo "=== vmix: SDL failed, retrying headless ==="
|
|
cp ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd vars.fd && chmod +w vars.fd
|
|
timeout 3600 qemu-system-x86_64 -nographic $QEMU_ARGS
|
|
else
|
|
exit 1
|
|
fi
|
|
|
|
echo "=== vmix: ${name} install complete ==="
|
|
mv disk.qcow2 $out
|
|
'';
|
|
in drv // { _vmixOsType = "windows"; inherit useAHCI; }
|