diff --git a/README.md b/README.md index 31f3c50..c6cd965 100644 --- a/README.md +++ b/README.md @@ -117,9 +117,9 @@ does not run Windows Setup again. `build-windows-base.sh` makes that base image (by default at the path `./download-images.sh --print-path windows11` prints): it installs Windows unattended from the ISO in `install-iso/` (it does everything itself: answer file in `windows11/seed/`, QEMU hardware in `windows11/qemu/`; this -directory has no dependency on any other repository). The answer file logs on once -with the built-in Administrator, which it disables again, and runs -`sysprep /generalize` as its last step; the script waits for the guest to power +directory has no dependency on any other repository). The answer file boots +into audit mode (no account and no credentials are needed) and runs +`sysprep /generalize` there as its last step; the script waits for the guest to power off and stores the disk read-only. The image is clean and generic, like a cloud image: nothing but Windows, with no account, no SSH, no settings, no VirtIO or other hardware-specific drivers and no machine identity. Each VM is configured diff --git a/build-windows-base.sh b/build-windows-base.sh index 3350b70..4288708 100755 --- a/build-windows-base.sh +++ b/build-windows-base.sh @@ -6,13 +6,14 @@ # made once, and this script needs nothing outside this directory: # 1. an answer ISO is built from windows11/seed/Autounattend.xml; # 2. QEMU installs Windows unattended from the ISO into a scratch directory. -# After the first logon, the answer file runs sysprep /generalize, which -# removes the machine identity and shuts the guest down; +# The answer file then boots into audit mode, where it runs sysprep +# /generalize, which removes the machine identity and shuts the guest down; # 3. the shut-down disk is converted into the output file and made read-only. # The image holds nothing but Windows itself, like a cloud image: no VirtIO or # other hardware-specific drivers (the installation hardware, windows11/qemu, # only uses devices with inbox Windows drivers), no machine identity, no user -# account (the built-in Administrator is disabled), no SSH, no settings. Every +# account (the answer file holds no credentials either: audit mode needs no +# account; the built-in Administrator is disabled), no SSH, no settings. Every # VM is configured on its first boot: Windows looks for an Unattend.xml in the # root of an attached CD-ROM during its specialize and OOBE passes, and so # takes the host name, account, auto logon, SSH and so on from a seed ISO. diff --git a/windows11/seed/Autounattend.xml b/windows11/seed/Autounattend.xml index b0e7c31..a9aeb61 100644 --- a/windows11/seed/Autounattend.xml +++ b/windows11/seed/Autounattend.xml @@ -96,59 +96,45 @@ + - - en-US - en-US - en-US - en-US + + Audit + - + + - - true - true - true - 3 - - - - - Build-Only-1 - true</PlainText> - </AdministratorPassword> - </UserAccounts> - <AutoLogon> - <Enabled>true</Enabled> - <LogonCount>1</LogonCount> - <Username>Administrator</Username> - <Password> - <Value>Build-Only-1</Value> - <PlainText>true</PlainText> - </Password> - </AutoLogon> - <FirstLogonCommands> - <SynchronousCommand wcm:action="add"> + <RunSynchronous> + <RunSynchronousCommand wcm:action="add"> <Order>1</Order> <Description>Disable the built-in Administrator again</Description> - <CommandLine>net.exe user Administrator /active:no</CommandLine> - </SynchronousCommand> - <SynchronousCommand wcm:action="add"> + <Path>net.exe user Administrator /active:no</Path> + </RunSynchronousCommand> + <RunSynchronousCommand wcm:action="add"> <Order>2</Order> - <Description>Remove the cached copies of this answer file (Windows would read - them before the Unattend.xml on a seed ISO, and one has the build password) - and the setup logs</Description> - <CommandLine>cmd.exe /c "del /f /q C:\Windows\Panther\unattend*.xml C:\Windows\Panther\Unattend\unattend*.xml C:\Windows\Panther\*.log &amp; rd /s /q C:\Windows\Panther\UnattendGC &amp; exit /b 0"</CommandLine> - </SynchronousCommand> - <SynchronousCommand wcm:action="add"> + <Description>Turn hibernation off, which deletes hiberfil.sys (3 GB) from the image</Description> + <Path>powercfg.exe /hibernate off</Path> + </RunSynchronousCommand> + <RunSynchronousCommand wcm:action="add"> <Order>3</Order> + <Description>Remove the cached copies of this answer file (Windows would read + them before the Unattend.xml on a seed ISO) and the setup logs</Description> + <Path>cmd.exe /c "del /f /q C:\Windows\Panther\unattend*.xml C:\Windows\Panther\Unattend\unattend*.xml C:\Windows\Panther\*.log &amp; rd /s /q C:\Windows\Panther\UnattendGC &amp; exit /b 0"</Path> + </RunSynchronousCommand> + <RunSynchronousCommand wcm:action="add"> + <Order>4</Order> <Description>Generalize the image and power off</Description> - <CommandLine>C:\Windows\System32\Sysprep\sysprep.exe /generalize /oobe /shutdown /quiet</CommandLine> - </SynchronousCommand> - </FirstLogonCommands> + <Path>C:\Windows\System32\Sysprep\sysprep.exe /generalize /oobe /shutdown /quiet</Path> + </RunSynchronousCommand> + </RunSynchronous> </component> </settings> </unattend>