clawdie-iso/docs/POUDRIERE-BUILD-SERVER.md
Clawdie Operator d4a3d4b9be Poudriere plan: add bhyve virtualization + memory split
- 16GB host (ZFS ARC + Poudriere + services), 16GB bhyve guests
- Phase 6: bhyve test VMs (ISO boot test, Linux cross-compile, builder jail)
- Xeon E5-2400 has VT-x + EPT — full hardware virt
- bhyve packages added to disk-install-extras
2026-06-04 15:58:37 +00:00

8.3 KiB

Poudriere + bhyve Build Server Plan — v1.0.0

Build colibri/clawdie as proper FreeBSD packages instead of raw cargo build binaries copied into the ISO. Plus bhyve virtualization for build test VMs. Target: HPE ML350p Gen8, 32GB RAM, Xeon E5-2400.

Date: 4 Jun 2026 Target server: HPE ProLiant ML350p Gen8 (iLO at 10.0.0.2)


Why

Current build flow:

colibri host (dev machine)
  cargo build --release
  → stage-colibri-iso.sh copies binaries to ISO
  → no version tracking, no pkg metadata, manual

Proposed flow:

ml350p build server (Poudriere)
  → FreeBSD port: sysutils/colibri
  → poudriere builds .pkg files in clean jail
  → pkg repo hosted at pkg.clawdie.home.arpa
  → ISO build does: pkg install colibri

Benefits:

  • Versioned packages with dependencies
  • Clean-room builds (no host contamination)
  • pkg upgrade colibri on deployed machines
  • No Rust toolchain needed on the ISO build host
  • Proper pkg info colibri metadata

Memory split

32GB total — 16GB host, 16GB bhyve:

Host (16GB):
  6GB  — ZFS ARC (primary cache)
  4GB  — Poudriere tmpfs (builds in RAM)
  6GB  — headroom (ARC bursts, nginx, clawdie, SSH)

bhyve (16GB):
  4GB  — FreeBSD build jail (Poudriere test guest)
  4GB  — Linux test guest (cross-compile validation)
  4GB  — FreeBSD ISO test VM (boot clawdie-iso after build)
  4GB  — spare / future CI runner

CPU: Xeon E5-2400 v1/v2 — all SKUs have VT-x + EPT + VT-d. bhyve uses hardware-accelerated virt (no emulation penalty). With 8-10 cores, 2 vCPUs per guest is comfortable.

Architecture

┌──────────────────────────────────────────────────┐
│  HPE ML350p Gen8 (FreeBSD 15)                    │
│                                                   │
│  ZFS pool: zroot                                 │
│    zroot/ROOT/default     ← base system           │
│    zroot/poudriere        ← build jails           │
│    zroot/poudriere/data   ← packages              │
│    zroot/poudriere/ports  ← ports tree            │
│    zroot/bhyve            ← VM disk images        │
│    zroot/bhyve/iso-test   ← ISO boot test VM      │
│                                                   │
│  Services:                                        │
│    poudriere (bulk builder)                       │
│    bhyve (VM host: FreeBSD + Linux + ISO test)    │
│    nginx (pkg repo)                               │
│    clawdie agent (self-hosting)                   │
│    tailscale (mesh)                               │
└──────────────────────────────────────────────────┘

Phase 1 - server provision

1.1 Boot FreeBSD from ISO

# iLO virtual media mount + boot
ipmitool -H 10.0.0.2 -U Administrator -P <pw> power status
ipmitool -H 10.0.0.2 -U Administrator -P <pw> chassis bootdev cdrom
# Mount clawdie-iso via iLO virtual media
ipmitool -H 10.0.0.2 -U Administrator -P <pw> power reset

1.2 Disk survey + ZFS

camcontrol devlist
geom disk list

# Single disk or mirror
zpool create -o ashift=12 zroot /dev/ada0
zfs create -o mountpoint=/ zroot/ROOT/default
zfs create zroot/poudriere
zfs create -o mountpoint=/usr/local/poudriere zroot/poudriere/root

1.3 Install base system

# Install FreeBSD 15 base + kernel to zroot
# Set up /boot, /etc, clawdie service
# Configure network (DHCP, tailscale)

Phase 2 - Poudriere setup

2.1 Install Poudriere

pkg install poudriere

2.2 Configure

# /usr/local/etc/poudriere.conf
ZPOOL=zroot
ZROOTFS=/poudriere
FREEBSD_HOST=download.freebsd.org
RESOLV_CONF=/etc/resolv.conf
BASEFS=/usr/local/poudriere
USE_TMPFS=yes         # build in RAM (we have 32GB)
MAX_MEMORY=4          # limit per-jail RAM
MAX_FILES=2048
DISTFILES_CACHE=/usr/local/poudriere/distfiles
PARALLEL_JOBS=8

