Bhyve on FreeBSD: From Basics to Advanced Networking
🔗Introduction
Bhyve (pronounced "bee-hive") is the native hypervisor built into the FreeBSD base system. It provides a lean virtualization platform that requires no third-party hypervisor software. What drew me to it is how much you can do with something that ships as part of the base system: run full guest operating systems, build multi-VM lab networks, and practice real networking scenarios without any dedicated hardware.
This post walks through what Bhyve is, how its networking model works, and a complete quickstart using vm-bhyve on a ZFS-based FreeBSD 12.0 system.
🔗Advantages
- Native to FreeBSD: Bhyve ships with the base system. No external packages needed to get started.
- Low overhead: Minimal CPU and memory overhead compared to traditional hosted hypervisors.
- Flexible configuration: VM parameters are fully tunable from the command line or through automation tools.
- Networking breadth: Supports tap interfaces, bridges, and VLANs for building realistic lab topologies.
- ZFS integration: Pairs naturally with ZFS for efficient storage, snapshots, and cloning.
- Hands-on learning: Running real guests gives you a practical environment for NAT, DHCP, firewall rules, and routing.
🔗Disadvantages
- Command-line focused: Most configuration requires shell work unless you use a third-party management tool.
- Hardware requirements: Requires a CPU with Intel VT-x or AMD-V support. The GENERIC kernel includes bhyve support by default.
- Windows guest support: Windows guests require UEFI firmware (
bhyve-firmware) and a VirtIO driver disk. FreeBSD 12.0 improved this significantly, though some edge cases remain depending on the Windows version. - Smaller community: FreeBSD's Bhyve community is active but smaller than KVM or VMware communities, so some questions take more digging to answer.
🔗Use Cases
- Home lab: Simulate networks, run servers, and test configurations without dedicated hardware.
- Lightweight service hosting: Run DNS, web servers, or VPN endpoints in isolated VMs.
- FreeBSD administration practice: A contained environment for working through system administration tasks without risking the host.
- Isolated development: Test software in clean environments without affecting the host.
- Network appliances: Run pfSense, OPNsense, or other firewall and router appliances inside Bhyve.
🔗When to Avoid Bhyve
- You need a polished GUI for VM management and prefer not to use the command line.
- Your workload depends heavily on Windows guests in production.
- Your team requires a hypervisor with broad enterprise adoption and vendor support, such as VMware or Hyper-V.
🔗Tooling
🔗vm-bhyve
vm-bhyve is the most widely used management utility for Bhyve. It wraps bhyve's command-line complexity into simple, repeatable commands.
Key features:
- Template-based VM creation
- Automated bridge and switch management
- Autostart on boot via rc.d
- Simple console access
🔗Native CLI
FreeBSD includes bhyve, bhyvectl, and bhyveload for manual VM management. This approach gives you full control over every parameter but requires a solid understanding of tap interfaces, UEFI or grub-bhyve boot loaders, and storage device configuration.
🔗Networking Concepts
Bhyve uses tap interfaces for virtual NICs and bridge interfaces to connect them to the host network. The two key components are:
- tap(4): A virtual Ethernet device attached to a guest VM.
- bridge(4): A Layer 2 switch that connects physical and virtual interfaces, allowing guests to communicate with the host network or with each other.
🔗Network Diagrams
🔗1. Basic VM with Bridge Networking
+-----------------------------+
| FreeBSD Host |
| |
Internet--em0 |
| bridge0---tap0---[VM1] |
+-----------------------------+em0: physical NICtap0: virtual NIC assigned to VM1bridge0: connectsem0andtap0at Layer 2, giving VM1 access to the same network segment as the host
🔗2. Dual-NIC Router VM (WAN and LAN)
Internet
|
em0
|
bridge0 --- tap0 (WAN) ---+
|
Router VM
|
bridge1 --- tap1 (LAN) ---+
|
LAN Client VMstap0is bridged toem0for upstream internet access.tap1is bridged to an internal-only bridge (bridge1).- The router VM runs pfSense, OPNsense, or a FreeBSD host with pf and handles NAT, DHCP, and firewall rules for LAN clients.
🔗3. VLAN Trunk to a VM
Physical Switch (VLAN 10, VLAN 20 tagged)
|
em0 (trunk port on host)
|
bridge0 --- tap0 (trunk) --> Firewall VMVLAN tagging can be handled on the host using ifconfig vlan subinterfaces, or inside the guest VM if it receives a tagged trunk. Use ifconfig vlan10 create vlan 10 vlandev em0 on the host to create a VLAN interface before bridging.
🔗4. Lab-in-a-Box
Internet
|
em0
|
bridge0 --- tap0 (WAN) ---+
|
Router VM
|
bridge1 --- tap1 (LAN) ---+
|
+--- tap2 --- VM2 (Client)
|
+--- tap3 --- VM3 (Client)
Optional VLAN trunk:
em0 --- vlan20 --- bridge2 --- tap4 --- Router VMThe router VM handles NAT, DHCP, and firewall rules. Multiple client VMs on bridge1 form a LAN segment. The optional VLAN trunk on bridge2 allows isolated VLAN testing without additional hardware.
🔗Quickstart with vm-bhyve
The following walkthrough uses vm-bhyve on a ZFS-based FreeBSD 12.0 system. Adjust device names and paths to match your environment. The ISO URL structure shown here follows the standard FreeBSD mirror layout, which has remained consistent across releases: replace the version number to use any current release.
🔗Step 1: Install packages
pkg install vm-bhyve bhyve-firmwarebhyve-firmware provides UEFI firmware (BHYVE_UEFI.fd) required for booting UEFI guests, including Windows and most modern Linux distributions.
🔗Step 2: Load kernel modules
kldload vmm
kldload if_tap
kldload if_bridgeTo load these automatically on boot, add the following to /boot/loader.conf:
vmm_load="YES"
if_tap_load="YES"
if_bridge_load="YES"🔗Step 3: Create a ZFS dataset for VM storage
zfs create -o mountpoint=/vm zroot/vmvm-bhyve manages its own volume options per VM, so no additional dataset properties are required here.
🔗Step 4: Configure rc.conf
Add the following to /etc/rc.conf:
vm_enable="YES"
vm_dir="zfs:zroot/vm"🔗Step 5: Initialize vm-bhyve
vm initThis creates the .config directory and default templates under /vm.
🔗Step 6: Create a virtual switch
vm switch create public
vm switch add public em0Replace em0 with your actual physical interface name. You can find it with ifconfig -l.
🔗Step 7: Download an ISO
vm iso fetch https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-disc1.isoOr place an already-downloaded ISO in /vm/.iso/ manually. To use a different release, substitute the version number in both the path and filename.
🔗Step 8: Create and install a VM
vm create -t freebsd -s 20G testvm
vm install testvm FreeBSD-12.0-RELEASE-amd64-disc1.isoThe -t freebsd flag uses the built-in FreeBSD template. Adjust the ISO filename to match what you downloaded.
🔗Step 9: Connect to the console
vm console testvmPress ~. (tilde then period) to disconnect from the console once installation is complete.
🔗Step 10: Start the VM after installation
vm start testvmTo configure the VM to start automatically at boot:
vm set testvm loader=bhyveload autostart=yes🔗Useful vm-bhyve Commands
| Task | Command |
|---|---|
| List all VMs | vm list |
| Stop a VM | vm stop testvm |
| Force stop | vm poweroff testvm |
| Destroy a VM | vm destroy testvm |
| Show VM info | vm info testvm |
| List ISO images | vm iso |
🔗Scalability and Community
Bhyve scales well on capable hardware. You can script VM creation, use ZFS clones for fast provisioning, and combine Bhyve with FreeBSD jails for mixed workloads on a single host.
Community support is available through the FreeBSD mailing lists (freebsd-virtualization@), the FreeBSD forums, and the #freebsd IRC and Matrix channels.
🔗Closing Thoughts
Getting Bhyve running for the first time is one of those moments where the pieces snap together quickly, and then you start wondering what else you can do with it. A router VM sitting between two bridges, a pfSense appliance handling your lab traffic, a cluster of lightweight guests sharing a single machine: none of it requires anything beyond what FreeBSD already ships with. That is what keeps me coming back to it.
