Skip to content

Configuration

Configuration file

The configuration file is optional and loaded from /etc/qm-template/config.toml when it exists; use --config PATH/-c or QM_TEMPLATE_CONFIG to point elsewhere. All commands work without a configuration file. Settings are validated with pydantic-settings; unknown keys and invalid values are rejected with the file and key path in the error. Every setting can also be overridden with a QM_TEMPLATE_* environment variable that uses __ for nesting, for example QM_TEMPLATE_DOWNLOAD__CONNECTIONS=4; environment variables take precedence over the file, and command-line options take precedence over both.

Downloaded images are stored in /var/lib/qm-template unless paths.images_dir overrides it, mirroring the upstream layout:

<images_dir>/<distro>/<release>/[<tag>/]<filename>

Settings

download.preferred orders the downloaders and download.connections sets the number of parallel connections for axel and aria2c. Downloads show progress by default; download.quiet = true or -q/--quiet hides it. Signed checksums and images are verified with gpg; set download.verify_signature = false to skip verification, for example when gnupg is not installed. prepare.preferred orders the ISO builders and defaults to genisoimage, xorriso, mkisofs.

cloudinit.user is the Cloud-Init login name; when empty the distro's usual name is used (debian, freebsd, ec2-user for Amazon Linux, ...) and admin is used when the image is not stored under a known distro directory. cloudinit.password is optional: an empty password means no password login, so SSH keys are required in that case. cloudinit.sshkeys/sshkeys_files list inline SSH public keys and key files whose contents are merged and deduplicated by key fingerprint; create and prepare require at least one key or a password. The password is masked in --dry-run output and debug logs. cloudinit.shell sets the login shell of the user created by the local seed ISO (prepare); set it to "" to keep the image's default shell, or to /bin/ash on Alpine Linux. Cloud-Init itself can configure several users in user-data, but Proxmox VE's managed Cloud-Init only exposes a single ciuser/cipassword (multiple users would need custom cicustom snippets), so [cloudinit] intentionally describes one user.

create.storage is the Proxmox storage for the imported disk and the Cloud-Init drive. create.cpu sets the CPU type passed to qm as cputype=... (default host, which is fast but prevents migration across CPU generations). create.firmware (auto, bios or uefi) selects the firmware; auto uses UEFI for images whose filename contains uefi (for example Fedora's UEFI-UKI variant) and BIOS for everything else. UEFI templates are created with --bios ovmf and an EFI disk (--efidisk0 <storage>:1,pre-enrolled-keys=0, so Secure Boot stays disabled). create.tags, create.pool, create.onboot and create.description add optional Proxmox metadata to the template. vmid.start and vmid.step (defaults 9000 and 1) drive automatic VM ID selection. Add -v (debug messages) or -vv (also log levels and timestamps) to any command for troubleshooting.

Remote Proxmox VE hosts

Optional [pve.<name>] sections describe remote Proxmox VE hosts for create --pve <name>. They need host, user, token_name and token_secret, plus import_storage to upload images; node is required on clusters with more than one node, and verify_ssl, port, timeout and task_timeout have sensible defaults. Nested [pve.<name>.create], [pve.<name>.vmid] and [pve.<name>.cloudinit] tables override the global sections for that host only. Keep the token secret out of the file with QM_TEMPLATE_PVE__<NAME>__TOKEN_SECRET, and make the file owner-readable only:

[pve.home]
host = "pve.home.arpa"
user = "qm-template@pve"
token_name = "automation"
token_secret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
import_storage = "local"

[pve.home.vmid]
start = 9000

See Create a template for what the remote mode requires on the Proxmox VE side.

Per-distro overrides

Per-distro overrides are optional and live under [distro.<name>]. They are not included in the default configuration printed by qm-template config; add them only when a distro should use something other than its built-in default:

[distro.debian]
release = "bookworm-backports"
arch = "arm64"
base_url = "https://mirror.example.org/debian-cloud"

Every parameter listed by qm-template distros is validated per distro and is also exposed as a command-line option for download (for example --release, --variant, --fs or --firmware); passing an option a distro does not declare is an error. base_url is the exception: it is configuration-only.

base_url points a distro at an upstream or mirror that mirrors the expected directory layout; the checksum file and its signature are fetched from the same base. Where upstream signs its metadata (Ubuntu, Fedora, Rocky, AlmaLinux, openSUSE, Alpine and Arch Linux) the signature is verified with gpg before the checksum is trusted, and the signing keys are fetched from the distro's canonical source - never from the mirror - with pinned fingerprints where upstream publishes stable keys. Debian, CentOS Stream and FreeBSD do not sign their cloud image metadata, and Amazon Linux's RSA signature is not verified yet; for those a mirror serves both the image and its checksum, so use a trusted mirror, or verify the checksum out of band, when authenticity matters.

Generate a configuration file

qm-template config prints the default configuration (with comments) to stdout; redirect it to create a starting point. --full also appends the per-distro default tables. The file is never written automatically:

install -d /etc/qm-template
qm-template config > /etc/qm-template/config.toml

# pin every distro parameter explicitly
qm-template config --full > /etc/qm-template/config.toml

config.example.toml in the repository is a symlink to the same file that is shipped inside the wheel.