Reference · reference
Guest OS profile files
A guest OS profile is a named bundle of known-good hardware defaults. It is the floor of the hardware resolution chain: a value not set on the VM and not recorded by its template comes from the profile. Profiles are data, shipped as WCL and extensible from a directory in your config. Guest OS profiles explains when to write one; this chapter lists the fields, the shipped set and where user files go.
Where profiles live
The shipped profiles are compiled into the binary. User profiles are *.wcl files in the profiles directory of vmlab's XDG config directory, ~/.config/vmlab/profiles/ by default; see Files and directories. Every file there is loaded in sorted filename order after the shipped set, and a profile whose name matches a shipped one replaces it entirely rather than merging with it. A file must start with import <vmlab-profile.wcl>; one without the import is rejected, and so is any file with an unknown field, a bad keyword or a wrong type, with the line named.
import <vmlab-profile.wcl>
profile "freebsd" {
description = "FreeBSD 14: q35, SeaBIOS, virtio disk and NIC"
machine = "q35"
firmware = "seabios"
disk_bus = "virtio"
nic_model = "virtio-net-pci"
display = "std"
cpus = 2
memory = 2GiB
}
profile {}
One profile. Every field is optional. A field left unset means the QEMU default applies for that device, which is what the shipped custom profile relies on.
profile "<name>" {
description = "…"
machine = "q35"
firmware = "ovmf"
secure_boot = false
tpm = false
disk_bus = "virtio"
nic_model = "virtio-net-pci"
display = "virtio-vga"
cpus = 2
memory = 4GiB
agent_transport = "virtio-serial"
input_transport = "qmp"
virtiofs = false
workspace_guest = "/src"
}
| Field | Type | Default | Meaning |
|---|---|---|---|
| name | utf8 (label) | required | Profile name, what a vm, container or template names in profile =; the inline block label. |
| description | utf8 | none | Human-readable summary. Parsed and kept; no verb surfaces it yet. |
| machine | utf8 | QEMU default | Machine type: q35, or pc for i440fx. |
| firmware | utf8 | QEMU default | Firmware: ovmf or seabios. |
| secure_boot | bool | unset | Enable secure boot; OVMF only. |
| tpm | bool | unset | Attach a swtpm 2.0 device. |
| disk_bus | utf8 | QEMU default | Primary disk bus: virtio, ide or sata. |
| nic_model | utf8 | QEMU default | NIC device model, for example virtio-net-pci, e1000, rtl8139 or pcnet. |
| display | utf8 | QEMU default | Display device, for example virtio-vga, qxl, std or cirrus-vga. |
| cpus | i64 | unset | Default vCPU count, at least 1. |
| memory | ByteSize | unset | Default RAM, for example 4GiB. |
| agent_transport | utf8 | virtio-serial | The guest agent channel's device: virtio-serial, isa-serial (a 16550 on COM1 for the legacy agent; the serial log moves to COM2), or none (no agent; never ready by handshake). |
| agent_channel | bool | unset | Superseded by agent_transport; still accepted: true reads as virtio-serial, false as none, and agent_transport wins when both are present. |
| input_transport | utf8 | qmp | How scripted input reaches the guest: qmp send-key, or vnc for guests that ignore the PS/2 path. |
| virtiofs | bool | false | The guest mounts virtiofs natively, so transport = "auto" shares use it instead of SMB. |
| workspace_guest | utf8 | unset | Guest path an @dev workspace lands at when the decorator names none. |
The parser enforces the keyword sets above for machine, firmware, disk_bus and input_transport, cpus at least 1, and a non-negative memory. nic_model and display are passed to QEMU as written. A profile that sets no workspace_guest still hosts a dev machine; the floor of /src applies. On a non-x86 virt machine a virtio-vga display is downgraded to virtio-gpu-pci, which has no legacy VGA.
The profile a machine resolves against is the one it names, else the one its template recorded, else the default. Validation reports an unknown profile name on the block that names it. A login {} block's family rules read the resolved profile's name: windows* is Windows, linux* is Linux, and any other name is unknown and gets neither rule.
Shipped profiles
The shipped set, with the values each one carries. A blank cell means the field is unset. Every Windows profile lands an @dev workspace at C:\src and every Linux one at /src.
| Profile | Machine | Firmware | Secure boot | TPM | Disk bus | NIC model | Display | CPUs | Memory | Other |
|---|---|---|---|---|---|---|---|---|---|---|
| windows-11 | q35 | ovmf | true | true | virtio | virtio-net-pci | virtio-vga | 4 | 8GiB | |
| windows-10 | q35 | ovmf | false | false | virtio | virtio-net-pci | virtio-vga | 4 | 8GiB | |
| windows-server | q35 | ovmf | false | true | virtio | virtio-net-pci | virtio-vga | 4 | 8GiB | |
| windows-legacy | pc | seabios | false | false | ide | e1000 | std | 2 | 2GiB | XP, 7 and 2008-era guests with no virtio drivers. |
| windows-9x | pc | seabios | false | false | ide | pcnet | cirrus-vga | 1 | 256MiB | input_transport = "vnc". DOS, Windows 3.x to ME and 2000-era guests. |
| linux-modern | q35 | ovmf | false | false | virtio | virtio-net-pci | virtio-vga | 2 | 4GiB | virtiofs = true. |
| linux-generic | q35 | seabios | false | false | virtio | virtio-net-pci | std | 2 | 2GiB | Older or unusual distros. |
| container | 1 | 256MiB | Micro-VM size for an OCI container; nothing else applies to a container. | |||||||
| custom | Nothing assumed; supply everything on the VM or template and in qemu_args. |
The container profile carries only a size because a container micro-VM boots the guest asset directly and has no firmware, disk bus, display or NIC model to choose. Its floor is an order of magnitude below a VM's on purpose: the micro-VM runs one process, not an operating system. Raise it per container with cpus and memory, or drop your own container profile into the user directory to change the default for every lab.
Overriding replaces, it does not merge
A user profile named windows-11 replaces the shipped one completely. A file holding only profile "windows-11" { machine = "pc" } leaves that profile with no firmware, disk bus or memory. Copy the full shipped block and change the fields you need.
import <vmlab-profile.wcl>
// Shipped guest OS profiles (PRD §5.3). Known-good hardware defaults;
// values not set on the VM or template inherit from these. Override or
// extend by dropping `*.wcl` files into `~/.config/vmlab/profiles/`.
//
// No Windows profile sets `virtiofs`: virtio-win 0.1.302's VioFS driver fails
// large reads at random, so `transport = "auto"` shares on Windows ride SMB
// (§7.5).
profile "windows-11" {
description = "Windows 11: q35, OVMF with secure boot, swtpm 2.0, virtio devices"
machine = "q35"
firmware = "ovmf"
secure_boot = true
tpm = true
disk_bus = "virtio"
nic_model = "virtio-net-pci"
display = "virtio-vga"
cpus = 4
memory = 8GiB
// Where an `@dev` workspace lands when the decorator names no
// `workspace_guest` (§19.1) — the key is guest-OS-shaped, which is why it
// is profile-sourced.
workspace_guest = "C:\\src"
}
profile "windows-10" {
description = "Windows 10: q35, OVMF, virtio devices (no TPM/secure boot required)"
machine = "q35"
firmware = "ovmf"
secure_boot = false
tpm = false
disk_bus = "virtio"
nic_model = "virtio-net-pci"
display = "virtio-vga"
cpus = 4
memory = 8GiB
workspace_guest = "C:\\src"
}
profile "windows-server" {
description = "Windows Server: q35, OVMF, swtpm 2.0, virtio devices"
machine = "q35"
firmware = "ovmf"
secure_boot = false
tpm = true
disk_bus = "virtio"
nic_model = "virtio-net-pci"
display = "virtio-vga"
cpus = 4
memory = 8GiB
workspace_guest = "C:\\src"
}
profile "windows-legacy" {
description = "Vista/7/2008-era guests with no virtio storage/net drivers at install time: i440fx, SeaBIOS, IDE disk, e1000 NIC, std VGA; virtio-serial agent channel (virtio-win covers this era)"
machine = "pc"
firmware = "seabios"
secure_boot = false
tpm = false
disk_bus = "ide"
nic_model = "e1000"
display = "std"
cpus = 2
memory = 2GiB
workspace_guest = "C:\\src"
}
profile "windows-xp" {
description = "NT4 through XP/2003: i440fx, SeaBIOS, IDE disk, e1000 NIC, std VGA; no virtio drivers at all, so the agent channel is a 16550 on COM1 (the legacy agent)"
machine = "pc"
firmware = "seabios"
secure_boot = false
tpm = false
disk_bus = "ide"
nic_model = "e1000"
display = "std"
cpus = 2
memory = 2GiB
agent_transport = "isa-serial"
workspace_guest = "C:\\src"
}
profile "windows-9x" {
description = "DOS / Windows 3.x-ME / 2000-era PCs: i440fx, SeaBIOS, IDE disk, Cirrus VGA, AMD PCnet NIC (all drivable by these guests); cap RAM low per template"
machine = "pc"
firmware = "seabios"
secure_boot = false
tpm = false
disk_bus = "ide"
nic_model = "pcnet"
display = "cirrus-vga"
cpus = 1
memory = 256MiB
agent_transport = "isa-serial"
// Real-mode DOS/9x TUIs (fdisk, setup) drop QMP send-key events between menu
// redraws; drive their keyboard over VNC instead, which lands reliably.
input_transport = "vnc"
workspace_guest = "C:\\src"
}
profile "templeos" {
description = "TempleOS: i440fx, SeaBIOS, IDE disk, std VGA (it drives VBE directly), no network by design; the agent channel is a 16550 on COM1 for the HolyC agent"
machine = "pc"
firmware = "seabios"
secure_boot = false
tpm = false
disk_bus = "ide"
nic_model = "e1000"
display = "std"
cpus = 2
memory = 512MiB
agent_transport = "isa-serial"
}
profile "linux-modern" {
description = "Modern Linux: q35, OVMF, virtio everything"
machine = "q35"
firmware = "ovmf"
secure_boot = false
tpm = false
disk_bus = "virtio"
nic_model = "virtio-net-pci"
// VGA-compatible virtio GPU on x86; auto-downgrades to virtio-gpu-pci on the
// non-x86 `virt` machine (no legacy VGA there). See display_device_name.
display = "virtio-vga"
cpus = 2
memory = 4GiB
// Kernel ≥5.4 ships the virtiofs client — `transport = "auto"` shares
// mount natively instead of over SMB (§7.5).
virtiofs = true
workspace_guest = "/src"
}
profile "linux-generic" {
description = "Older or unusual distros: q35, SeaBIOS, virtio disk/net, conservative elsewhere"
machine = "q35"
firmware = "seabios"
secure_boot = false
tpm = false
disk_bus = "virtio"
nic_model = "virtio-net-pci"
display = "std"
cpus = 2
memory = 2GiB
workspace_guest = "/src"
}
profile "container" {
description = "Micro-VM defaults for an OCI container (PRD §18): the smallest shape that boots the guest asset and a typical service image"
// A container micro-VM boots the guest asset directly — no firmware, disk
// bus, display or NIC model to choose — so this profile carries only the
// size, which is the whole reason a container names a profile. It is an
// order of magnitude below the VM floor on purpose: the micro-VM runs one
// process, not an operating system. Raise it per container with
// `memory = …`, or drop your own `container` profile into
// ~/.config/vmlab/profiles to change the default for every lab.
cpus = 1
memory = 256MiB
workspace_guest = "/src"
}
profile "custom" {
description = "Nothing assumed — supply everything via VM/template attributes and qemu_args"
}