115 lines
6.6 KiB
Markdown
115 lines
6.6 KiB
Markdown
# The Windows base image
|
|
|
|
Unlike Ubuntu, this one is installed by hand. There is no unattended path here
|
|
and that is deliberate: Windows licensing, edition choice and the out-of-box
|
|
experience are all decisions for the operator, not for a script.
|
|
|
|
## What is already prepared
|
|
|
|
/var/lib/owuivm/iso/Win11_25H2_English_x64_v2.iso the media you supplied
|
|
/var/lib/owuivm/iso/virtio-win.iso the driver disc
|
|
|
|
Both are recorded in `windows.manifest` and `virtio.manifest` with their
|
|
SHA-256. **Recorded, not verified** - unlike Ubuntu, there is no published
|
|
checksum list to compare a Windows ISO against, so the manifest says what the
|
|
file hashed to and nothing stronger. That difference is real and is not papered
|
|
over.
|
|
|
|
## Three things Windows needs that Ubuntu does not
|
|
|
|
All three are already in the launcher, applied only when the image is named
|
|
`windows`:
|
|
|
|
| Requirement | What is provided | What happens without it |
|
|
|---|---|---|
|
|
| **TPM 2.0** | `swtpm` on a unix socket, `tpm-tis` device | Setup stops at "This PC can't run Windows 11" |
|
|
| **Secure Boot** | `OVMF_CODE_4M.secboot.fd` + a variable store seeded from `OVMF_VARS_4M.ms.fd`, with `property=secure,value=on` so the guest cannot rewrite it | Same message. Microsoft's keys have to be *enrolled*, not just the firmware present |
|
|
| **virtio drivers** | `virtio-win.iso` attached as a second CD during the install only | Setup reports no drives to install to, which looks like a broken VM |
|
|
| **Hyper-V enlightenments** | fourteen `hv-*` flags on `-cpu`, Windows only | The machine is simply slow, and the host looks busy while the guest looks idle - measured at 347% CPU on an idle installer with the cgroup neither short of memory nor throttled |
|
|
| **`-rtc base=localtime`** | Windows only | The clock is hours out, so TLS verification fails and every download breaks in a way that reads as a network fault |
|
|
|
|
`swtpm` also needed an AppArmor exception: Ubuntu's shipped profile permits
|
|
libvirt's paths and nothing else, so the socket was refused with
|
|
`Could not open UnixIO socket: Permission denied` - a policy denial wearing a
|
|
permission error's clothes, with nothing in dmesg. See
|
|
`vm/host/apparmor-local-swtpm`.
|
|
|
|
## Installing it
|
|
|
|
1. Finish the Ubuntu image first, or close it. Only one maintenance machine
|
|
runs at a time and the prepare step refuses the second.
|
|
Starting a *frozen* image is always safe, at any time: it boots a throwaway
|
|
copy and cannot change what is on disk. That is the way to check that an
|
|
image still comes up before handing it to the agent.
|
|
2. **Tool Server VM Maintenance** on the desktop -> the Windows row ->
|
|
**Install from ISO**.
|
|
A blank 60 GB disk is created, the media is attached, and the console opens.
|
|
3. **Two prompts eat keystrokes before Windows does, in this order.** OVMF shows
|
|
its own "press a key for boot options" window for about five seconds - any
|
|
key there drops you into the firmware menu, not the installer (if that
|
|
happens: **Boot Manager** -> **UEFI QEMU DVD-ROM QM00001**, which is the
|
|
Windows ISO; QM00003 is virtio-win). Then the ISO itself shows "Press any
|
|
key to boot from CD or DVD" for about five seconds, and *that* one has to be
|
|
answered or the machine falls through to an EFI shell. So: let the firmware
|
|
window pass untouched, then press a key.
|
|
4. When setup asks where to install and shows no drives, choose **Load driver**,
|
|
browse the second CD, and take `amd64\w11` (or `amd64\2k25`). The disk
|
|
appears immediately afterwards.
|
|
5. Install normally. A local account is simplest - the machine has no way to
|
|
reach a Microsoft account sign-in that needs a phone, and nothing about this
|
|
image should depend on one.
|
|
|
|
## Before you shut down
|
|
|
|
The equivalents of what the Ubuntu image needed, and for the same reasons:
|
|
|
|
- **`qemu-guest-agent`** from the driver disc (`virtio-win-guest-tools.exe`, or
|
|
`guest-agent\qemu-ga-x86_64.msi`). This is the entire control channel; without
|
|
it the machine boots and is unreachable, which looks identical to a machine
|
|
that failed to boot.
|
|
- **Static networking**: address `10.0.2.15/24`, gateway `10.0.2.2`, DNS
|
|
`1.1.1.1`. DHCP hands out SLIRP's own resolver at `10.0.2.3`, which relays to
|
|
*this host's* resolver and is correctly blocked by the sandbox filter - giving
|
|
a machine with working TCP and no name resolution.
|
|
- **Auto-logon** for the admin account, so a GUI session has a desktop from boot
|
|
with no human. `netplwiz`, or `Set-LocalUser` plus the `AutoAdminLogon`
|
|
registry values.
|
|
- **The rest of virtio-win**, not just the storage driver setup needed: NetKVM
|
|
for the network, and the display driver in particular. Until it is installed
|
|
`virtio-vga` is a plain VGA framebuffer to Windows and every redraw is a full
|
|
repaint - which is most of what "the VM feels slow" turns out to be once the
|
|
enlightenments are on.
|
|
- **Turn off Windows Update's automatic reboots** and anything else that changes
|
|
the machine between sessions. Every session starts from this frozen disk, so
|
|
background change here is change in every future run.
|
|
|
|
## Then
|
|
|
|
Press **Shut down**. The guest is asked to power off over ACPI and systemd waits
|
|
for it, so this is the machine shutting itself down rather than the plug coming
|
|
out. The variable store is copied back on the way - a UEFI boot entry added by
|
|
setup is otherwise lost and the disk will not boot.
|
|
|
|
Then press **Freeze**, which is the operator's own button and is not done for
|
|
you: nothing re-freezes an image behind your back any more. Freezing sets `0444`
|
|
and records the checksum, and until it is done no agent session will start -
|
|
vmd refuses to open one on a writable base and says so.
|
|
|
|
Then press **Installed — remove disc**, which appears on the row while an
|
|
install is in progress and wakes up once the machine is stopped. That is what
|
|
says the install is finished: until it is pressed the installer media is still
|
|
attached at every boot, deliberately, because a machine shut down halfway
|
|
through setup needs its disc to be finished and nothing here can tell the two
|
|
cases apart. The disc first, the disk second - the boot order tries the disk and
|
|
falls through to the media, so an installed system boots itself either way and
|
|
the only cost of leaving it attached is the ISO staying open.
|
|
|
|
## Not yet done
|
|
|
|
Nothing on this page has been run. The Ubuntu path was measured end to end;
|
|
this one is written from the same code paths plus the documented Windows
|
|
requirements, and the first real install will find something. The argv it will
|
|
be given *is* asserted, by `tests/test_vm_launch_argv.sh`, which checks that the
|
|
Windows machine gets secure-boot firmware, a TPM and a protected variable store
|
|
while the Ubuntu one gets none of them.
|