Automated codename upgrades

Moving a BOA host between Devuan codenames (beowulf → chimaera → daedalus → excalibur) is driven by a family of auto* codename scripts in /usr/local/bin/, triggered by a run-to-*.cnf marker and launched by the clean-boa-env service. Each script runs a chain of barracuda up-<tier> system passes and reboots, advancing the OS one codename per pass until it reaches its named target. This is the path to prefer for the supported targets; the explicit per-hop alternative is the classic major OS upgrade.

Backup, test the backup, then proceed. This is an unattended migration chain across multiple reboots. If it wedges mid-chain there is no in-place rescue — recovery is "restore the VM snapshot." Do not start without a tested backup. The provider boot caveats below are why Step 1 is non-negotiable.

The four codename drivers

Target codename Driver script Trigger marker
Excalibur (latest) autoexcalibur /root/.run-to-excalibur.cnf
Daedalus (recommended) autodaedalus /root/.run-to-daedalus.cnf
Chimaera autochimaera /root/.run-to-chimaera.cnf
Beowulf autobeowulf /root/.run-to-beowulf.cnf

All four share one template; they differ only in the named target and the intermediate hops they walk through. Each driver carries the full _${FROM}_TO_${TO}=YES pairing set for every codename below its target, so a single trigger walks the whole chain. autoexcalibur, for example, carries _BULLSEYE_TO_CHIMAERA, _BEOWULF_TO_CHIMAERA, _BOOKWORM_TO_DAEDALUS, _CHIMAERA_TO_DAEDALUS, _TRIXIE_TO_EXCALIBUR and _DAEDALUS_TO_EXCALIBUR.

Which target

  • Daedalus is the recommended production target. Stable, well-tested, supports Percona 5.7, 8.0 and 8.4.
  • Excalibur is the latest. Supported, but only with Percona 8.4 — there is no 5.7 or 8.0 path on Excalibur. Stage the DB to 8.4 on Daedalus first (see Percona sequencing below); autoexcalibur enforces this with a hard pre-flight gate.
  • Chimaera is supported as a stepping stone; upgrade off it to Daedalus.
  • Beowulf is a rescue target, not a destination: use it to get a very old Debian box onto Devuan, then chain forward to Daedalus.

Running the chain

The procedure is identical for all four targets — only the trigger marker changes.

Step 1 — Snapshot and verify the snapshot

Take a fresh VM snapshot, restore it to a throwaway VM, and confirm the restored VM boots and the BOA host works. Do not proceed until the backup is proven.

Step 2 — Pre-flight barracuda pass and clean reboot

A clean baseline first, so nothing is half-applied going in:

screen
barracuda up-lts system
boa reboot

If that reboot is not clean — boot fails, services don't come up, network is unreachable — fix it before triggering the chain. A major-OS chain on a host that already has boot problems guarantees a bad outcome.

Step 3 — Refresh the meta-installers

wget -qO- https://files.boa.io/BOA.sh.txt | bash

This installs the current auto* codename drivers and barracuda/octopus shims into /usr/local/bin.

Step 4 — Drop exactly one trigger marker and launch

# Recommended production target
touch /root/.run-to-daedalus.cnf

# Or: latest (Excalibur — Percona 8.4 only, see below)
touch /root/.run-to-excalibur.cnf

# Or: intermediate stops
touch /root/.run-to-chimaera.cnf
touch /root/.run-to-beowulf.cnf

Then launch:

service clean-boa-env start

The driver walks barracuda up-<tier> system + reboot for each intermediate codename until it reaches the target. The tier is the host's own (_tRee), not a fixed lts — each driver runs barracuda up-${_tRee} system, so an LTS host chains with up-lts, a PRO host with up-pro. (_tRee is baked per release branch: the LTS-branch driver pins export _tRee=lts, the PRO-branch driver pro, the dev-branch driver dev; the host fetches the copy matching its tier.)

Step 5 — Wait it out

A two-codename jump (e.g. Chimaera → Daedalus) is typically 30–60 minutes; a Debian-Buster → Devuan-Daedalus chain through several codenames can take 2–3 hours. The host reboots multiple times. Do not intervene unless a reboot fails to come back.

Step 6 — Verify

# Confirm the Devuan codename
lsb_release -ar 2>/dev/null