2.3 Create jail + ports tree

poudriere jail -c -j 150-amd64 -v 15.0-RELEASE -a amd64
poudriere ports -c -p default -m git -B main

2.4 Create colibri port

Create sysutils/colibri/ in the ports tree:

sysutils/colibri/
├── Makefile
├── distinfo
├── pkg-descr
└── pkg-plist

Makefile (Rust port pattern):

PORTNAME=   colibri
PORTVERSION=    0.0.1
CATEGORIES= sysutils
MASTER_SITES=   https://code.smilepowered.org/clawdie/colibri/archive/
DISTNAME=   ${PORTNAME}-${PORTVERSION}

MAINTAINER= hello@clawdie.si
COMMENT=    Colibri control plane - agent supervision, skills, tasks
WWW=        https://code.smilepowered.org/clawdie/colibri

LICENSE=    MIT

USES=       cargo
USE_GITHUB= no

CARGO_CRATES=   ... # generated by make cargo-crates

.include <bsd.port.mk>

2.5 Build

cd /usr/local/poudriere/ports/default/sysutils/colibri
make makesum        # generate distinfo
make cargo-crates > Makefile.crates  # generate crate list

poudriere bulk -j 150-amd64 -p default sysutils/colibri

Phase 3 - pkg repository

3.1 Nginx pkg repo

pkg install nginx
# /usr/local/etc/nginx/nginx.conf:
#   server { listen 80; root /usr/local/poudriere/data/packages/150-amd64-default; autoindex on; }

service nginx enable
service nginx start

3.2 Client config

On ISO builds and deployed machines:

# /usr/local/etc/pkg/repos/clawdie.conf
clawdie: {
    url: "http://pkg.clawdie.home.arpa/",
    enabled: yes,
}

Phase 4 - ISO integration

Instead of stage-colibri-iso.sh copying raw binaries:

# build.sh - install colibri packages during ISO build
pkg -r ${MOUNT_POINT} install colibri

This gives us:

  • colibri
  • colibri-daemon
  • colibri-tui
  • colibri-smoke-agent

All with proper pkg metadata, upgradeable, with dependencies tracked.

Phase 5 — self-hosted clawdie

Once the server builds itself:

# The ml350p runs its own clawdie agent
service clawdie enable
service clawdie start

# clawdie monitors build jails, runs periodic rebuilds
# clawdie skills include "rebuild-colibri" and "poudriere-status"

Phase 6 — bhyve test VMs

6.1 Enable bhyve kernel module

kldload vmm
sysrc kld_list+="vmm"

6.2 Install bhyve packages

pkg install bhyve-firmware edk2-bhyve vm-bhyve

6.3 Create ZFS datasets for VMs

zfs create zroot/bhyve
zfs create zroot/bhyve/iso-test
zfs create zroot/bhyve/linux-test
zfs create zroot/bhyve/freebsd-test

6.4 Test VMs

FreeBSD ISO test VM (boots clawdie-iso after each build):

vm create -t freebsd iso-test
vm install iso-test clawdie-iso.iso
vm start iso-test
# → verifies ISO boots, colibri starts, clawdie health passes

Linux cross-compile test VM (validates non-FreeBSD targets):

vm create -t linux linux-test
# → test colibri builds on Linux target

FreeBSD Poudriere test jail VM (full pkg build validation):

vm create -t freebsd freebsd-test
# → clone poudriere setup, run bulk build as validation

6.5 Packages for ISO

Add to pkg-list-disk-install-extras.txt (installed on deployed server, not live USB):

bhyve-firmware
edk2-bhyve
vm-bhyve

Timeline

Step Effort Depends on
1. Server provision (ZFS, base system) ~1h iLO password, ISO boots
2. Poudriere setup ~30m base system running
3. colibri port creation ~1h Poudriere running
4. First pkg build ~30m (compile) port ready
5. pkg repo + nginx ~15m packages built
6. ISO integration ~15m repo hosted
7. bhyve + test VMs ~30m base system + ZFS

Total: ~4h once iLO password is available.

Notes

  • Rust target x86_64-unknown-freebsd stays — that's the compiler triple. The package name is colibri (or clawdie-colibri), no "unknown" in package branding.
  • Poudriere builds each package in a clean jail — no host Rust toolchain pollution. The jail installs lang/rust from ports automatically.
  • 32GB RAM + tmpfs means builds stay in memory (fast, no SSD wear).
  • Tailscale mesh means the operator USB can install packages from this server even after deploying to a different machine.
  • Xeon E5-2400 has VT-x + EPT — full hardware virt acceleration.
  • bhyve guests can run concurrently with Poudriere builds (16GB reserved for VMs, 16GB for host).