From 6a62a649bd407576d6595a90fa111da75512eca3 Mon Sep 17 00:00:00 2001 From: Git Sagar Date: Thu, 10 Sep 2026 07:28:14 -0300 Subject: [PATCH] generalize: assert the static address per boot, not once during the build Setting it from post-oobe.cmd could never have worked, and the reason is worth writing down. Without delayOobeRun, OOBE runs inside the build VM -- whose NIC is qemu user networking, on a different subnet, with a different MAC. The address was being applied to an adapter that does not exist on the real host. Windows then meets the target's NIC as new hardware and defaults to DHCP. RDP came through the same script unharmed because its settings are registry-wide rather than per-adapter, which is why one worked and the other did not despite sitting a few lines apart. So the script is now registered as an onstart scheduled task running as SYSTEM. It was already idempotent, and per-boot also survives the adapter being replaced again later. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0117qMyjpuXsjpVAcpJbFD8g --- lib/images/windows/templates/generalize.nix | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/images/windows/templates/generalize.nix b/lib/images/windows/templates/generalize.nix index 5db8285..52109d6 100644 --- a/lib/images/windows/templates/generalize.nix +++ b/lib/images/windows/templates/generalize.nix @@ -238,8 +238,13 @@ in ${lib.optionalString (staticIP != null) '' :: This VM's only NIC sits on a macvtap bridged to the host's LAN, so its :: address is a LAN address that nothing hands out -- the guest asserts it. - :: Clearing first makes the command idempotent across re-runs. - call C:\vmix-static-ip.cmd + :: Registered to run at every boot rather than applied here. OOBE runs in + :: the build VM, whose NIC is qemu user networking on another subnet with + :: another MAC -- so an address set now lands on an adapter that does not + :: exist on the real host. Windows sees the target's NIC as new hardware + :: and falls back to DHCP, which is exactly what happened. Per-boot also + :: survives the adapter being replaced again later. + schtasks /create /tn "vmix-static-ip" /tr "C:\vmix-static-ip.cmd" /sc onstart /ru SYSTEM /rl HIGHEST /f > nul 2>&1 ''} ${lib.optionalString (writeFilter != null) ''