# Confirm BOA is back and on the expected DB series
boa info | grep -i db
mysql -e "SELECT VERSION();"

boa info | grep -c Percona returns 3 once the post-upgrade chain has fully completed, including the cron-triggered background phase — a quick confirmation that the DB layer has settled. You can also check the codename with lsb_release and the DB series with SELECT VERSION().

Starting from Debian

autoinit/automini carry the Debian→Devuan codename map and advance one step per pass, with one mandatory consequence to know up front: the per-source-OS target is not universally Daedalus.

Starting OS First Devuan hop
Debian Trixie (13) Excalibur (touches /root/.top-excalibur.cnf)
Debian Bookworm (12) Daedalus
Debian Bullseye (11) Chimaera
Debian Buster (10) Beowulf
Devuan Chimaera Daedalus
Devuan Beowulf Chimaera
Devuan Daedalus / Excalibur (terminal — no further hop)

A Trixie box therefore lands on Excalibur, not Daedalus, and so inherits the Excalibur Percona-8.4 requirement. Older Debian releases that cannot reach Daedalus in one hop walk an intermediate codename first; chain to the next target after the first chain completes and the host is stable.

Percona sequencing across the chain

The DB series the host carries constrains which OS targets are reachable:

  • Daedalus defaults to Percona 5.7. You can stage forward in place: barracuda up-lts system percona-8.0 (5.7 → 8.0), then barracuda up-lts system percona-8.4 (8.0 → 8.4). There is no direct 5.7 → 8.4 jump.
  • Excalibur requires Percona 8.4. autoexcalibur runs _check_mysql_compatibility up front and refuses to proceed (exit 1) on anything but 8.4, telling you exactly what to run first:
    • on Percona 8.0barracuda up-lts system percona-8.4 once;
    • on Percona 5.7barracuda up-lts system percona-8.4 twice (5.7 → 8.0, then 8.0 → 8.4).

The full staged-upgrade mechanics, recovery guards and the client-library soname ladder are in Percona install + tuning.

What the Daedalus/Excalibur path also changes

Beyond the Percona requirement, reaching the modern codenames applies:

  • ICU bumped to 76.1. On excalibur/daedalus (and trixie/bookworm) the ICU resolver targets _ICU_NEWER_VRN=76-1. PHP 8.1+ builds intl against any ICU and is rebuilt against 76 automatically. PHP below 8.1 is the catch: PHP 7.4 and 8.0 cannot build intl against ICU 76+ (only against ICU ≤ 73), so their intl must stay on an older ICU, pinned with _ICU_FORCE_VRN in /root/.barracuda.cnf. In practice 7.4 is the one that matters — it is the version still hosting legacy Drupal 7 sites that need intl. Where weekly auto-updates are enabled the SELFUPGRADE weekly run self-heals 7.4 intl after a system ICU bump; without auto-updates the pin is the operator's responsibility. The _ICU_FORCE_VRN / _ICU_NEWER_VRN variables are catalogued in barracuda.cnf reference.
  • resolvconf purged. No longer needed on these releases; BOA writes /etc/resolv.conf directly.
  • /root/.top-daedalus.cnf retired on the Excalibur hop. On either hop into Excalibur (_TRIXIE_TO_EXCALIBUR or _DAEDALUS_TO_EXCALIBUR) the old Daedalus marker is renamed to /root/.old-top-daedalus.cnf and a .top-excalibur.cnf marker is created.
  • Brief PHP downtime while the stack is rebuilt against the new OS.

Provider boot caveats

Some providers (notably Linode/Akamai) have unreliable system-driven reboots. The Lassie watchdog sometimes fails to remount the filesystem after a snapshot restore, and an in-VM shutdown -r now does not always wake the VM.

Symptom: SSH stops responding mid-chain while the vendor panel shows the VM "running" but boot hung. Recovery: vendor-panel Power Off → Power On (sometimes several attempts), or restore the Step 1 snapshot. This is the failure mode that makes a tested snapshot mandatory.

Post-chain PHP-version cleanup

The chain deactivates every installed-but-unused PHP version (it applies /root/.allow-php-multi-install-cleanup.cnf semantics automatically). Re-install what you need afterwards:

barracuda php-idle enable    # re-install previously-disabled versions
barracuda php-idle disable   # disable unused again later

The per-site PHP-version mechanics are in PHP-FPM performance.

Related