Synopsis #
OpenBSD provides the vmm(4) hypervisor, vmd(8) management daemon, vmctl(8) control utility, and vm.conf(5) persistent configuration. This chapter creates one serial-console guest, connects it through a local interface, makes the configuration persistent, and defines shutdown, backup, and recovery boundaries.
The official virtualization FAQ is the authority for current host requirements, supported guests, and feature limits. Current support is limited to OpenBSD and Linux guests with serial consoles. Graphics, snapshots, guest SMP, hardware passthrough, live migration, and live hardware changes are not currently available.
Confirm Host Support #
vmm is available on supported amd64 systems with hardware virtualization and nested paging. Firmware settings may need to enable the feature. Check the processor flags:
$ dmesg | egrep '(VMX/EPT|SVM/RVI)'
VMX/EPT identifies the required Intel facilities; SVM/RVI identifies the AMD equivalents. A virtualization marketing name without EPT or RVI output is insufficient.
After changing firmware settings, install the separately distributed vmm firmware with fw_update(8) :
# fw_update
Plan host memory, storage, CPU, and network capacity before starting guests. Guest memory is also constrained by the datasize limit for the vmd service account in login.conf(5)
.
Enable vmd #
Use rcctl(8)
rather than editing rc.conf.local directly:
# rcctl enable vmd
# Enable the daemon at boot
# rcctl start vmd
# Start it now
# rcctl check vmd
# Confirm that it remains running
When the host shuts down, vmd requests clean shutdown through vmmci(4)
and waits before forcing termination. Adjust the service timeout only after measuring guest shutdown behavior.
Prepare Guest Storage and Installation Media #
Create a protected directory and a sparse qcow2 disk:
# install -d -o root -g wheel -m 700 /var/vm
# Create the VM storage directory
# vmctl create -s 40G /var/vm/example.qcow2
# Create a 40 GB qcow2 disk image
Download and verify an installation ISO from the guest operating system’s authoritative source. For an OpenBSD 7.9 guest, use the verified-media procedure in Installing OpenBSD . The version shortcode is not expanded inside code blocks; use the resolved ISO filename in the commands below.
Start the Installer #
Start a guest with one gigabyte of memory, one local network interface, the installation ISO, and the prepared disk:
# vmctl start -c -m 1G -L -r INSTALL_ISO -d /var/vm/example.qcow2 example
INSTALL_ISO is a placeholder for the verified image path. -c attaches the serial console. -L gives the guest one local interface with an address supplied by vmd. The guest sees a vio(4) network device and the host sees a tap(4) device.
Configure the guest installer to use its serial console. Disconnect from a vmctl console session with ~.. When the console is reached through SSH, the SSH escape processing requires ~~..
Inspect the running guest from a separate terminal:
# vmctl status
# List configured and running VMs
# vmctl console example
# Reattach to the named guest console
Make the Guest Persistent #
After installation, define the guest in /etc/vm.conf:
vm "example" {
memory 1G
enable
disk "/var/vm/example.qcow2"
local interface
}
Validate the complete configuration before loading it:
# vmd -n
# Parse /etc/vm.conf without starting another daemon
# vmctl reload
# Remove stopped definitions and load the validated configuration
Running guests do not receive all configuration changes during reload. Stop a guest cleanly before relying on changed memory, disk, or interface settings.
The enable keyword starts the VM when vmd loads the configuration. Use disable when startup must remain manual.
Use Local Networking Deliberately #
A local interface allocates a host/guest address pair from 100.64.0.0/10 and provides DHCP/BOOTP to the guest. The host-side tap address becomes the guest’s default route and resolver address.
Local networking alone does not provide Internet access. To route guest IPv4 traffic, enable forwarding and add PF policy that is consistent with the host’s complete ruleset:
net.inet.ip.forwarding=1
In /etc/pf.conf, a minimal outbound translation rule is:
pass out on egress from 100.64.0.0/10 to any nat-to (egress)
Parse the complete PF ruleset before loading it:
# pfctl -nf /etc/pf.conf
# Check syntax without changing the active ruleset
# pfctl -f /etc/pf.conf
# Load only after the full policy and recovery path are verified
This is only the egress and translation half of the policy. A default-block ruleset also needs an explicit, suitably restricted pass in policy on the relevant tap interface or interface group before guest packets can reach egress. Define that ingress rule from the intended guest, destination, and service matrix; do not use it to expose host services unintentionally. DNS redirection, inbound publication, and inter-guest policy are separate decisions.
Use a Virtual Switch for Explicit Topologies #
For host-only, segmented, or physical-network attachment, create a supported veb(4)
and optional vport(4)
topology, then reference it from a switch block. Do not copy old examples that add an addressed physical interface directly to bridge0; a veb port is disconnected from the host IP stack and host addressing belongs on a vport when the host must participate.
The official virtualization FAQ documents four current patterns:
- local host/guest networking;
- local networking with NAT;
- a controlled virtual switch using
vebandvport; - attachment to a real Ethernet network.
Bridging to a real network works with Ethernet, not a Wi-Fi client interface. Preserve console access while moving host addresses between physical and virtual interfaces because a mistake can remove host connectivity.
Operate Guests Safely #
Request a clean stop and wait for completion:
# vmctl stop -w example
Use -f only when the guest cannot shut down and data-loss risk has been accepted. Pause is not a durable backup or shutdown state.
Inspect guest state and host logs when an operation fails:
# vmctl status example
# Inspect the VM state
# tail -n 100 /var/log/daemon
# Review recent vmd diagnostics
# ifconfig -g tap
# Inspect host-side guest interfaces
Do not assume a command from another hypervisor exists in vmctl. The current manual documents create, start, stop, console, pause, unpause, status, load, reload, reset, and wait operations.
Back Up and Restore a Guest #
A copied disk image is crash-consistent only if guest writes were quiesced at the correct boundary. Prefer an application-aware backup inside the guest. For a complete cold image backup:
- shut the guest down cleanly;
- confirm
vmctl statusno longer reports it as running; - copy the disk image and
/etc/vm.confto independent storage; - verify the backup and periodically restore it under another VM name;
- retain guest encryption keys and application recovery material separately.
Do not copy a live qcow2 image and call it a tested snapshot. The official vmm feature list does not include VM snapshots.
Recover a Failed Guest #
Separate host, configuration, boot, disk, and guest-network failures:
- If
vmddoes not start, runvmd -n, inspect firmware availability, and review daemon logs. - If the guest is undefined, verify
/etc/vm.conf, reload it, and inspectvmctl status. - If the guest does not boot, attach the console and use verified installation media for guest recovery.
- If the disk image is damaged, stop write attempts and restore the tested copy.
- If networking fails, inspect the guest
viodevice, hosttapdevice, forwarding state, PF state, and the selected local or switch topology in order.
Troubleshoot PF, NAT, and Routing provides the packet path workflow. Plan a Docker Workload Migration to OpenBSD explains when a Linux guest is appropriate for a workload that requires Linux container interfaces.