clawdie-iso/docs/POUDRIERE-BUILD-SERVER.md

6 KiB

Poudriere Build Server Plan — v1.0.0

Build colibri/clawdie as proper FreeBSD packages instead of raw cargo build binaries copied into the ISO. Target: HPE ML350p Gen8, 32GB RAM.

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

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    │
│                                          │
│  Services:                               │
│    poudriere (bulk builder)              │
│    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"

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

Total: ~3.5h 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.