Prebuilt package builder
The heavy stack components — Modern and Legacy OpenSSL, ICU, cURL, and every
selected PHP version — reach the fleet as prebuilt .deb packages, so a box
installs them in seconds instead of recompiling each from source. The
self-hosting Prebuilt stack packages page covers that from the consuming box's
side: the _USE_PREBUILT_PKGS switch, the automatic per-component fallback to a
source build, and reading the report log. This page is the producer side —
how those packages are actually built and published.
Packages are produced by stackbuild (aegir/tools/bin/stackbuild) on
dedicated builder-mirror VMs, one per supported release. The load-bearing
property is that the builder re-implements no build logic: it runs after a
real barracuda up-<tree> on a real BOA box of the target release, and only
snapshots, packages, and publishes what the unmodified installer already
built. The _*_VRN version pins in BARRACUDA.sh.txt stay the single source
of truth — stackbuild never sets a version, it detects each installed version
from the tree on disk, so a pin bump is packaged on the next run with no edit to
the builder. And because a package can only exist once the real upgrade succeeded
on a real box of that release, the builder doubles as a standing upgrade
canary ahead of the fleet.
Builder-box invariants
A builder is an ordinary BOA box of its release, pinned into two states:
_USE_PREBUILT_PKGS=NO, set explicitly and permanently in/root/.barracuda.cnf. A builder must always compile from source — if it installed its own packages it would repackage them in a circle.stackbuildenforces this and refuses to run the moment it finds_USE_PREBUILT_PKGS=YES.- The full PHP matrix (
php-max), every build-shape toggle at shipped defaults. An empty_PHP_EXTRA_CONFand no_ICU_FORCE_VRNpin, so the packages carry the default build shape — the only shape a consuming box is ever offered a package for.php-maxguarantees every PHP version is present on disk to snapshot.
The daily cycle
Each builder runs one cron line: barracuda up-<tree> then stackbuild all.
Both are cheap no-ops when nothing changed. When a pin bump lands, the next
upgrade compiles the new version from source on the builder, and the following
stackbuild all packages and publishes it — so any pin bump is packaged within
about 24 hours. Boxes that upgrade inside that window find no package for the
new version yet and fall back to a source build by design: this is just the
normal per-component fallback, not an error.
stackbuild verbs
All verbs require root and re-assert the builder invariant first. package,
publish, and all take a lock (/run/stackbuild.lock) and refuse to run
concurrently.
| Verb | Action |
|---|---|
check |
Report installed versions against published packages |
package |
Build the missing (or explicitly named) packages |
publish |
gzip each built package plus a sha256 sidecar into the mirror /dev/ tree |
sync |
Cross-sync fresh packages to the peer active mirror |
all |
package the missing set, then publish, then sync |
Naming and integrity
Every package is published as a compressed .deb with a checksum sidecar:
boa-<component>_<version>.<codename>_amd64.deb.gz
boa-<component>_<version>.<codename>_amd64.deb.gz.sha256
The installer constructs each filename from its own version pins
(_install_boa_deb in lib/functions/helper.sh.inc), fetches the sidecar
first as a cheap published-or-not probe, and verifies the checksum before
unpacking anything. The sidecar hashes the compressed file, so verification
happens before gunzip. Because the filename carries the exact version, a mirror
safely holds many versions side by side, and publish never deletes an
older package — slower trees and older pins keep resolving to their exact
filename.
Dependency policy
Each package's Depends: carries distro libraries only, resolved on the
builder for its exact release (dpkg-shlibdeps over the staged ELF objects, so
per-release sonames come out right by construction). The BOA-to-BOA ordering
— PHP needs the BOA OpenSSL, ICU, and cURL trees present first — is enforced by
the installer itself, not by dpkg. A published package deliberately carries
no inter-BOA Depends:, so a box whose companion component fell back to a source
build (correct tree on disk, no dpkg record) keeps working, and the
installer's apt-get -f install pass never drags a companion back to source.
Adding a builder mirror for a new release
To bring up the next release's builder — for example Excalibur alongside Daedalus:
- Create and install the VM on the target release the normal way, e.g.
boa in-lts public <fqdn> <email> o1. On a Debian base the installer converts it to Devuan via the matchingauto*tool automatically. - Set the builder invariants:
_USE_PREBUILT_PKGS=NOexplicitly in/root/.barracuda.cnf, and selectphp-maxso all PHP versions build. - Point
stackbuildat the publish dir. It auto-detects_PUB_DIRfrom the existing prebuilt packages under/var/www; on a fresh mirror where that detection does not apply yet, set_PUB_DIRin the tool's configuration block. - Set
_PEER_MIRRORon BOTH active builders so each pushes its release's fresh packages to the other — both then hold the complete package tree. Passive mirrors keep syncing from the authoritative Daedalus mirror exactly as before. - Add the daily cron:
barracuda up-<tree>thenstackbuild all. - Flip the shipped default last. Only after the new release's package set is
published and propagated does the shipped default for that release flip to
YESin a BOA update — never before the packages exist.
Reference
- Commands — the consolidated CLI index,
including
stackbuildand its verbs. - Variables —
_USE_PREBUILT_PKGSand the rest of the_VARcatalogue. - Build & test — the other "prebuilt" path a box fetches:
the Ægir
make_local.tar.gzbundle and the versioned Drush 8 tarball, distinct from these stack.debpackages.