bhyve in one config

freebsd 15 / published / guide #52 / ≈ 4 min read

bhyve (pronounced "bee-hive") is FreeBSD's built-in hypervisor — full hardware virtualisation, like KVM on Linux or VMware. Where jails are tiny FreeBSD environments sharing the host kernel, bhyve runs entire other operating systems with their own kernels: another FreeBSD, a Linux distro, even Windows.

This guide is the simplest possible path: get one Ubuntu VM running with disk, network, and a console you can interact with.

How bhyve compares to other tools you might know

  • jails — same kernel, very light, only FreeBSD inside.
  • bhyve — separate kernel per VM, more isolation, can run any OS that supports VT-x/AMD-V.
  • VirtualBox on FreeBSD — works but heavier; bhyve is the native answer.

Use jails for "another FreeBSD environment." Use bhyve for "an entirely different OS."

Step 0: check your CPU supports it

grep -E "POPCNT|VT-x|AMD-V" /var/run/dmesg.boot 2>/dev/null || sudo dmesg | grep -iE "vt-x|svm"

If you see VT-x (Intel) or SVM (AMD), you're good. Otherwise bhyve can't run.

Step 1: load the kernel modules

sudo kldload vmm                 # the main bhyve module
sudo kldload nmdm                # null-modem console pairs (for talking to VMs)
sudo kldload if_tap              # virtual network interfaces
sudo kldload if_bridge           # to bridge them to your real network

To make these persistent across reboot:

sudo sysrc -f /boot/loader.conf vmm_load=YES
sudo sysrc -f /boot/loader.conf nmdm_load=YES
sudo sysrc -f /boot/loader.conf if_tap_load=YES
sudo sysrc -f /boot/loader.conf if_bridge_load=YES

Step 2: install vm-bhyve, the friendly wrapper

Raw bhyve takes a lot of arguments. vm-bhyve is a small management layer that hides the boilerplate:

sudo pkg install vm-bhyve grub2-bhyve bhyve-firmware
  • vm-bhyve — the wrapper.
  • grub2-bhyve — loads grub-based Linux installers (older guests use this).
  • bhyve-firmware — UEFI firmware images for modern UEFI guests.

Step 3: pick a place for VMs to live

On ZFS, dedicate a dataset:

sudo zfs create -o mountpoint=/vm zroot/vm
sudo sysrc vm_enable="YES"
sudo sysrc vm_dir="zfs:zroot/vm"
sudo vm init

On UFS:

sudo mkdir /vm
sudo sysrc vm_enable="YES"
sudo sysrc vm_dir="/vm"
sudo vm init

vm init creates the directory layout and a default config template.

Step 4: bridge for networking

Pick the network interface that talks to your LAN. Find it with ifconfig — likely em0, re0, igb0, or similar.

Configure vm-bhyve's default switch to use it:

sudo vm switch create public
sudo vm switch add public em0          # replace em0 with your interface

This creates a software bridge so VMs share your LAN with the host (they get IPs from the same DHCP server you do).

Step 5: download an OS installer ISO

Grab an Ubuntu Server ISO (smallest sensible Linux to demo with):

sudo fetch -o /vm/.iso/ubuntu.iso https://releases.ubuntu.com/24.04/ubuntu-24.04-live-server-amd64.iso

Step 6: create the VM

sudo vm create -t ubuntu -s 20G ubuntu1
  • -t ubuntu — template (vm-bhyve ships several; vm list-templates shows them).
  • -s 20G — virtual disk size.
  • ubuntu1 — name of the VM.

Step 7: install from the ISO

sudo vm install ubuntu1 ubuntu.iso

This boots the VM with the ISO attached. Now connect to its console:

sudo vm console ubuntu1

You're inside the Ubuntu installer's text-mode UI over a serial console. Step through. (Detach from the console with ~ . like SSH escape sequences.)

When the install asks about networking, DHCP should just work via the bridge.

Step 8: boot it normally

After install finishes:

sudo vm stop ubuntu1
sudo vm start ubuntu1
sudo vm console ubuntu1

Or if you'd rather use SSH (recommended once the system is up), find the VM's IP via your router or by logging in once via the console with ip a, then ssh user@that-ip from the host or anywhere on the LAN.

Daily commands

vm list                          # all VMs, running / stopped
vm start ubuntu1                 # start (background)
vm stop ubuntu1                  # stop politely
vm poweroff ubuntu1              # hard power off
vm console ubuntu1               # serial console
vm restart ubuntu1               # graceful restart
vm destroy ubuntu1               # delete (asks first)

Auto-start on boot

sudo sysrc vm_list="ubuntu1 someother-vm"

vm-bhyve will start them in order at system boot.

A more useful config: edit the VM's settings

sudo vm configure ubuntu1

Opens a small config file. The interesting keys:

cpu=2
memory=2G
network0_type="virtio-net"
network0_switch="public"
disk0_type="virtio-blk"
disk0_name="disk0.img"
uefi="yes"

Change CPU count or RAM, then vm restart ubuntu1. Live resizing isn't supported — a stop/start is needed.

Useful inspection

vm info ubuntu1                  # everything about one VM
vm switch list                   # what bridges exist
ifconfig bridge0                 # the host's view of the bridge

Things that trip people up

  • "vm: switch 'public' has no member" — you forgot vm switch add public em0.
  • Console keeps reattaching — only one process can hold the console at a time. Use ~ . to detach cleanly.
  • VM gets no IP — check that the bridge is in UP state with ifconfig bridge0; check that pf isn't blocking the bridge interface.
  • Windows guest won't boot — needs uefi="yes" and the bhyve-firmware package installed.

How does this compare to a jail?

A jail is ~1 MB of overhead and milliseconds to start. A bhyve VM is a full second OS — hundreds of MB of RAM, full kernel boot. Pick the lighter one when you can. bhyve's sweet spot is "I need a Linux box on my FreeBSD server" or "I'm testing OS installers."

← back to index