Reading the installation files through QEMU's emulated USB CD-ROM runs at a
few MB/s on macOS. --install-from-img FILE (or WIN11_VM_INSTALL_IMG) attaches
an installation disk image built by vm-images/build-windows-install-disk.sh as
an NVMe disk instead, which is read about 15 times faster. The image is
attached with snapshot=on because NVMe cannot report write protection and
Windows fails on a read-only volume.
Add windows11-arm64-install-speed.md with the analysis and measurements.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Replace qemu/<guest>-<arch>.ini with qemu/<guest>-<os>-<arch>.ini, where os is
linux or darwin, the name platform.system() reports. The accelerators move out
of the shared <guest>.ini into these files (KVM on Linux, HVF on macOS, TCG as
the fallback). The launchers pick the file from the host system and
architecture, and reject amd64 guests on macOS hosts, so no darwin-amd64 files
exist.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Pick qemu-system-aarch64, the AArch64 UEFI firmware and a per-architecture
QEMU config (NVMe disk, virtio-net, ramfb, USB installation media) on arm64,
render the answer file for the target architecture, and move the q35-only
disk and NIC devices out of the shared config. Update vm-images to match
arm64 Windows ISO names.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Adds a -CopyInstallers switch to the Windows 11 configure script and enables
it in Autounattend.xml.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ws2tcp-local-gui needs qt_generate_deploy_app_script INCLUDE_PLUGINS, which
Qt 6.8 does not support.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Disables automatic Windows Update via policy, pins the current feature
release, and is enabled in Autounattend.xml.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Move the QEMU hardware definition of the Windows 11 VM into
qemu/windows11.ini and qemu/windows11-amd64.ini, loaded with -readconfig
like the Linux launchers. The network stays in the launcher because a
config file section cannot hold two hostfwd entries. Add --rdp-port and
--ssh-port, which override the WIN11_VM_*_PORT environment variables.
WIN11_VM_MEMORY and WIN11_VM_CPUS are replaced by the config file.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Relaunch as Administrator through UAC when needed, report success or
failure, and wait for Enter before the window closes. Autounattend.xml
passes -NoPause so the unattended install does not block.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Add -InstallVirtIO and -EnableAutomaticLogon switches to
Configure-Windows.ps1 so it can run standalone on a physical machine.
Autounattend.xml passes both switches during the virtual machine install.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Add run-ubuntu2604.py with its QEMU config files and NoCloud seed. The
launcher follows the Debian 13 one, with UBUNTU_VM_ settings and SSH
forwarded to host port 2225. The seed injects the current user's SSH public
key, uses the USTC mirror (ubuntu-ports on arm64) and installs the GNOME
desktop on first boot. Update vm-images for the ubuntu2604 image target.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kwxp2XWvKnuEBifnCbhyX5
Moving the SSH port forward into the QEMU config files dropped the
launchers' SSH hint. Read the host port forwarded to guest port 22 from
the rendered config and print the matching ssh command.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdbBg69LciFz8kjVCtnkbj
user-data is now a template with an @SSH_PUBKEY@ placeholder that
build-seed.sh fills in from SSH_PUBKEY_FILE, ~/.ssh/id_*.pub or ssh-agent.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A [netdev] in a -readconfig file does not stop QEMU from adding its
default NIC, so the guests had a second user-mode network without the
SSH port forward. Both NICs got 10.0.2.15 over DHCP, and SSH only worked
on boots where the forwarded NIC won the race for the default route.
Removing the default NIC shifts the other PCI devices down one slot, so
existing VMs may need their UEFI variable store reset to boot again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The option downloads the media a launcher would fetch automatically and
exits without checking for QEMU, creating a VM disk or starting the VM:
the base image for Debian, AlmaLinux and Fedora, and the VirtIO tools
ISO for Windows 11.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKxXLyiL7XJ3a9e8HmR2my
Apply the Debian launcher's config file layout to Fedora: the shared
qemu/fedora44.ini and qemu/fedora44-<arch>.ini replace the inline QEMU
arguments and the FEDORA_VM_MEMORY, FEDORA_VM_CPUS and
FEDORA_VM_SSH_PORT variables; FEDORA_VM_QEMU_CONFIG selects a different
shared config file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKxXLyiL7XJ3a9e8HmR2my
Move the Debian launcher's QEMU arguments into qemu/debian13.ini, which
the launcher renders with the per-run file paths and passes to QEMU with
-readconfig, followed by qemu/debian13-<arch>.ini for the machine type
and arm64-only devices. Memory, CPU count, SSH port and accelerator are
now set in the config files, replacing VM_MEMORY, VM_CPUS and
VM_SSH_PORT; VM_QEMU_CONFIG selects a different shared config file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YKxXLyiL7XJ3a9e8HmR2my
Let each run-*.py launcher take the VM directory (disk, seed ISO, UEFI
variables, PID file, console log) from the command line, taking
precedence over the *_STATE_DIR environment variable. Paths derived
from the state directory are now computed after argument parsing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1dybYsc36kf3gUPB7NuNB
Each run-*.py mirrors its run-*.sh counterpart: same options, environment
variables, messages and QEMU command line. Unlike the shell scripts, the
Python ports use a portable /usr/bin/env shebang.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S8ZGHSJ5JogcTAYhPNxXTV