Merge pull request 'combined/iso-poudriere-livepower' (#75) from combined/iso-poudriere-livepower into main
Reviewed-on: #75
This commit is contained in:
commit
352a1d6da9
6 changed files with 387 additions and 68 deletions
|
|
@ -1,11 +1,21 @@
|
|||
# Poudriere + bhyve Build Server Plan — v1.0.0
|
||||
# Poudriere + bhyve Build Server Plan — v2.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.
|
||||
> Target: the **`mother-build`** host (FreeBSD VPS) serving **`pkg.clawdie.si`** —
|
||||
> the package half of the trusted supply chain (layered-soul `HIVE-ONBOARDING.md §10`).
|
||||
|
||||
**Date:** 4 Jun 2026
|
||||
**Target server:** HPE ProLiant ML350p Gen8 (iLO at 10.0.0.2)
|
||||
**Date:** 4 Jun 2026 (v1.0.0) · retargeted 20 Jun 2026 (v2.0.0)
|
||||
**Target server:** `mother-build` — a FreeBSD VPS with a ZFS pool (OVHcloud candidate;
|
||||
see layered-soul `HOST-MATRIX.md`). The original ML350p Gen8 target is **retired**
|
||||
(boot-looping); host provisioning is now provider-specific, not iLO/IPMI. Hardware-
|
||||
specific sizing below (32 GB split, Xeon VT-x) is kept only as **reference numbers**
|
||||
from the ML350p — scale them to the chosen `mother-build` plan.
|
||||
|
||||
**Scripts:** the reproducible Phase 2–3 steps are implemented in
|
||||
[`../scripts/poudriere/`](../scripts/poudriere/) — `poudriere-setup.sh`,
|
||||
`poudriere-build.sh`, `clawdie-repo.conf.in`. This doc is the rationale, host-
|
||||
provisioning context, and the manual reference those scripts encode.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -23,10 +33,10 @@ colibri host (dev machine)
|
|||
Proposed flow:
|
||||
|
||||
```
|
||||
ml350p build server (Poudriere)
|
||||
mother-build server (Poudriere)
|
||||
→ FreeBSD port: sysutils/colibri
|
||||
→ poudriere builds .pkg files in clean jail
|
||||
→ pkg repo hosted at pkg.clawdie.home.arpa
|
||||
→ signed pkg repo hosted at pkg.clawdie.si
|
||||
→ ISO build does: pkg install colibri
|
||||
```
|
||||
|
||||
|
|
@ -38,9 +48,11 @@ Benefits:
|
|||
- No Rust toolchain needed on the ISO build host
|
||||
- Proper `pkg info colibri` metadata
|
||||
|
||||
## Memory split
|
||||
## Memory split (reference sizing — ML350p 32 GB)
|
||||
|
||||
32GB total — 16GB host, 16GB bhyve:
|
||||
These numbers are the original ML350p reference; on a smaller cloud `mother-build`
|
||||
plan, poudriere alone needs little (drop `USE_TMPFS` if RAM is tight) and the bhyve
|
||||
guests are optional. 32GB total — 16GB host, 16GB bhyve:
|
||||
|
||||
```
|
||||
Host (16GB):
|
||||
|
|
@ -63,7 +75,7 @@ With 8-10 cores, 2 vCPUs per guest is comfortable.
|
|||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ HPE ML350p Gen8 (FreeBSD 15) │
|
||||
│ mother-build host (FreeBSD 15) │
|
||||
│ │
|
||||
│ ZFS pool: zroot │
|
||||
│ zroot/ROOT/default ← base system │
|
||||
|
|
@ -82,17 +94,14 @@ With 8-10 cores, 2 vCPUs per guest is comfortable.
|
|||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Phase 1 - server provision
|
||||
## Phase 1 - server provision (provider-specific)
|
||||
|
||||
### 1.1 Boot FreeBSD from ISO
|
||||
### 1.1 Get a booted FreeBSD host
|
||||
|
||||
```sh
|
||||
# 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
|
||||
```
|
||||
Host provisioning is **provider-specific** and out of scope for the scripts. On
|
||||
OVHcloud, install FreeBSD via the rescue system or a FreeBSD template/image; the
|
||||
old ML350p iLO/IPMI virtual-media path is retired. The poudriere scripts assume you
|
||||
already have a **booted FreeBSD host with a ZFS pool** (default `zroot`).
|
||||
|
||||
### 1.2 Disk survey + ZFS
|
||||
|
||||
|
|
@ -117,6 +126,12 @@ zfs create -o mountpoint=/usr/local/poudriere zroot/poudriere/root
|
|||
|
||||
## Phase 2 - Poudriere setup
|
||||
|
||||
> **Scripted (DONE).** `poudriere-setup.sh` performs 2.1–2.3 idempotently
|
||||
> (install, `poudriere.conf` incl. `PKG_REPO_SIGNING_KEY`, signing-key generation,
|
||||
> jail, ports tree) after validating root / version / pool. `poudriere-build.sh`
|
||||
> performs 2.5 (bulk + automatic repo signing). The steps below are the reference
|
||||
> they encode; only 2.4 (creating the `sysutils/colibri` port) is still manual.
|
||||
|
||||
### 2.1 Install Poudriere
|
||||
|
||||
```sh
|
||||
|
|
@ -142,8 +157,9 @@ PARALLEL_JOBS=8
|
|||
### 2.3 Create jail + ports tree
|
||||
|
||||
```sh
|
||||
poudriere jail -c -j 150-amd64 -v 15.0-RELEASE -a amd64
|
||||
poudriere ports -c -p default -m git -B main
|
||||
# poudriere-setup.sh does this with these names by default:
|
||||
poudriere jail -c -j clawdie-amd64 -v 15.0-RELEASE -a amd64
|
||||
poudriere ports -c -p clawdie -m git -B main
|
||||
```
|
||||
|
||||
### 2.4 Create colibri port
|
||||
|
|
@ -160,35 +176,27 @@ sysutils/colibri/
|
|||
|
||||
**Makefile** (Rust port pattern):
|
||||
|
||||
```makefile
|
||||
PORTNAME= colibri
|
||||
PORTVERSION= 0.0.1
|
||||
CATEGORIES= sysutils
|
||||
MASTER_SITES= https://code.smilepowered.org/clawdie/colibri/archive/
|
||||
DISTNAME= ${PORTNAME}-${PORTVERSION}
|
||||
The port files are maintained in the **colibri** repo (source-of-truth, kept
|
||||
with the code) at `packaging/freebsd/port/sysutils/colibri/` — `Makefile`,
|
||||
`pkg-descr`, `pkg-plist`, plus a README covering generation. Don't hand-copy a
|
||||
Makefile here; drop that directory into the ports tree. Key facts:
|
||||
|
||||
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>
|
||||
```
|
||||
- `LICENSE= AGPLv3` (per `colibri/Cargo.toml` — **not** MIT).
|
||||
- `USES= cargo`; source from the Forgejo archive (tagged `v${DISTVERSION}`).
|
||||
- Ships 6 binaries: `clawdie`, `colibri`, `colibri-daemon`, `colibri-mcp`,
|
||||
`colibri-test-agent`, `colibri-tui`.
|
||||
- `CARGO_CRATES` and `distinfo` are generated on the build host
|
||||
(`make cargo-crates`, `make makesum`).
|
||||
|
||||
### 2.5 Build
|
||||
|
||||
```sh
|
||||
cd /usr/local/poudriere/ports/default/sysutils/colibri
|
||||
cd /usr/local/poudriere/ports/clawdie/sysutils/colibri
|
||||
make makesum # generate distinfo
|
||||
make cargo-crates > Makefile.crates # generate crate list
|
||||
|
||||
poudriere bulk -j 150-amd64 -p default sysutils/colibri
|
||||
# then build via the wrapper (validates + signs):
|
||||
poudriere-build.sh --jail clawdie-amd64 --ports clawdie sysutils/colibri
|
||||
```
|
||||
|
||||
## Phase 3 - pkg repository
|
||||
|
|
@ -198,7 +206,9 @@ poudriere bulk -j 150-amd64 -p default sysutils/colibri
|
|||
```sh
|
||||
pkg install nginx
|
||||
# /usr/local/etc/nginx/nginx.conf:
|
||||
# server { listen 80; root /usr/local/poudriere/data/packages/150-amd64-default; autoindex on; }
|
||||
# server { listen 443 ssl; server_name pkg.clawdie.si;
|
||||
# root /usr/local/poudriere/data/packages/clawdie-amd64-clawdie; autoindex on; }
|
||||
# TLS via acme.sh (osa/mother-build already carry nginx + acme).
|
||||
|
||||
service nginx enable
|
||||
service nginx start
|
||||
|
|
@ -206,16 +216,19 @@ service nginx start
|
|||
|
||||
### 3.2 Client config
|
||||
|
||||
On ISO builds and deployed machines:
|
||||
On ISO builds and deployed jails, generate from
|
||||
[`../scripts/poudriere/clawdie-repo.conf.in`](../scripts/poudriere/clawdie-repo.conf.in)
|
||||
and ship the **public** key from Phase 2. The repo is **signed**, so clients verify:
|
||||
|
||||
```sh
|
||||
# /usr/local/etc/pkg/repos/clawdie.conf
|
||||
clawdie: {
|
||||
url: "http://pkg.clawdie.home.arpa/",
|
||||
enabled: yes,
|
||||
}
|
||||
sed "s#__PKG_URL__#https://pkg.clawdie.si/#; s#__PUBKEY_PATH__#/usr/share/keys/pkg/clawdie.pub#" \
|
||||
clawdie-repo.conf.in > /usr/local/etc/pkg/repos/clawdie.conf
|
||||
install -m 0444 /usr/local/etc/ssl/clawdie-pkg.pub /usr/share/keys/pkg/clawdie.pub
|
||||
```
|
||||
|
||||
For first-party-only (paid) tenants, lower the stock FreeBSD repo priority so
|
||||
resolution prefers signed Clawdie packages.
|
||||
|
||||
## Phase 4 - ISO integration
|
||||
|
||||
Instead of `stage-colibri-iso.sh` copying raw binaries:
|
||||
|
|
@ -241,7 +254,7 @@ Once the deployed-system service implementation lands and the server builds
|
|||
itself:
|
||||
|
||||
```sh
|
||||
# The ml350p runs its own deployed-system clawdie service
|
||||
# The mother-build host runs its own deployed-system clawdie service
|
||||
service clawdie enable
|
||||
service clawdie start
|
||||
|
||||
|
|
@ -254,6 +267,16 @@ The current live USB does not stage `service clawdie`; it runs
|
|||
|
||||
## Phase 6 — bhyve test VMs
|
||||
|
||||
> **Largely DONE (on the ISO-build host, not yet on `mother-build`).** The
|
||||
> ISO-boot test VM exists and is wired as a **build gate**:
|
||||
> [`../scripts/bhyve-test.sh`](../scripts/bhyve-test.sh) boots the built image in
|
||||
> bhyve with `com1,stdio`, and [`../scripts/run-bhyve-test.sh`](../scripts/run-bhyve-test.sh)
|
||||
> scans the serial console for required boot markers / forbidden failures (panics,
|
||||
> restart loops, the colibri permission-denied regression) and exits non-zero on a
|
||||
> critical miss. [`../scripts/bhyve-pf-allow.sh`](../scripts/bhyve-pf-allow.sh) opens
|
||||
> the guest network. What remains: replicate this on `mother-build` and add the
|
||||
> Linux cross-compile / poudriere-validation guests (6.4) if wanted.
|
||||
|
||||
### 6.1 Enable bhyve kernel module
|
||||
|
||||
```sh
|
||||
|
|
@ -313,17 +336,18 @@ 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 |
|
||||
| Step | Effort | Status / depends on |
|
||||
| -------------------------------------- | -------------- | --------------------------------------------------- |
|
||||
| 1. Provision `mother-build` host | ~1h | PENDING — OVH FreeBSD VPS + ZFS pool (cost-gated) |
|
||||
| 2. Poudriere setup | ~30m | **SCRIPTED** — `poudriere-setup.sh`; needs the host |
|
||||
| 3. colibri port creation | ~1h | PENDING — write `sysutils/colibri` (manual, §2.4) |
|
||||
| 4. First pkg build | ~30m (compile) | **SCRIPTED** — `poudriere-build.sh`; needs the port |
|
||||
| 5. pkg repo + nginx (`pkg.clawdie.si`) | ~15m | PENDING — nginx + acme + DNS |
|
||||
| 6. ISO integration | ~15m | PENDING — `pkg install` in `build.sh` (Phase 4) |
|
||||
| 7. bhyve ISO-boot test gate | done | **DONE** — `bhyve-test.sh` + `run-bhyve-test.sh` |
|
||||
|
||||
**Total: ~4h** once iLO password is available.
|
||||
**Critical path:** provision `mother-build` → write the colibri port → run the two
|
||||
scripts → stand up nginx/DNS. The host purchase is gated on the HOST-MATRIX cost rows.
|
||||
|
||||
## Notes
|
||||
|
||||
|
|
@ -332,9 +356,9 @@ vm-bhyve
|
|||
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).
|
||||
- `USE_TMPFS=yes` keeps builds in RAM (fast, no SSD wear) when the host has the
|
||||
memory; drop it on a small cloud plan.
|
||||
- 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).
|
||||
- bhyve needs a host with VT-x + EPT (the ML350p's Xeon E5-2400 had it; confirm
|
||||
the chosen OVH plan exposes nested virt before relying on Phase 6 there).
|
||||
|
|
|
|||
|
|
@ -1,14 +1,22 @@
|
|||
#!/bin/sh
|
||||
# PROVIDE: clawdie_live_power
|
||||
# REQUIRE: FILESYSTEMS syslogd
|
||||
# BEFORE: LOGIN
|
||||
# KEYWORD: nojail
|
||||
#
|
||||
# Clawdie operator USB live power baseline.
|
||||
# Applies the rc.conf power_profile C-state policy once at boot. FreeBSD's
|
||||
# power_profile service is marked nostart and normally runs only when devd sees
|
||||
# an AC-line transition, so a live USB can otherwise sit at the firmware/default
|
||||
# C-state until AC is unplugged/replugged.
|
||||
|
||||
# PROVIDE: clawdie_live_power
|
||||
# REQUIRE: FILESYSTEMS syslogd
|
||||
# BEFORE: LOGIN
|
||||
# KEYWORD: nojail
|
||||
#
|
||||
# Scope: this selects a CPU C-state/frequency profile ONLY. It never suspends,
|
||||
# sleeps, blanks the screen, or enables DPMS (screen-blank is handled separately
|
||||
# by the no-blank stack: xorg.conf.d/40-clawdie-noblank.conf + the power-manager
|
||||
# skel + clawdie-noblank-guard.sh). Both branches are wake-safe: rc.conf pins
|
||||
# performance_cx_lowest AND economy_cx_lowest to C3, so neither the AC (0x01) nor
|
||||
# battery (0x00) profile can drop into a deeper C-state that breaks the
|
||||
# USB-backed resume path. Keep both at C3 on the live USB — do not deepen.
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
|
|
|
|||
58
scripts/poudriere/README.md
Normal file
58
scripts/poudriere/README.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# First-party package build server (`pkg.clawdie.si`)
|
||||
|
||||
Lean scripts that turn the manual Phase 2–3 runbook in
|
||||
[`../../docs/POUDRIERE-BUILD-SERVER.md`](../../docs/POUDRIERE-BUILD-SERVER.md) into
|
||||
repeatable, idempotent steps. They run on the **`mother-build`** host (FreeBSD) and
|
||||
produce the **first-party, signed** package repo that paid tenants pull from instead
|
||||
of public mirrors — the package half of the trusted supply chain
|
||||
([layered-soul `HIVE-ONBOARDING.md §10`](https://code.smilepowered.org/clawdie/layered-soul)).
|
||||
|
||||
These scripts deliberately do not provision the host (ZFS pool, base system,
|
||||
networking) — that is hardware-specific and stays in the runbook. They assume a
|
||||
FreeBSD host with a ZFS pool already present.
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
poudriere-setup.sh → poudriere-build.sh → serve + client config
|
||||
(config, key, jail, (build ports into the (nginx over the repo dir;
|
||||
ports tree) signed repo) clawdie-repo.conf.in)
|
||||
```
|
||||
|
||||
1. **Set up** (idempotent; re-run anytime):
|
||||
|
||||
```sh
|
||||
mdo -u root ./poudriere-setup.sh --zpool zroot
|
||||
```
|
||||
|
||||
Generates `/usr/local/etc/ssl/clawdie-pkg.{key,pub}`, writes
|
||||
`/usr/local/etc/poudriere.conf` (only if absent), and creates the build jail and
|
||||
ports tree. The **public** key is what clients trust.
|
||||
|
||||
2. **Build** (signs the repo automatically via `PKG_REPO_SIGNING_KEY`):
|
||||
|
||||
```sh
|
||||
mdo -u root ./poudriere-build.sh --jail clawdie-amd64 --ports clawdie sysutils/colibri
|
||||
```
|
||||
|
||||
The `sysutils/colibri` port itself (Makefile/distinfo/pkg-plist) is created in the
|
||||
ports tree per the runbook's Phase 2.4.
|
||||
|
||||
3. **Serve + clients.** Point nginx at
|
||||
`/usr/local/poudriere/data/packages/clawdie-amd64-clawdie` for `https://pkg.clawdie.si/`
|
||||
(osa/mother-build already carry `nginx` + `acme`). Generate each client's repo config
|
||||
from the template and ship the public key:
|
||||
|
||||
```sh
|
||||
sed "s#__PKG_URL__#https://pkg.clawdie.si/#; s#__PUBKEY_PATH__#/usr/share/keys/pkg/clawdie.pub#" \
|
||||
clawdie-repo.conf.in > /usr/local/etc/pkg/repos/clawdie.conf
|
||||
install -m 0444 /usr/local/etc/ssl/clawdie-pkg.pub /usr/share/keys/pkg/clawdie.pub
|
||||
```
|
||||
|
||||
## Conventions
|
||||
|
||||
- POSIX `sh`, `set -u`, fixed `PATH`, `usage()` + strict arg parsing, **verify-then-act**
|
||||
(inputs and environment are validated before anything is created). Matches
|
||||
`live/operator-session/hw-report`.
|
||||
- Idempotent: existing config, key, jail, and ports tree are left untouched.
|
||||
- Defaults are overridable by flag or `POUDRIERE_*` env var.
|
||||
18
scripts/poudriere/clawdie-repo.conf.in
Normal file
18
scripts/poudriere/clawdie-repo.conf.in
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# First-party Clawdie package repo. Install on clients (ISO build root and
|
||||
# deployed jails) as /usr/local/etc/pkg/repos/clawdie.conf, after substituting
|
||||
# __PKG_URL__ and shipping the public key to __PUBKEY_PATH__.
|
||||
#
|
||||
# sed "s#__PKG_URL__#https://pkg.clawdie.si/#" clawdie-repo.conf.in > clawdie.conf
|
||||
# install -m 0444 clawdie-pkg.pub __PUBKEY_PATH__ # from poudriere-setup.sh
|
||||
#
|
||||
# For first-party-only (paid) tenants, also set the stock FreeBSD repo to a
|
||||
# lower priority (or disabled) so resolution prefers signed Clawdie packages.
|
||||
|
||||
clawdie: {
|
||||
url: "__PKG_URL__",
|
||||
mirror_type: "none",
|
||||
signature_type: "pubkey",
|
||||
pubkey: "__PUBKEY_PATH__",
|
||||
priority: 100,
|
||||
enabled: yes
|
||||
}
|
||||
72
scripts/poudriere/poudriere-build.sh
Executable file
72
scripts/poudriere/poudriere-build.sh
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
#!/bin/sh
|
||||
# Build one or more ports into the first-party repo with poudriere, then refresh
|
||||
# repo metadata (signed via PKG_REPO_SIGNING_KEY in poudriere.conf). Validates
|
||||
# the jail, ports tree, and each origin before building. Run as root.
|
||||
|
||||
set -u
|
||||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
export PATH
|
||||
|
||||
BASEFS="${POUDRIERE_BASEFS:-/usr/local/poudriere}"
|
||||
JAIL="${POUDRIERE_JAIL:-clawdie-amd64}"
|
||||
PTREE="${POUDRIERE_PTREE:-clawdie}"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: poudriere-build.sh [--jail NAME] [--ports NAME] ORIGIN [ORIGIN ...]
|
||||
|
||||
Builds each ORIGIN (category/name, e.g. sysutils/colibri) in the clean jail and
|
||||
publishes signed packages to the first-party repo.
|
||||
|
||||
Options (or POUDRIERE_* env):
|
||||
--jail NAME build jail (default: ${JAIL})
|
||||
--ports NAME ports tree (default: ${PTREE})
|
||||
-h, --help show this help
|
||||
EOF
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "ERROR: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
have() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--jail) JAIL="${2:?--jail needs a value}"; shift 2 ;;
|
||||
--ports) PTREE="${2:?--ports needs a value}"; shift 2 ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
--) shift; break ;;
|
||||
-*) echo "ERROR: unknown option: $1" >&2; usage >&2; exit 2 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ "$#" -ge 1 ] || { echo "ERROR: need at least one ORIGIN" >&2; usage >&2; exit 2; }
|
||||
|
||||
# --- verify, then act -------------------------------------------------------
|
||||
|
||||
[ "$(id -u)" -eq 0 ] || die "must run as root."
|
||||
have poudriere || die "poudriere not found; run poudriere-setup.sh first."
|
||||
poudriere jail -i -j "${JAIL}" >/dev/null 2>&1 || die "jail '${JAIL}' not found; run poudriere-setup.sh."
|
||||
poudriere ports -l | awk 'NR>1 {print $1}' | grep -Fxq "${PTREE}" || die "ports tree '${PTREE}' not found."
|
||||
|
||||
_ports_root="${BASEFS}/ports/${PTREE}"
|
||||
for _origin in "$@"; do
|
||||
case "${_origin}" in
|
||||
*/*) ;;
|
||||
*) die "origin '${_origin}' must be category/name (e.g. sysutils/colibri)." ;;
|
||||
esac
|
||||
[ -f "${_ports_root}/${_origin}/Makefile" ] || \
|
||||
die "port '${_origin}' not found under ${_ports_root}."
|
||||
done
|
||||
|
||||
poudriere bulk -j "${JAIL}" -p "${PTREE}" "$@" || die "bulk build failed."
|
||||
|
||||
echo ""
|
||||
echo "Build complete. Signed repo at:"
|
||||
echo " ${BASEFS}/data/packages/${JAIL}-${PTREE}"
|
||||
echo "Serve that directory over nginx at pkg.clawdie.si (see README.md)."
|
||||
139
scripts/poudriere/poudriere-setup.sh
Executable file
139
scripts/poudriere/poudriere-setup.sh
Executable file
|
|
@ -0,0 +1,139 @@
|
|||
#!/bin/sh
|
||||
# Set up a first-party FreeBSD package build server (poudriere) for
|
||||
# pkg.clawdie.si. Idempotent: safe to re-run. Validates the environment and
|
||||
# inputs first, then acts. Run on the mother-build host as root.
|
||||
#
|
||||
# After this: build with poudriere-build.sh, serve the repo over nginx, and
|
||||
# hand clients clawdie-repo.conf.in. See README.md.
|
||||
|
||||
set -u
|
||||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
export PATH
|
||||
|
||||
ZPOOL="${POUDRIERE_ZPOOL:-zroot}"
|
||||
ZROOTFS="${POUDRIERE_ZROOTFS:-/poudriere}"
|
||||
BASEFS="${POUDRIERE_BASEFS:-/usr/local/poudriere}"
|
||||
VERSION="${POUDRIERE_VERSION:-15.0-RELEASE}"
|
||||
ARCH="${POUDRIERE_ARCH:-amd64}"
|
||||
JAIL="${POUDRIERE_JAIL:-clawdie-${ARCH}}"
|
||||
PTREE="${POUDRIERE_PTREE:-clawdie}"
|
||||
PORTS_BRANCH="${POUDRIERE_PORTS_BRANCH:-main}"
|
||||
KEYDIR="${POUDRIERE_KEYDIR:-/usr/local/etc/ssl}"
|
||||
KEY="${KEYDIR}/clawdie-pkg.key"
|
||||
PUB="${KEYDIR}/clawdie-pkg.pub"
|
||||
CONF="/usr/local/etc/poudriere.conf"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: poudriere-setup.sh [options]
|
||||
|
||||
Idempotently prepares poudriere on this host: config, signing key, build jail,
|
||||
and a ports tree. Re-running skips anything already present.
|
||||
|
||||
Options (or set the matching POUDRIERE_* env var):
|
||||
--zpool NAME ZFS pool poudriere stores under (default: ${ZPOOL})
|
||||
--version VER FreeBSD jail version (default: ${VERSION})
|
||||
--arch ARCH jail architecture (default: ${ARCH})
|
||||
--jail NAME build jail name (default: ${JAIL})
|
||||
--ports NAME ports tree name (default: ${PTREE})
|
||||
-h, --help show this help
|
||||
EOF
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "ERROR: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
have() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
info() {
|
||||
printf '==> %s\n' "$*"
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--zpool) ZPOOL="${2:?--zpool needs a value}"; shift 2 ;;
|
||||
--version) VERSION="${2:?--version needs a value}"; shift 2 ;;
|
||||
--arch) ARCH="${2:?--arch needs a value}"; shift 2 ;;
|
||||
--jail) JAIL="${2:?--jail needs a value}"; shift 2 ;;
|
||||
--ports) PTREE="${2:?--ports needs a value}"; shift 2 ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "ERROR: unknown option: $1" >&2; usage >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- verify, then act -------------------------------------------------------
|
||||
|
||||
[ "$(id -u)" -eq 0 ] || die "must run as root (poudriere setup creates jails)."
|
||||
|
||||
case "${VERSION}" in
|
||||
[0-9]*.[0-9]*-RELEASE|[0-9]*.[0-9]*-STABLE|[0-9]*.[0-9]*-CURRENT) ;;
|
||||
*) die "invalid --version '${VERSION}' (expected e.g. 15.0-RELEASE)." ;;
|
||||
esac
|
||||
|
||||
have pkg || die "pkg not found; run on a FreeBSD host."
|
||||
have openssl || die "openssl not found (needed to generate the repo signing key)."
|
||||
zpool list "${ZPOOL}" >/dev/null 2>&1 || die "ZFS pool '${ZPOOL}' not found; create it or pass --zpool."
|
||||
|
||||
# --- act --------------------------------------------------------------------
|
||||
|
||||
if ! have poudriere; then
|
||||
info "installing poudriere"
|
||||
env ASSUME_ALWAYS_YES=yes pkg install -y poudriere || die "pkg install poudriere failed."
|
||||
fi
|
||||
|
||||
if [ ! -f "${KEY}" ]; then
|
||||
info "generating repo signing key: ${KEY}"
|
||||
mkdir -p "${KEYDIR}"
|
||||
( umask 077; openssl genrsa -out "${KEY}" 4096 ) || die "failed to generate signing key."
|
||||
openssl rsa -in "${KEY}" -pubout -out "${PUB}" || die "failed to derive public key."
|
||||
chmod 0400 "${KEY}"
|
||||
fi
|
||||
|
||||
if [ ! -f "${CONF}" ]; then
|
||||
info "writing ${CONF}"
|
||||
cat > "${CONF}" <<EOF
|
||||
# Clawdie first-party package build server. Managed by poudriere-setup.sh.
|
||||
ZPOOL=${ZPOOL}
|
||||
ZROOTFS=${ZROOTFS}
|
||||
BASEFS=${BASEFS}
|
||||
FREEBSD_HOST=download.freebsd.org
|
||||
RESOLV_CONF=/etc/resolv.conf
|
||||
DISTFILES_CACHE=${BASEFS}/distfiles
|
||||
USE_TMPFS=yes
|
||||
# poudriere signs the repo catalog with this key on every bulk run; clients
|
||||
# trust the matching public key (${PUB}). See clawdie-repo.conf.in.
|
||||
PKG_REPO_SIGNING_KEY=${KEY}
|
||||
EOF
|
||||
else
|
||||
info "${CONF} exists; leaving it untouched"
|
||||
fi
|
||||
|
||||
if poudriere jail -i -j "${JAIL}" >/dev/null 2>&1; then
|
||||
info "jail '${JAIL}' exists; skipping"
|
||||
else
|
||||
info "creating jail '${JAIL}' (${VERSION} ${ARCH})"
|
||||
poudriere jail -c -j "${JAIL}" -v "${VERSION}" -a "${ARCH}" || die "jail create failed."
|
||||
fi
|
||||
|
||||
if poudriere ports -l | awk 'NR>1 {print $1}' | grep -Fxq "${PTREE}"; then
|
||||
info "ports tree '${PTREE}' exists; skipping"
|
||||
else
|
||||
info "creating ports tree '${PTREE}' (git ${PORTS_BRANCH})"
|
||||
poudriere ports -c -p "${PTREE}" -m git -B "${PORTS_BRANCH}" || die "ports tree create failed."
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Poudriere is ready.
|
||||
jail: ${JAIL}
|
||||
ports tree: ${PTREE}
|
||||
signing key: ${KEY}
|
||||
public key: ${PUB} <-- ship this to clients (see clawdie-repo.conf.in)
|
||||
|
||||
Next:
|
||||
./poudriere-build.sh --jail ${JAIL} --ports ${PTREE} sysutils/colibri
|
||||
EOF
|
||||
Loading…
Add table
Reference in a new issue