aboutsummaryrefslogtreecommitdiff
path: root/README
blob: 85a6b9d288cbe0536ebb2b515c3da347910f2f4d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
win11-qemu-install
==================
Mostly-unattended install of Windows 11 onto a disk image under QEMU/KVM.
The script generates an Autounattend.xml, hands it to Windows Setup on a
virtual floppy, and runs QEMU against the install ISO and a target disk
created beforehand with qemu-img. The answer file presets the en-US locale,
bypasses the TPM 2.0, Secure Boot, and minimum RAM checks via LabConfig,
creates one local administrator, and auto-logs in once. The pages it leaves
alone (EULA, edition, target disk) are clicked once over VNC.

Whatever disk is picked on Setup's disk page is wiped.


Requirements
------------
  - qemu-system-x86_64 with KVM and seccomp sandbox support
  - a POSIX shell, sed, id, and mktemp
  - a Windows 11 install ISO and a disk image made with qemu-img
  - a VNC client such as remote-viewer for the Setup pages
  - optionally the VirtIO driver ISO

Run as an unprivileged user with access to /dev/kvm. The script refuses to
run as root.


Usage
-----
Create a disk, then run the install:

    qemu-img create -f qcow2 win11.qcow2 64G
    ./win11-qemu-install win11.iso win11.qcow2

QEMU runs in the foreground. Connect a VNC client and click through the
pages the answer file leaves alone:

    remote-viewer vnc://127.0.0.1:5900

A third argument names the VirtIO driver ISO. The install disk is then
attached over VirtIO, which is faster:

    ./win11-qemu-install win11.iso win11.qcow2 virtio-win.iso

Setup shows an empty disk list until viostor is loaded by hand:

    Load driver -> virtio CD -> viostor -> w11 -> amd64

Without it the disk is attached over SATA/AHCI and Setup sees it with no
extra drivers. The same driver ISO covers network and balloon after the
install.


Configuration
-------------
Environment variables, all optional.

  - RAM_MB        guest memory in MB during install (default 8192)
  - SMP           guest CPU count during install (default 8)
  - IMAGE_FORMAT  disk image format: qcow2 or raw (default qcow2)
  - LOCAL_USER    administrator account name (default user)
  - LOCAL_PASS    administrator account password (default 123456)

Example:

    RAM_MB=16384 SMP=4 LOCAL_USER=admin LOCAL_PASS=hunter2 \
        ./win11-qemu-install win11.iso win11.qcow2


Networking
----------
The installer runs with -nic none. With no way to reach Microsoft, OOBE
settles for a local account instead of forcing an online one, and restarting
inside Setup changes nothing. Networking arrives when the installed image is
booted afterwards, with a NIC model Windows has an in-box driver for:

    qemu-system-x86_64 -enable-kvm -machine q35 -cpu host -m 8192 \
        -drive file=win11.qcow2,if=ide \
        -nic user,model=e1000e \
        -vnc 127.0.0.1:0 -usb -device usb-tablet

Use if=virtio for the drive if the install ran in VirtIO mode. virtio-net
stays dead until NetKVM is installed from the driver ISO; e1000e works out
of the box.


Quirks
------
The windowsPE pass is minimal on purpose. Automating the EULA, edition, and
disk pages with UserData, DiskConfiguration, and DriverPaths makes the
Windows 11 24H2 setup engine abort right after boot ("Windows installation
encountered an unexpected error", extend code 0x40031), so those pages are
left to the VNC session.

The answer file is written to a per-run mktemp directory (mode 0700, under
TMPDIR), reaches the guest as fat:floppy:, and is removed by an EXIT trap.
SIGKILL and host failure cannot run the trap; remove stale
win11-qemu-install.* directories from TMPDIR after either.

QEMU runs as a background command so HUP, INT, and TERM stop it and then
clean up, exiting 129, 130, or 143. In the foreground the trap would not run
until QEMU had already exited.

LOCAL_USER and LOCAL_PASS are XML-escaped, so values containing & < > " '
are safe.


Debugging
---------
Watch the install over VNC. While QEMU runs the generated answer file can be
read at win11-qemu-install.*/Autounattend.xml under TMPDIR.

  - "must not contain a comma": QEMU separates drive options with commas;
    use a path without one.
  - Black VNC screen: Setup is still booting.
  - Empty disk list in Setup: load the VirtIO driver as shown above, or
    rerun without the VirtIO ISO for the SATA/AHCI path.
  - "installation encountered an unexpected error" right after boot: the
    answer file automates more of windowsPE than the setup engine accepts.
  - KVM errors on start: check that /dev/kvm exists and is accessible.


Security
--------
The default password is 123456 and the account is a local administrator, so
this is for throwaway lab VMs. Set LOCAL_PASS for anything kept. VNC has no
authentication and any local host user can reach the guest console; it is
bound to 127.0.0.1, and the QEMU monitor, serial port, and guest network are
not exposed.

The answer file holds the password in plain text in the 0700 temp dir. QEMU
refuses to run as root and runs under its seccomp sandbox with privilege
elevation, process spawning, obsolete system calls, and resource-control
changes denied, but it still has the invoking user's file access. Use a
dedicated unprivileged account when installing untrusted media.