Skip to content

Powered by Grav

Prebuilt package builder

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 truthstackbuild 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. stackbuild enforces 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_CONF and no _ICU_FORCE_VRN pin, so the packages carry the default build shape — the only shape a consuming box is ever offered a package for. php-max guarantees 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:

TXT
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:

  1. 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 matching auto* tool automatically.
  2. Set the builder invariants: _USE_PREBUILT_PKGS=NO explicitly in /root/.barracuda.cnf, and select php-max so all PHP versions build.
  3. Point stackbuild at the publish dir. It auto-detects _PUB_DIR from the existing prebuilt packages under /var/www; on a fresh mirror where that detection does not apply yet, set _PUB_DIR in the tool's configuration block.
  4. Set _PEER_MIRROR on 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.
  5. Add the daily cron: barracuda up-<tree> then stackbuild all.
  6. 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 YES in a BOA update — never before the packages exist.

Reference

  • Commands — the consolidated CLI index, including stackbuild and its verbs.
  • Variables_USE_PREBUILT_PKGS and the rest of the _VAR catalogue.
  • Build & test — the other "prebuilt" path a box fetches: the Ægir make_local.tar.gz bundle and the versioned Drush 8 tarball, distinct from these stack .deb packages.

© 2026 BOA Documentation. All rights reserved.