BOA-5.88.844 — Certainty Edition
BOA-5.88.844 PRO/LTS is the Certainty Edition — 74 commits across three repositories (boa 57, provision 15, hosting 2), a combined feature and bugfix release. Everything in it ships in both PRO and LTS; no action is required beyond the ordinary upgrade.
Why "Certainty"? The Candour release made the platform tell the truth about what it does. This one makes it prove things before acting on them: a backup is not a backup until its dump verifies, an import does not run until the store proves whose data it holds, a migration reports nothing it cannot show evidence for, and nothing purges, drops or overwrites what a running install still depends on.
Every backup you ask for is now the restorable kind. The Candour release taught the panel's Backup form to open on the restorable mode; this release completes the contract everywhere else. Backups requested from the command line, through the API, from the sites-list bulk action or by a schedule now produce the same self-contained, restorable archive as a panel click. And the automatic safety copy taken before every Restore is itself a restorable backup now, database included, on Drupal and Backdrop alike — so the one archive you reach for in a bad moment can actually bring the site back. (The internal working copies that clone and migrate take for themselves keep their fast path by design.) The honest trade-off: the restorable shape is larger and slower than the old modeless fast copies, and the now-complete safety copy costs more disk per restore; naming a mode explicitly still gets the fast shape on purpose.
And a backup now has to show its work. A failed or truncated database
export now fails the backup instead of archiving nothing. A dump directory
without its completion marker is refused before import. A classic import
whose statements error out refuses to call itself a restore — on a current
Percona 8.4 server a wholly failing dump used to import "successfully" as
an empty database, and Restore would then drop the real one in its favour.
Truncated archives no longer extract their readable prefix and report
success — extraction now drives tar through explicit, status-checked
branches for every archive format the backup side can produce, which also
makes .tar.lz4 archives readable at all. The shared fast-import store
gained an identity guard: a dump it cannot prove belongs to this site — a
leftover from an earlier broken task, say — is refused loudly and left in
place rather than imported. Import failure messages carry the importer's
output instead of a credentialed command line. Databases with a stray
non-transactional table keep exporting under the new strict checks, and
the mydumper/myloader pair now heals its own version mismatches in both
directions on every system pass. Part of this wave started as an external
contribution — a dead failure check in the import path made live — which
the release gladly credits.
Root tooling took the same oath. The nightly classic database dumps
discard and name a dump that fails or loses its trailer, and the
compressor never deletes the uncompressed copy until the archive verifies.
The pre-rename dump in renameaegirhost — the only copy before a
destructive rewrite — refuses to proceed unless complete. The same
completeness checks reached the Ægir adoption export, the hostmaster
import, sqlmagic's dump rewriter and the nginx access-control revert,
which verifies its last-good archive before destroying live state.
Migrations prove their claims. In the whole-server migration suite, the
"exported" marker now means "this account's export is restorable", not "an
export was attempted": a failed or hollow export withholds the marker,
transfer and import refuse the account, and both xoct and xcopy end
incomplete runs with a non-zero exit an operator or harness can key on.
A loud --force exists for deliberate exceptions. After a move, pinned
PHP pools are rebuilt on the new host and verified live — closing the
quietest failure in the suite, where a site pinned to one PHP version could
run indefinitely on the account's default pool and look perfectly healthy.
A source box converted into a migration proxy now stays converted: its own
task queue can no longer regenerate the old vhosts minutes later and
silently resume serving a stale copy of the site. Routine octopus up-*
passes skip proxied accounts instead of rebuilding trees the migration
retired, and a subtle transfer exclusion no longer drops nested files/
directories living inside shipped codebases. And the migration docs now
spell out the one post-move check that matters: confirm cron runs on the
target, because a box whose cron never restarts silently stops receiving
fleet updates.
xtrim: retire a migration source without retiring its safety. New in
this release, xtrim shrinks a fully proxied migration source down to the
cheap relay it has become — in stages, from a dry plan through a
reversible quiesce (with a full restore on hand) to the one-way shrink and
finalize. It removes nothing until the migration is proven complete on the
live target, dumps and verifies every database — trailer included — and
re-proves the target between dump and drop; the one-way stage is marked
only at the moment something is actually dropped, and a fourteen-day
minimum age (_XTRIM_MIN_DAYS, floor seven) keeps it away from fresh
conversions.
High availability round-trips. Replication bring-up now parses multi-identity GTID sets whole — previously the set was silently truncated to its first identity, which meant an HA mirror could not be built from a box that had itself been migrated with the replication-based path. A box returning to master duty re-arms its binary log automatically (the master-readiness gate checks GTID and binlog together, restarting the database server when only one of them is armed), and a promotion cleans up after the role swap: source-role records, parked dispatchers, leftover proxy vhosts and travelled state markers are all cleared at cutover. The result, proven end to end on published code: failover and failback as a complete round trip with zero manual repairs.
A migration proxy is still a live server. The role marker that used to stand a finalized proxy's tooling down entirely has been narrowed to its actual meaning. A finalized proxy now runs its intrusion detection, security hardening, load profiling and tool self-updates, and re-registers its web server and cron at boot — while the database server and the site-serving stack stay intentionally down. PHP maintenance windows use a self-expiring run marker instead of borrowing the proxy marker, so a crashed maintenance run can no longer leave a production box silently muted.
Installs can no longer be sabotaged by housekeeping. BOA now knows,
box-wide, when an install or upgrade is in flight. The shared build staging
under /opt/tmp is never purged mid-install, launchers refuse to start a
second pass over a live one (and say why), and the fleet's own
housekeeping — nightly maintenance, database-cleanup tooling, load
emergency kills, Solr upkeep, the weekly update window — defers with a
bounded wait or a stated skip instead of pulling the floor from under a
running install. Aborted installs stop purging state they do not own, and
a half-extracted build tree heals itself by re-fetch. On top of that, a
fresh install now verifies that the client control-panel account it
advertises really exists, retries through a full bootstrap if not, and
alerts loudly if it still cannot — and the tool-update guard only defers
to processes actually executing a tool, so an open editor or a checksum
no longer silently pins a tool at an old version.
The panel trap is closed. A site name pasted with a trailing slash —
the natural shape of a copied URL — could previously be stored verbatim,
and on instances with subdirectory support enabled it built a site that
redirected to itself forever, gaining a slash per hop. The domain is now
cleaned at the door and a slash with nothing after it is never treated as
a subdirectory site, while genuine subdirectory sites (example.com/shop)
behave exactly as before. The guard is forward-only: a site that already
redirects to itself needs its stored alias and redirection rows cleaned
once before a Verify will rebuild it correctly.
A quieter, sharper edge. A new per-site ceiling bounds how many
anonymous page renders may be in flight at once on a single vhost —
visitors with a session are exempt by construction — which is the control
that bounds scraping campaigns spread across hundreds of addresses at one
browser-like request each, too thin for any per-IP alarm. The default
(100 concurrent anonymous renders per site) sits far above the busiest
legitimate peak measured across every tenant of a production box over a
full day (13–57) and well below an observed flood (417); it is tunable per
instance, and wants tuning on instances whose PHP worker pool saturates
well below a hundred concurrent renders. And the shared probe maps gained
one entry — credentials.json requests are dropped before PHP — while
three trialled candidates were deliberately withdrawn after review proved
each could be a real route on some hosted application: at a shared edge
the bar is "impossible on any conceivable tenant", because a false
positive there breaks legitimate traffic fleet-wide.
Also in this release: Drupal 7 core 7.105.2, BOA's own Drupal 7
Extended Support release — the sticky "4 byte UTF-8 for mysql is activated,
but not supported" warning now self-heals on the next database update, and
form validation errors keep custom field markup intact; Classic Drush
8.5.5 (vendor dependency refresh); Unbound 1.26.0, installed from
the prebuilt package set on modern systems; the long-dead mydropwizard module
force-disabled on Drupal 6 and 7 sites (its vendor service closed in 2022,
so its synchronous update calls can never succeed — nothing is deleted from
disk); DXPR Marketing and OpenLucius retired from the distro catalogue as
both are formally unmaintained upstream — this stops new platform
builds only, existing platforms and sites are untouched; and a truth pass
over the module-policy reference so the documented force-disabled list
matches the code exactly. The complete technical index is in the
CHANGELOG.
Component Versions
| Component | Version |
|---|---|
| Nginx | 1.31.3 |
| Valkey | 9.1.1 |
| OpenSSH | 10.4p1 |
| PHP | 8.5.9, 8.4.24, 8.3.33 (8.4 default CLI/FPM), 8.2.33 available |
| Composer | 2.10.2 |
| Drush 8 (classic) | 8.5.5 |
| Drupal 7 core (D7ES) | 7.105.2 |
| New Relic | 12.9.0.38 |
| Unbound | 1.26.0 |
| Backup stack | Python 3.14.6 + Duplicity 3.1.0 |
| Backdrop CMS | 1.34.3 |
Upgrade Instructions
Run inside a screen session as root:
screen
wget -qO- https://files.boa.io/BOA.sh.txt | bash
barracuda up-lts
octopus up-lts all force
boa reboot
Silent, logged variant (emailed on completion — useful for cron):
screen
wget -qO- https://files.boa.io/BOA.sh.txt | bash
barracuda up-lts log
octopus up-lts all force log
Full upgrade documentation: Manual BOA upgrade reference
Links
- Documentation: https://docs.boa.io
- News & announcements: https://omega8.cc/news
- Full changelog: https://github.com/omega8cc/boa/blob/5.x-dev/CHANGELOG.txt
- Commit history: https://github.com/omega8cc/boa/commits/5.x-dev/