vmix.nix/wip/win10-update.session.md
Git Sagar f33b8e7ce3 WIP: add Windows Update template with online COM API updates
Add essentials.windowsUpdate template that boots Audit Mode, uses the
Windows Update COM API to search/download/install all available updates
(cumulative, .NET, Defender), handles multi-round reboots with Audit
Mode preservation, and compacts the image afterward.

Known issues being worked:
- Audit Mode preservation after update reboot needs verification
- Install takes ~60-90 min with 4GB RAM on slow machines

See wip/win10-update.session.md for full context and TODOs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-09 10:31:08 +05:30

5 KiB

Windows Update Template - Development Session

Goal

Create a customizeImage template that applies Windows Updates to an existing image via the Windows Update COM API in Audit Mode, then compacts the qcow2.

What was built

New files

  • lib/images/windows/templates/essentials/windows-update.nix — template that boots into Audit Mode, runs Windows Update via COM API, handles reboots automatically, compacts image

Modified files

  • lib/images/windows/helpers/customizeImage.nix — added compact, qemuTimeout parameters
  • lib/images/windows/templates/default.nix — wired windowsUpdate into essentials
  • lib/images/windows/win10/images.nix — added updated step between upstream and basic
  • lib/images/windows/win11/images.nix — same

New customizeImage parameters

  • compact ? false — flattens COW chain via qemu-img convert into standalone qcow2 (no backing file)
  • qemuTimeout ? 1800 — configurable QEMU timeout in seconds (was hardcoded 30 min)

How the template works

  1. Boots image in Audit Mode with QEMU user networking
  2. Starts wuauserv service, removes update-blocking policies
  3. Uses PowerShell COM API (Microsoft.Update.Session) to search, download, install updates
  4. Accepts EULAs, logs per-update results
  5. If reboot required: copies script, preserves Audit Mode registry keys, re-registers via RunOnce, reboots
  6. After reboot: continues with next round (up to maxRounds, default 3)
  7. When done: runs dism /Cleanup-Image /StartComponentCleanup /ResetBase, shuts down
  8. Host-side: qemu-img convert flattens COW chain (when compact=true)

Usage

# Online mode (default) - triggers Windows Update service
essentials.windowsUpdate {}
essentials.windowsUpdate { maxRounds = 5; }

# In image pipeline
updated = customizeImage upstream (templates.essentials.windowsUpdate {});
basic = customizeImageFold updated [ ... ];

Test results

What works

  • Windows Update service starts successfully in Audit Mode
  • COM API finds all available updates (cumulative, .NET, Defender, MSRT)
  • Downloads and installs 6 updates including:
    • 2026-05 Cumulative Update KB5087544
    • .NET Framework updates (KB5010472, KB5011048, KB5088859)
    • Windows Malicious Software Removal Tool (KB890830)
    • Microsoft Defender definitions (KB2267602)
  • compact flag works — produces standalone qcow2 without backing file
  • Image grows from 5.02 GB to ~8.33 GB with updates

Issues found and fixed during session

  1. First build (no service start): COM API found 0 updates because wuauserv wasn't running

    • Fix: added net start wuauserv + sc config wuauserv start= auto + remove blocking policies + 30s wait
  2. Wrapper deletes script before reboot: After round 1, the wrapper's del /q C:\vmix-audit-script.cmd runs before reboot completes, so RunOnce points to deleted file

    • Fix: script copies itself to C:\vmix-update-continue.cmd before rebooting; registers that path in RunOnce
  3. Audit Mode lost after reboot: Cumulative updates can reset the Audit Mode flag, causing Windows to enter OOBE instead of Audit Mode after reboot

    • Fix: explicitly set AuditBoot=1 and AuditInProgress=1 registry keys before rebooting
  4. No shutdown after round 2: When script runs from RunOnce (not wrapper), no shutdown command executes

    • Fix: script always calls shutdown /s /f /t 10 when done, regardless of invocation method

Remaining TODO (for next session on faster machine)

  • Verify the Audit Mode preservation fix (AuditBoot + AuditInProgress registry keys) actually works — last build was still in round 1 install when session ended
  • The cumulative update install takes ~60-90 min with 4GB RAM — consider using 8GB for faster builds
  • Test round 2 → round 3 flow (does it find additional updates after cumulative?)
  • Test with compact = true to verify final image is standalone
  • Test full pipeline: upstream → updated → basic → generalize
  • Test win11 images too
  • Consider: should windowsUpdate go before or after virtioTools in the pipeline? Currently it's before (applied to raw upstream), but having virtio drivers might help with disk I/O performance during update install
  • The template is impure (downloads from Microsoft during build) — document this clearly
  • Consider adding a maxRounds = 1 fast mode that skips the reboot cycle (just installs whatever doesn't need reboot)

Build command for testing

nix build --print-build-logs --impure --option sandbox relaxed --expr '
  let
    vmixLib = (builtins.getFlake "path:/storage/gitrepos/vmix.nix").lib.x86_64-linux;
    upstream = vmixLib.windows.images.win10.ltsc.upstream;
    withVirtio = vmixLib.windows.customizeImage upstream vmixLib.windows.templates.essentials.virtioTools;
    windowsUpdate = vmixLib.windows.templates.essentials.windowsUpdate {};
  in vmixLib.windows.customizeImage withVirtio (windowsUpdate // { vncDisplay = ":55"; compact = false; })
'

Monitor via VNC on port 5955 (localhost:55):

gvnccapture localhost:55 /tmp/screenshot.png