Use vm/ instead of the hidden .vm/ as the default state directory

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
guofangandClaude Sonnet 5.5 committed 2026-10-23 23:41:21 +08:00
1 parent 2fe0d568ce
commit 69e2141b7c
7 files changed
+32 -32

No files matched your search

+2 -2
View File
@@ -1,5 +1,5 @@
# QEMU runtime state and writable overlays # QEMU runtime state and writable overlays (vm/ in the repository root)
.vm /vm/
# VM disk and generated installation/seed images # VM disk and generated installation/seed images
*.qcow2 *.qcow2
+13 -13
View File
@@ -21,7 +21,7 @@ background while still showing the graphical window:
``` ```
The launcher uses KVM when `/dev/kvm` is accessible, forwards host port `2222` The launcher uses KVM when `/dev/kvm` is accessible, forwards host port `2222`
to guest port `22`, and creates `.vm/debian13/disk.qcow2` as a 20G writable overlay with the to guest port `22`, and creates `vm/debian13/disk.qcow2` as a 20G writable overlay with the
original qcow2 image as its backing file. The base image therefore stays original qcow2 image as its backing file. The base image therefore stays
unchanged. Run `./run-debian13.py --help` for the supported environment unchanged. Run `./run-debian13.py --help` for the supported environment
variables. variables.
@@ -32,14 +32,14 @@ architecture-specific devices are in `qemu/debian13-<os>-<arch>.ini`
(os `linux` or `darwin`, arch `amd64` or `arm64`), together with the (os `linux` or `darwin`, arch `amd64` or `arm64`), together with the
accelerators. Edit these files to change the settings. The accelerators. Edit these files to change the settings. The
launcher fills in the `${...}` file path placeholders of `qemu/debian13.ini`, launcher fills in the `${...}` file path placeholders of `qemu/debian13.ini`,
writes the result to `.vm/debian13/qemu.ini` and starts QEMU with writes the result to `vm/debian13/qemu.ini` and starts QEMU with
`-readconfig` for that file followed by the one for the host system and guest architecture. `-readconfig` for that file followed by the one for the host system and guest architecture.
QEMU arguments given after `--` override the config files, for example QEMU arguments given after `--` override the config files, for example
`./run-debian13.py -- -m 4G -smp 4`. `./run-debian13.py -- -m 4G -smp 4`.
The launchers accept `--state-dir DIR` to keep The launchers accept `--state-dir DIR` to keep
the VM disk, seed ISO, UEFI variables, PID file and console log in `DIR` the VM disk, seed ISO, UEFI variables, PID file and console log in `DIR`
instead of the default `.vm/<name>/`. The option takes precedence over the instead of the default `vm/<name>/`. The option takes precedence over the
corresponding `*_STATE_DIR` environment variable: corresponding `*_STATE_DIR` environment variable:
```bash ```bash
@@ -55,7 +55,7 @@ for Windows 11 (whose installation ISO and base QCOW2 are supplied manually):
./run-fedora44.py --download-only ./run-fedora44.py --download-only
``` ```
If `.vm/debian13/seed.iso` is missing, the launcher automatically builds it If `vm/debian13/seed.iso` is missing, the launcher automatically builds it
from `seediso/debian13/user-data`, `seediso/debian13/meta-data`, and from `seediso/debian13/user-data`, `seediso/debian13/meta-data`, and
`seediso/debian13/network-config` before starting the VM. `seediso/debian13/network-config` before starting the VM.
@@ -84,7 +84,7 @@ Start an AlmaLinux 10 Generic Cloud VM with:
When the shared AlmaLinux image is missing, the launcher calls the selected When the shared AlmaLinux image is missing, the launcher calls the selected
image helper with `almalinux10`. It creates the writable image helper with `almalinux10`. It creates the writable
overlay `.vm/almalinux10/disk.qcow2` and uses the NoCloud configuration in overlay `vm/almalinux10/disk.qcow2` and uses the NoCloud configuration in
`seediso/almalinux10/`. SSH is forwarded to host port `2223` by default: `seediso/almalinux10/`. SSH is forwarded to host port `2223` by default:
```bash ```bash
@@ -98,9 +98,9 @@ ALMA_VM_MEMORY=4G ALMA_VM_CPUS=4 ALMA_VM_SSH_PORT=2224 ./run-almalinux10.py
``` ```
Run `./run-almalinux10.py --help` for all supported settings. The seed ISO is Run `./run-almalinux10.py --help` for all supported settings. The seed ISO is
stored alongside the VM disk at `.vm/almalinux10/seed.iso`. If it already stored alongside the VM disk at `vm/almalinux10/seed.iso`. If it already
exists after editing its source files, rebuild it explicitly with exists after editing its source files, rebuild it explicitly with
`./seediso/almalinux10/build-seed.sh .vm/almalinux10/seed.iso`. `./seediso/almalinux10/build-seed.sh vm/almalinux10/seed.iso`.
## Fedora 44 ## Fedora 44
@@ -111,7 +111,7 @@ Start a Fedora 44 Cloud Base VM with:
``` ```
The launcher downloads the `fedora44` image through the shared helper when it The launcher downloads the `fedora44` image through the shared helper when it
is missing, creates `.vm/fedora44/disk.qcow2`, and builds its NoCloud seed from is missing, creates `vm/fedora44/disk.qcow2`, and builds its NoCloud seed from
`seediso/fedora44/`. SSH is forwarded to host port `2224` by default: `seediso/fedora44/`. SSH is forwarded to host port `2224` by default:
```bash ```bash
@@ -136,7 +136,7 @@ Start an Ubuntu 26.04 LTS (Resolute Raccoon) cloud image VM with:
``` ```
The launcher downloads the `ubuntu2604` image through the shared helper when The launcher downloads the `ubuntu2604` image through the shared helper when
it is missing, creates `.vm/ubuntu2604/disk.qcow2`, and builds its NoCloud seed it is missing, creates `vm/ubuntu2604/disk.qcow2`, and builds its NoCloud seed
from `seediso/ubuntu2604/`. Like the Debian seed, it injects the current user's from `seediso/ubuntu2604/`. Like the Debian seed, it injects the current user's
SSH public key and points APT at the USTC mirror (`ubuntu-ports` on arm64). SSH public key and points APT at the USTC mirror (`ubuntu-ports` on arm64).
SSH is forwarded to host port `2225` by default: SSH is forwarded to host port `2225` by default:
@@ -165,7 +165,7 @@ from the shared Windows 11 QCOW2 base image:
./run-windows11.py ./run-windows11.py
``` ```
It creates a persistent 64G disk at `.vm/windows11/disk.qcow2`, automatically It creates a persistent 64G disk at `vm/windows11/disk.qcow2`, automatically
partitions it, completes OOBE, creates the local administrator `guofang` with partitions it, completes OOBE, creates the local administrator `guofang` with
the initial password `wang`, and enables Remote Desktop on the initial password `wang`, and enables Remote Desktop on
`localhost:3389`. During the first login it also silently installs the VirtIO `localhost:3389`. During the first login it also silently installs the VirtIO
@@ -173,7 +173,7 @@ drivers (the guest tools installer on amd64, the Arm64 driver packages from the
VirtIO ISO with `pnputil` on arm64), without which the guest has no network on VirtIO ISO with `pnputil` on arm64), without which the guest has no network on
arm64. The installer includes the VirtIO drivers, SPICE vdagent, and QEMU Guest arm64. The installer includes the VirtIO drivers, SPICE vdagent, and QEMU Guest
Agent. The launcher exposes the vdagent channel for host/guest clipboard Agent. The launcher exposes the vdagent channel for host/guest clipboard
integration and the QEMU Guest Agent at `.vm/windows11/qemu-guest-agent.sock`. integration and the QEMU Guest Agent at `vm/windows11/qemu-guest-agent.sock`.
Change the password after first login. The OpenSSH Server is installed during Change the password after first login. The OpenSSH Server is installed during
the first logon from the Win32-OpenSSH zip for the host architecture, which the the first logon from the Win32-OpenSSH zip for the host architecture, which the
seed ISO carries (downloaded by `vm-images/download-images.sh openssh-win`), so seed ISO carries (downloaded by `vm-images/download-images.sh openssh-win`), so
@@ -184,11 +184,11 @@ administrator login.
The Windows VM hardware (8G memory, 8 CPUs, system disk, devices) The Windows VM hardware (8G memory, 8 CPUs, system disk, devices)
is defined in `qemu/windows11.ini`, with the accelerators and machine type in is defined in `qemu/windows11.ini`, with the accelerators and machine type in
`qemu/windows11-<os>-<arch>.ini`; the launcher renders the former to `qemu/windows11-<os>-<arch>.ini`; the launcher renders the former to
`.vm/windows11/qemu.ini` and loads both with `-readconfig`. Only the network `vm/windows11/qemu.ini` and loads both with `-readconfig`. Only the network
and the installation media are still set by the launcher. QEMU arguments after and the installation media are still set by the launcher. QEMU arguments after
`--` override the config files, for example `./run-windows11.py -- -m 4G -smp 4`. `--` override the config files, for example `./run-windows11.py -- -m 4G -smp 4`.
The generated answer-file ISO is stored beside the disk as The generated answer-file ISO is stored beside the disk as
`.vm/windows11/seed.iso`. `vm/windows11/seed.iso`.
To install from the Windows ISO instead, use `./run-windows11.py To install from the Windows ISO instead, use `./run-windows11.py
--install-from-iso`. This choice only applies while creating a missing system --install-from-iso`. This choice only applies while creating a missing system
+3 -3
View File
@@ -51,7 +51,7 @@ else:
base_image = Path(result.stdout.rstrip("\n")) base_image = Path(result.stdout.rstrip("\n"))
uses_shared_base_image = True uses_shared_base_image = True
state_dir = Path(env("ALMA_VM_STATE_DIR") or script_dir / ".vm" / "almalinux10") state_dir = Path(env("ALMA_VM_STATE_DIR") or script_dir / "vm" / "almalinux10")
disk_size = env("ALMA_VM_DISK_SIZE") or "20G" disk_size = env("ALMA_VM_DISK_SIZE") or "20G"
memory = env("ALMA_VM_MEMORY") or "8G" memory = env("ALMA_VM_MEMORY") or "8G"
cpus = env("ALMA_VM_CPUS") or "8" cpus = env("ALMA_VM_CPUS") or "8"
@@ -132,7 +132,7 @@ Options:
--daemon Run in the background while keeping the graphical window --daemon Run in the background while keeping the graphical window
--download-only Download the base image if it is missing, then exit --download-only Download the base image if it is missing, then exit
--state-dir DIR Directory for the VM disk, seed ISO and runtime files --state-dir DIR Directory for the VM disk, seed ISO and runtime files
(default: .vm/almalinux10; overrides ALMA_VM_STATE_DIR) (default: vm/almalinux10; overrides ALMA_VM_STATE_DIR)
-h, --help Show this help -h, --help Show this help
Environment variables: Environment variables:
@@ -141,7 +141,7 @@ Environment variables:
ALMA_VM_SSH_PORT Host port forwarded to guest SSH (default: 2223) ALMA_VM_SSH_PORT Host port forwarded to guest SSH (default: 2223)
ALMA_VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper) ALMA_VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper)
ALMA_VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk) ALMA_VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk)
ALMA_VM_STATE_DIR Runtime state directory (default: .vm/almalinux10) ALMA_VM_STATE_DIR Runtime state directory (default: vm/almalinux10)
ALMA_VM_DISK_IMAGE Writable overlay path ALMA_VM_DISK_IMAGE Writable overlay path
ALMA_VM_DISK_SIZE New overlay virtual capacity (default: 20G) ALMA_VM_DISK_SIZE New overlay virtual capacity (default: 20G)
VM_IMAGE_ARCH Guest/host architecture: arm64 or amd64 (default: auto-detected from the host) VM_IMAGE_ARCH Guest/host architecture: arm64 or amd64 (default: auto-detected from the host)
+4 -4
View File
@@ -53,7 +53,7 @@ else:
base_image = Path(result.stdout.rstrip("\n")) base_image = Path(result.stdout.rstrip("\n"))
uses_shared_base_image = True uses_shared_base_image = True
state_dir = Path(env("VM_STATE_DIR") or script_dir / ".vm" / "debian13") state_dir = Path(env("VM_STATE_DIR") or script_dir / "vm" / "debian13")
disk_size = env("VM_DISK_SIZE") or "20G" disk_size = env("VM_DISK_SIZE") or "20G"
@@ -124,7 +124,7 @@ def usage(stream=sys.stdout):
Usage: {Path(sys.argv[0]).name} [--daemon] [--download-only] [--state-dir DIR] [-- QEMU_ARGUMENT ...] Usage: {Path(sys.argv[0]).name} [--daemon] [--download-only] [--state-dir DIR] [-- QEMU_ARGUMENT ...]
Start the Debian 13 virtual machine. A writable overlay is created in the state Start the Debian 13 virtual machine. A writable overlay is created in the state
directory (default: .vm/debian13/), so the downloaded base image is never directory (default: vm/debian13/), so the downloaded base image is never
modified. The VM hardware (memory, CPUs, SSH port forward, ...) is defined in modified. The VM hardware (memory, CPUs, SSH port forward, ...) is defined in
qemu/debian13.ini, which is rendered to qemu.ini in the state directory and qemu/debian13.ini, which is rendered to qemu.ini in the state directory and
loaded with QEMU's -readconfig, followed by qemu/debian13-<os>-<arch>.ini (os is linux or darwin, arch is amd64 or arm64). Later loaded with QEMU's -readconfig, followed by qemu/debian13-<os>-<arch>.ini (os is linux or darwin, arch is amd64 or arm64). Later
@@ -134,13 +134,13 @@ Options:
--daemon Run in the background while keeping the graphical window --daemon Run in the background while keeping the graphical window
--download-only Download the base image if it is missing, then exit --download-only Download the base image if it is missing, then exit
--state-dir DIR Directory for the VM disk, seed ISO and runtime files --state-dir DIR Directory for the VM disk, seed ISO and runtime files
(default: .vm/debian13; overrides VM_STATE_DIR) (default: vm/debian13; overrides VM_STATE_DIR)
-h, --help Show this help -h, --help Show this help
Environment variables: Environment variables:
VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper) VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper)
VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk) VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk)
VM_STATE_DIR Runtime state directory (default: .vm/debian13) VM_STATE_DIR Runtime state directory (default: vm/debian13)
VM_DISK_IMAGE Writable overlay path VM_DISK_IMAGE Writable overlay path
VM_DISK_SIZE New overlay virtual capacity (default: 20G) VM_DISK_SIZE New overlay virtual capacity (default: 20G)
VM_IMAGE_ARCH Guest/host architecture: arm64 or amd64 (default: auto-detected from the host) VM_IMAGE_ARCH Guest/host architecture: arm64 or amd64 (default: auto-detected from the host)
+3 -3
View File
@@ -53,7 +53,7 @@ else:
base_image = Path(result.stdout.rstrip("\n")) base_image = Path(result.stdout.rstrip("\n"))
uses_shared_base_image = True uses_shared_base_image = True
state_dir = Path(env("FEDORA_VM_STATE_DIR") or script_dir / ".vm" / "fedora44") state_dir = Path(env("FEDORA_VM_STATE_DIR") or script_dir / "vm" / "fedora44")
disk_size = env("FEDORA_VM_DISK_SIZE") or "20G" disk_size = env("FEDORA_VM_DISK_SIZE") or "20G"
@@ -136,13 +136,13 @@ Options:
--daemon Run in the background while keeping the graphical window --daemon Run in the background while keeping the graphical window
--download-only Download the base image if it is missing, then exit --download-only Download the base image if it is missing, then exit
--state-dir DIR Directory for the VM disk, seed ISO and runtime files --state-dir DIR Directory for the VM disk, seed ISO and runtime files
(default: .vm/fedora44; overrides FEDORA_VM_STATE_DIR) (default: vm/fedora44; overrides FEDORA_VM_STATE_DIR)
-h, --help Show this help -h, --help Show this help
Environment variables: Environment variables:
FEDORA_VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper) FEDORA_VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper)
FEDORA_VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk) FEDORA_VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk)
FEDORA_VM_STATE_DIR Runtime state directory (default: .vm/fedora44) FEDORA_VM_STATE_DIR Runtime state directory (default: vm/fedora44)
FEDORA_VM_DISK_IMAGE Writable overlay path FEDORA_VM_DISK_IMAGE Writable overlay path
FEDORA_VM_DISK_SIZE New overlay virtual capacity (default: 20G) FEDORA_VM_DISK_SIZE New overlay virtual capacity (default: 20G)
VM_IMAGE_ARCH Guest/host architecture: arm64 or amd64 (default: auto-detected from the host) VM_IMAGE_ARCH Guest/host architecture: arm64 or amd64 (default: auto-detected from the host)
+4 -4
View File
@@ -53,7 +53,7 @@ else:
base_image = Path(result.stdout.rstrip("\n")) base_image = Path(result.stdout.rstrip("\n"))
uses_shared_base_image = True uses_shared_base_image = True
state_dir = Path(env("UBUNTU_VM_STATE_DIR") or script_dir / ".vm" / "ubuntu2604") state_dir = Path(env("UBUNTU_VM_STATE_DIR") or script_dir / "vm" / "ubuntu2604")
disk_size = env("UBUNTU_VM_DISK_SIZE") or "20G" disk_size = env("UBUNTU_VM_DISK_SIZE") or "20G"
@@ -125,7 +125,7 @@ def usage(stream=sys.stdout):
Usage: {Path(sys.argv[0]).name} [--daemon] [--download-only] [--state-dir DIR] [-- QEMU_ARGUMENT ...] Usage: {Path(sys.argv[0]).name} [--daemon] [--download-only] [--state-dir DIR] [-- QEMU_ARGUMENT ...]
Start an Ubuntu 26.04 LTS cloud image virtual machine. A writable overlay is Start an Ubuntu 26.04 LTS cloud image virtual machine. A writable overlay is
created in the state directory (default: .vm/ubuntu2604/), so the downloaded created in the state directory (default: vm/ubuntu2604/), so the downloaded
base image is never modified. The VM hardware (memory, CPUs, SSH port forward, base image is never modified. The VM hardware (memory, CPUs, SSH port forward,
...) is defined in qemu/ubuntu2604.ini, which is rendered to qemu.ini in the ...) is defined in qemu/ubuntu2604.ini, which is rendered to qemu.ini in the
state directory and loaded with QEMU's -readconfig, followed by state directory and loaded with QEMU's -readconfig, followed by
@@ -136,13 +136,13 @@ Options:
--daemon Run in the background while keeping the graphical window --daemon Run in the background while keeping the graphical window
--download-only Download the base image if it is missing, then exit --download-only Download the base image if it is missing, then exit
--state-dir DIR Directory for the VM disk, seed ISO and runtime files --state-dir DIR Directory for the VM disk, seed ISO and runtime files
(default: .vm/ubuntu2604; overrides UBUNTU_VM_STATE_DIR) (default: vm/ubuntu2604; overrides UBUNTU_VM_STATE_DIR)
-h, --help Show this help -h, --help Show this help
Environment variables: Environment variables:
UBUNTU_VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper) UBUNTU_VM_BASE_IMAGE Base qcow2 image path (default: resolved by shared image helper)
UBUNTU_VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk) UBUNTU_VM_SEED_IMAGE cloud-init seed ISO path (default: alongside the VM disk)
UBUNTU_VM_STATE_DIR Runtime state directory (default: .vm/ubuntu2604) UBUNTU_VM_STATE_DIR Runtime state directory (default: vm/ubuntu2604)
UBUNTU_VM_DISK_IMAGE Writable overlay path UBUNTU_VM_DISK_IMAGE Writable overlay path
UBUNTU_VM_DISK_SIZE New overlay virtual capacity (default: 20G) UBUNTU_VM_DISK_SIZE New overlay virtual capacity (default: 20G)
VM_IMAGE_ARCH Guest/host architecture: arm64 or amd64 (default: auto-detected from the host) VM_IMAGE_ARCH Guest/host architecture: arm64 or amd64 (default: auto-detected from the host)
+3 -3
View File
@@ -61,7 +61,7 @@ def find_image_downloader():
return image_downloader return image_downloader
state_dir = Path(env("WIN11_VM_STATE_DIR") or script_dir / ".vm" / "windows11") state_dir = Path(env("WIN11_VM_STATE_DIR") or script_dir / "vm" / "windows11")
disk_size = env("WIN11_VM_DISK_SIZE") or "64G" disk_size = env("WIN11_VM_DISK_SIZE") or "64G"
rdp_port = env("WIN11_VM_RDP_PORT") or "3389" rdp_port = env("WIN11_VM_RDP_PORT") or "3389"
ssh_port = env("WIN11_VM_SSH_PORT") or "2222" ssh_port = env("WIN11_VM_SSH_PORT") or "2222"
@@ -116,7 +116,7 @@ Options:
overrides VM_IMAGE_ARCH). A guest that differs from the overrides VM_IMAGE_ARCH). A guest that differs from the
host runs under slow TCG emulation host runs under slow TCG emulation
--state-dir DIR Directory for the VM disk, seed ISO and runtime files --state-dir DIR Directory for the VM disk, seed ISO and runtime files
(default: .vm/windows11; overrides WIN11_VM_STATE_DIR) (default: vm/windows11; overrides WIN11_VM_STATE_DIR)
--rdp-port PORT Host port forwarded to guest RDP (default: 3389; --rdp-port PORT Host port forwarded to guest RDP (default: 3389;
overrides WIN11_VM_RDP_PORT) overrides WIN11_VM_RDP_PORT)
--ssh-port PORT Host port forwarded to guest SSH (default: 2222; --ssh-port PORT Host port forwarded to guest SSH (default: 2222;
@@ -130,7 +130,7 @@ Environment variables:
WIN11_VM_TOOLS_ISO VirtIO Windows tools ISO (default: resolved by shared image helper) WIN11_VM_TOOLS_ISO VirtIO Windows tools ISO (default: resolved by shared image helper)
WIN11_VM_RDP_PORT Host RDP port (default: 3389) WIN11_VM_RDP_PORT Host RDP port (default: 3389)
WIN11_VM_SSH_PORT Host SSH port (default: 2222) WIN11_VM_SSH_PORT Host SSH port (default: 2222)
WIN11_VM_STATE_DIR Runtime directory (default: .vm/windows11) WIN11_VM_STATE_DIR Runtime directory (default: vm/windows11)
WIN11_VM_DISK_IMAGE System disk path WIN11_VM_DISK_IMAGE System disk path
WIN11_VM_DISK_SIZE New system disk size (default: 64G) WIN11_VM_DISK_SIZE New system disk size (default: 64G)
WIN11_VM_SEED_ISO Answer-file ISO path (default: alongside the VM disk) WIN11_VM_SEED_ISO Answer-file ISO path (default: alongside the VM disk)