Skip to content

Powered by Grav

BOA-5.88.844 — Certainty Edition

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:

SH
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):

SH
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

© 2026 BOA Documentation. All rights reserved.