How to Set Up a bhyve Virtual Machine Step by Step
A current vm-bhyve workflow for verified firmware, ZFS storage, virtual switches, guest templates, installation media, consoles, and backups.
bhyve(8) is FreeBSD’s native hypervisor; vm-bhyve is a third-party manager in the Ports Collection that creates command lines, storage, tap interfaces, switches, and lifecycle state. This procedure builds one UEFI guest with persistent configuration. Run networking changes from a local or out-of-band console: attaching the wrong host interface to a bridge can disconnect SSH.
Verify host support and install components
On amd64, confirm virtualization support and current FreeBSD state:
freebsd-version -kru
sysctl hw.vmm.vmx.initialized hw.vmm.svm.features
kldstat -m vmm
Intel and AMD expose different sysctls, so one may be absent. Enable virtualization in firmware when neither path is available. Install the manager and UEFI firmware:
pkg install vm-bhyve bhyve-firmware
pkg info -l bhyve-firmware
Do not hardcode an old BHYVE_UEFI.fd path; inspect the installed package. vm init loads required modules, while persistent host setup can use the manager’s rc script. Avoid the obsolete-looking vmm_load="YES" in rc.conf; loader modules belong in /boot/loader.conf, and runtime modules can be managed with kld_list where needed.
Create a dedicated datastore
With ZFS, create a dataset whose name and mount point are known:
zfs create -o mountpoint=/vm zroot/vm
sysrc vm_enable="YES"
sysrc vm_dir="zfs:zroot/vm"
vm init
If zroot/vm already exists, inspect its properties rather than recreating it. On UFS, set vm_dir to an existing directory instead of the zfs: form.
Install the sample templates into the initialized datastore:
cp /usr/local/share/examples/vm-bhyve/* /vm/.templates/
ls -la /vm/.templates
Review the chosen template before creating a VM. For a Linux UEFI guest, confirm firmware mode, memory, CPU, disk type, network adapter, switch, and graphics/console settings. Sample defaults can change between package versions.
Create and validate the virtual switch
Identify the physical interface and its current addressing:
ifconfig -a
netstat -rn
Then create a vm-bhyve switch and attach the correct wired interface:
vm switch create public
vm switch add public em0
vm switch list
Replace em0. A public bridge makes guest MAC addresses visible on the upstream segment; Wi-Fi client mode and some datacenter ports do not permit that. In those environments, use a routed/NAT design rather than forcing bridging. Confirm the host retains its address, default route, and management access after the switch change.
The VM template must reference the same switch, for example network0_switch="public". Do not manually create a second unrelated bridge0 behind vm-bhyve; let one configuration own the topology.
Create the VM and use verified installation media
Create from a reviewed Linux template:
vm create -t debian -s 20G mydebianvm
vm configure mydebianvm
vm info mydebianvm
The -s operation allocates guest disk capacity and can consume real pool space as the disk fills. Check ZFS free space and quotas first.
Download a currently supported amd64 installer from its publisher, verify its signed checksum, and then place or import it into vm-bhyve’s ISO datastore. vm iso URL can fetch a URL:
vm iso https://publisher.example/path/debian-netinst.iso
vm iso
The placeholder must be replaced with the exact current HTTPS URL. Never treat a successful download as integrity verification; compare the file hash with the distribution’s signed checksum before booting it.
Start installation:
vm install mydebianvm debian-netinst.iso
vm list
Use the basename shown by vm iso. If UEFI graphics are enabled, connect to the VNC endpoint reported by vm info or the install output. Bind VNC to localhost and tunnel it rather than exposing an unauthenticated console. vm console connects only to a configured serial console; a blank serial session does not mean graphical UEFI is stuck.
Install with compatible virtual devices
Inside the installer, confirm the expected virtual disk and NIC appear before partitioning. Modern Linux normally includes VirtIO drivers; older guests may require an emulated AHCI disk or E1000 NIC during installation. Keep the controller consistent between install and normal boot.
Partition the guest disk inside the guest. Do not run host gpart against vm-bhyve disk files unless doing a planned offline recovery. Let the installer create GPT and an EFI System Partition while booted under UEFI.
After installation, shut down from the guest so filesystems close cleanly. Then detach installation mode and start normally:
vm start mydebianvm
vm info mydebianvm
Verify guest address, DNS, package repositories, and outbound/inbound policy. Test by hostname as well as IP; a ping alone does not validate application ports.
Operate, stop, and protect the guest
Use guest-aware shutdown where possible:
vm list
vm stop mydebianvm
vm start mydebianvm
vm console mydebianvm
For snapshots, shut down or quiesce the guest first. A host ZFS snapshot of a running disk is at best crash-consistent unless the application and guest flush state. It is not automatically an application-consistent database backup and remains on the same pool.
Back up the VM configuration, disk data, firmware variable store, and recovery instructions to another failure domain. Test a restore. Before deletion, verify the name and backups:
vm info mydebianvm
vm destroy mydebianvm
vm destroy is destructive; do not include it in cleanup scripts without confirmation.
Finally enable the vm service only after deciding which guests should autostart and in what order. Reboot the host in a maintenance window, confirm modules, switches, and selected guests return, then verify graceful host shutdown. A VM that boots once is a lab result; persistent networking, verified media, controlled consoles, and tested recovery make it operational.
Related:
Sources: