Design
4 minute read
Barn provides two distinct virtualization workflows through one CLI: multi-node Linux labs and standalone macOS guests.
| Dimension | Linux labs (barn …) |
macOS guests (barn mac …) |
|---|---|---|
| Hypervisor | QEMU with HVF or KVM (TCG for foreign architectures and el8 on Apple Silicon) |
Apple Virtualization.framework |
| Desired state | One Pigsty-compatible YAML inventory (barn.yml) |
Named VMs configured via barn mac flags |
| State directory | $BARN_HOME (default ~/.barn) |
$BARN_HOME/mac (default ~/.barn/mac) |
| Networking | User-mode management NIC + shared fixed-IP /24 lab subnet |
Dedicated /24 NAT subnet and DHCP .10 reservation per VM |
| Primary workloads | Database clusters, Ansible playbooks, multi-node Linux testing | macOS builds, GUI testing, isolated desktop environments |
The sections below summarize the Linux lab architecture; for the deeper rationale behind each decision, see the Design Essays. The native Mac lifecycle essay explains network ownership, locks, credentials, and recovery; usage is in macOS Guests and Mac Commands.
One Linux lab per user
Each Unix user manages one Linux lab deployment stored in BARN_HOME (default ~/.barn) and driven by a single Pigsty-compatible YAML inventory (see Why Barn Has No Projects). Because deployment state lives in BARN_HOME rather than the working directory, lifecycle and access commands work from any directory.
Node-level convergence
Barn computes a specification hash per node from the documented vm_* and Pigsty identity fields and records it alongside the node’s committed state and QEMU process identity:
barn upcreates newly added nodes, starts stopped nodes, retries unfinished guest setup on running nodes without restarting their QEMU processes, and refreshes managed/etc/hostsand SSH entries.- Changing an existing node’s specification or removing a node from
barn.ymlnever destroys a VM behind your back—CPU and memory changes usebarn resize, other modifications requirebarn recreate, and removals requirebarn destroy. A whole-deploymentrecreaterefuses an inventory that omits an existing node (see Declarative Does Not Mean Destructive).
Runtime selection
--arch/-A overrides inventory vm_arch for an invocation. With neither set, the guest follows the host; -A native overrides the inventory and restores that default. Image flag -I does not change architecture, and switching an existing VM requires recreation; see configuration rules.
vm_arch applies across the entire deployment (native uses the host CPU architecture; explicit amd64 or arm64 selects that architecture from the catalog). Barn uses hardware acceleration (HVF on macOS, KVM on Linux) whenever guest and host architectures match, switching to QEMU TCG only for foreign architectures or catalog-declared kernel incompatibilities (el8 arm64 on Apple Silicon). If native HVF/KVM fails for any other reason, Barn fails closed rather than silently degrading to software emulation.
Each node’s committed state records the effective architecture and accelerator (barn status displays both). Before executing a destructive recreate, Barn pre-validates the QEMU binary, version, network backend, base image bytes, boot mode, and firmware so a missing dependency never destroys a working VM.
Two NICs, one fixed subnet
Every Linux VM attaches two virtual NICs (see Why Every Barn Node Has Two NICs):
- Management NIC: QEMU user-mode networking providing DHCP, DNS, outbound internet access, and host-loopback SSH port forwarding without host firewall changes.
- Fixed-IP lab NIC: Carries the static RFC1918
/24address frombarn.ymlfor host-to-node, node-to-node, and Ansible traffic.
To provide the fixed-IP subnet without running QEMU as root:
- macOS hosts run a pinned
socket_vmnetdaemon. - Linux hosts use NetworkManager (
nmclimanagingbarn0) when active, orsystemd-networkdwith the distributionqemu-bridge-helper(verifying beforehand that enabling an inactivesystemd-networkdwill not claim physical host interfaces). On Debian,setupgrantsqemu-bridge-helperaccess to a group containing the caller and smoke-tests an unprivileged QEMU attachment before committing the network transaction.
Storage and configuration lifetimes
Desired configuration (barn.yml), applied deployment state ($BARN_HOME), and cached base images ($BARN_HOME/images) have independent lifecycles:
- Updating a catalog channel (
barn update) does not rewrite existing VM root disks. - Verified base images are stored read-only and shared across nodes via per-node
qcow2copy-on-write root overlays. - Ordinary
destroyandrecreateretainpersistent: truedata disks. During guest recovery,upformats only a data disk without any signature or an ext4/XFS filesystem whose checker reports recognized corruption; anything it cannot classify keeps its data and reports a warning (see Data Disks and Storage and Access). barn image pruneprotects images referenced by the active catalog, applied nodes, andlocal-*aliases (see Images).
Safety boundary
QEMU processes and image downloads run as your normal user account; root privileges are used only during setup, network install/uninstall, and hosts install/uninstall. Before signaling a process or deleting a node file, Barn verifies file ownership, path containment, QMP UUID/name identity, process start-time/cmdline tuples, and the journal allowlist—stopping immediately if any check is ambiguous (see A PID Is Not a Virtual Machine).