linux bhyve template

The bhyve path is no longer “FreeBSD guest plus theory note for Linux”. Coppice now has a repo-native Linux guest recipe: debian-12-bhyve, built from Debian’s official generic cloud image and configured through the same bhyve template sidecar system the Windows and FreeBSD guests already use.

What landed

Template shape

The Debian template sidecar is straightforward:

TPL_GATEWAY_MODE=ssh
TPL_BOOT_MODE=uefi
TPL_PATCH_MODE=nocloud-seed
TPL_DISK_DEVICE=virtio-blk
TPL_NET_DEVICE=virtio-net
TPL_SSH_USER=root
TPL_SHELL=/bin/bash
TPL_SHELL_ARGS="-i"

That means:

  1. coppice-bhyve-pool-ctl.sh warm debian-12-bhyve —count N clones the raw disk image.
  2. The controller writes a NoCloud seed disk for the clone.
  3. bhyve boots the Debian image under UEFI with a virtio-blk root disk and a virtio-net NIC.
  4. The guest consumes the NoCloud seed, and the baked coppice-seed.service fallback still applies the same static IP, hostname, DNS, and SSH key if cloud-init stays cautious about local media.
  5. The normal checkout path returns a guest IP and the gateway reaches it over SSH as root, exactly like the other bhyve-backed templates.

Smoke receipt

The Linux receipt is:

It is a thin wrapper around the generic bhyve pool smoke, but it sets:

So the Linux-specific gates are still the real ones:

  1. warm the pool
  2. checkout a clone
  3. wait for SSH on the Linux guest
  4. run a guest command through the SSH path
  5. return and drain cleanly

Why NoCloud

For FreeBSD guests, the pool controller mutates the guest disk directly and drops /etc/coppice-instance. That is a good fit for a UFS image we own.

Linux cloud images already have a standard first-boot control plane: cloud-init. The correct analogue is therefore not “mount ext4 and rewrite random files from the host”, it is “attach a NoCloud seed disk and let the guest consume it the way the distro expects”.

That is what nocloud-seed implements.

GPU hook

The same sidecar layer now also exposes:

TPL_EXTRA_BHYVE_SLOTS='20:0,passthru,ppt0;21:0,passthru,ppt1'

The controller appends each declared slot directly to the bhyve command line. On a host with an NVIDIA card already bound to ppt(4), that is enough to express GPU passthrough without forking the launcher per template.

Honor now has that proof path measured. The debian-12-bhyve-gpu template uses the same sidecar hook, the host applies patches/freebsd-src/bhyve-nvidia-linux-passthrough.diff for the NVIDIA/Linux guest workaround, and benchmarks/results/gpu-passthrough/latest.txt captures a Debian guest checkout ending in GPU_OK. The smoke does more than list PCI visibility: it requires nvidia-smi -L to return an actual GPU N: row, queries name, driver, memory, and GPU utilization through NVML, and captures one nvidia-smi pmon sample from inside the guest before printing GPU_OK. Honor currently runs that receipt with a 2 GiB guest memory window; 4 GiB triggered host AMD-Vi IO_PAGE_FAULT diagnostics and guest RmInitAdapter failures. The passthrough smoke drains the entry after the probe instead of treating same-device destroy/respawn as part of the pass condition; reset/recycle behavior is tracked as the next GPU hardening receipt. CUDA kernel execution and GPU memory-snapshot receipts remain separate hardening steps.