BOA-5.88.855 — Kraken Edition
BOA-5.88.855 PRO/LTS is the Kraken Edition — 294 commits across seven repositories (boa 220, provision 24, hosting_tasks_extra 18, hosting 9, hosting_le 4, hostmaster 1, hosting_custom_settings 1), the largest release window since BOA-5.88.8. Everything in it ships in both PRO and LTS.
ACTION REQUIRED (self-hosted systems): kernel reboot and OpenSSL PHP rebuilds
A Linux kernel security update arrives with this release through the
automatic security-updates channel, and BOA never forces a reboot —
activating it is yours to schedule: run boa reboot at a quiet moment
(boxes with auto-reboot enabled restart themselves in their night
window). This release also ships the OpenSSL 3.5.8 LTS security
update, which rebuilds every bundled PHP version from 7.4 to 8.5 against
it — so running the barracuda and octopus upgrades soon matters more
than usual. Customers on hosted and remotely managed plans have all of
this handled for them by our team.
Why "Kraken"? The Certainty release made the platform prove things before acting; the Kraken guards what lives in its waters. A replication standby now holds a faithful copy that adds nothing of its own, your off-site backups open on your own workstation with your own keys, a destroyed database name keeps no residual access in any spelling at any scope, root never follows a path a tenant planted, and a wedged task queue heals itself. And after five releases of well-behaved C-words, 294 commits have earned a sea monster: the Kraken joins Barracuda, Octopus and Ægir in the bestiary.
Your backups, in your hands. The story starts on your own desk:
boa-restore, a small read-only tool published at
github.com/omega8cc/boa-restore,
opens the encrypted off-site backups BOA writes to your own bucket — on a
Mac, a Windows PC via WSL, or any Linux box — with no BOA server involved.
One downloaded file, one config template reusing the exact variable names
from the server-side credential files, then check, list and restore
with plain-language diagnostics; restores land in fresh timestamped
folders and the tool physically cannot write to your bucket. It was proven
against real server-written archives, full and incremental, and it turns
"we have backups" into "we have tested restores". The guide leads with it:
/using/backups/disaster-proof-restore.
On the server side — in the extended backup sub-system that ships on
hosted accounts and PRO-licensed servers — the gcs (Google Cloud
Storage) and ibm (IBM Cloud Object Storage) off-site targets work
again: Duplicity 3.x never shipped the per-vendor backends they relied
on, so every run failed before any transfer. Both now ride the proven S3-compatible route — GCS through its
XML interoperability API, IBM COS through its regional S3 endpoint — with
HMAC credentials. One consequence needs your hand: the credential
variable names changed, and an already-filled gcs.txt or ibm.txt is
deliberately not regenerated. Until you rewrite it with the variables its
README names (and mint HMAC keys at the provider), a gcs or ibm run stops
with a named error rather than handing Duplicity an empty key pair.
The panel's backup story is finished too: every backup row now records the mode the backend actually applied — the pre-Restore safety copy included — and exposes it to the Backups view for display and sorting. Each task resolves its backup mode exactly once, so a concurrent task or a dead task's leftover control file can never quietly downgrade the safety copy taken before a Delete or a Restore. And the default exclusion that keeps local Ægir backups out of the off-site chain finally fires — embedded quotes had made the pattern match nothing since it was written, so chains silently carried a duplicate copy of every local backup.
A standby you can finally trust. BOA's high-availability story gains
its missing properties: a passive mirror that provably adds nothing of
its own, and files that keep themselves current. The replica's database
runs super_read_only, held in its own MySQL include so it survives
restarts and reboots, refusing local writes from root down while
replication flows untouched — and standing mirrors convert themselves,
because the MySQL watchdog retrofits the hold by ordinary fleet
delivery. The web tier holds too: the shipped Nginx init script refuses
to start under the standby marker (closing the boot window no cron
enforcer can reach), a per-minute enforcer takes it back down, and a
dedicated firewall chain drops inbound 80/443 in both address families.
Tenant shell logins flip to nologin and are restored exactly at
promotion; FTPS and the whole backup chain stand down; and the
host-cache and privilege flushes the standby runs on itself no longer
reach the binary log — that per-minute remedy alone minted about 1440
errant transactions a day on every Percona 5.7 replica.
The file half is the new xmass autosync: arm a cadence once and the
live sync legs repeat unattended — minutes behind the continuously
replicating database — deferring quietly behind migrations and
upgrades, stopping loudly the moment the mirror is promoted, and never
restoring a standby marker on their own. Sync passes now propagate
source deletions on the data trees, so a mirror stops growing with
every nightly rotation — fenced four ways: deletions land only after a
successful transfer, a mass deletion is refused at a limit as a loud
failure, an empty source deletes nothing (an unmounted volume reads as
an empty directory), and the cutover legs delete nothing at all. A
duty-cycle guard keeps a long pass from walking the estate
continuously, a daily alarm names a cadence whose passes stopped
completing, and index segments are pruned only while the mirror's Solr
hold reads verifiably intact. At promotion, the cutover proves the
promoted web tier externally, HTTPS included, before DNS moves; an
abort before promotion restores the source's cron, backups and IDS by
itself; and xmass refuses a pair whose server Percona versions
mismatch down to the patch level, so a mirror built fresh from the
repo cannot strand a failback.
The audit dividend. This cycle audited every scheduled job on a BOA
box, and four of its findings were live on every box. A misplaced temp-path default made
the account manager run rm -f /*.txt against the filesystem root on
every pass. A Let's Encrypt "heal" tested an account field that stopped
existing years ago, so it periodically destroyed healthy ACME account keys
and forced re-registrations on sites that had nothing wrong — that
always-true arm is retired, and account directories are archived now,
never deleted. Backup
tools refuse an empty hostname instead of collapsing onto a shared bucket
name where two boxes could interleave and prune one chain. And a backup
overlapping the nightly swap reset no longer leaves the box swapless for a
day.
Migration source: a task, not a ticket. Pointing Drupal's migration
tooling at another site's database used to mean collecting credentials and
hand-assembling connection strings. It is now a control-panel task on
Drupal 8+ sites: pick another of your own sites, and its database appears
to the target site as the standard migrate connection. No new secret is written anywhere — the
connection reuses the target site's own credentials with only the database
name swapped — and the access granted is SELECT on exactly that one
database, issued only after the source site proves it can open that
database with the credentials it records for itself. Setting the source
back to None revokes; deleting either site tears the wiring down; a clone
never inherits the association. A nightly reconciliation sweep, running
inside the box-wide task-queue pause, reclaims any grant no live pairing
accounts for — and it never grants anything itself. The task is enabled on
every install and upgrade, so it is simply there.
A queue that heals itself. A task whose runner died — a reboot, a
signal, an upgrade swapping the live code trees underneath it — used to
sit at Processing forever, and one such corpse wedged an instance's whole
queue for hours. Two independent recoveries now exist: the dispatcher
stamps each runner's PID and reaps rows whose process is verifiably gone,
and the new task_guard watchdog does the same from outside the panel,
with no Drush bootstrap, so the queue heals even on a box whose Drush no
longer loads. Nothing is ever re-run — a crashed migrate or clone is
marked failed with a truthful log entry and left for a human. Hostmaster
upgrades stop minting these corpses in the first place: the queue is
drained synchronously before the code trees are swapped.
Root keeps its boundary. A hardening sweep closed a whole class of
root-versus-tenant defects: no root file operation follows a symlink
planted at a name BOA maintains. Control INIs are seeded atomically from a
root-only staging directory; robots.txt and llms.txt are fetched to a
temp file and moved into place; a dangling link in a shell account's home
no longer makes root create and hand over the file it points at; and the
same idiom was applied across the nightly, Solr maintenance, usage,
backup and migration tools. The install scratch root /opt/tmp is
root-owned and no longer world-writable — an operator script that wrote
there as a non-root user now needs the per-user state directory instead
— and install steps must positively stamp OK: a step that cannot signal
is failed, not passed.
Pre-rotation copies of database credentials are 0600 from birth, healed
where lax, and pruned to the newest three.
The database layer took the same oath. A site's grant now names its
database exactly — MySQL reads _ and % in a grant as wildcards, so
the old pattern also covered similarly named neighbours on the same box.
Destroying a database revokes every grant on it in the spelling the
server stored, down to table, column and routine scope; a superseded
database user is dropped once only bare USAGE remains; and destroying one
site never touches grants on databases it is not destroying. Where BOA
declines to act — grants it cannot read, or did not mint — the task log
names the account and database instead of going quiet.
Small fixes with large blast radii. On Debian 13 systems, glibc has
sent a POSIX -- separator into sh -c since version 2.38, and websh —
the restricted /bin/sh on hosted boxes — read it as the command itself:
every PHP exec(), shell_exec() and drush shell-out on such boxes was
denied silently, panel database layer included. Fixed at the argv intake.
Deleting a site now purges its Valkey/Redis cache namespace — on Drupal
and Backdrop alike — so a site recreated under the same name starts clean
instead of serving the deleted site's compiled routes from the shared
cache store. And renamed host-derived sites serve again: settings.php
kept the old hostname in its escaped spelling and answered HTTP 400,
while the rename's own closing queue imported duplicate site nodes — a
box rename now carries all seven per-site surfaces, refuses to finish
while any directory still holds the old name, and repairs boxes renamed
by an earlier release on the next run.
HTTPS that tells the truth. A Let's Encrypt run that loses the
issuance lock reports the abort and asks for a retry, instead of claiming
success and wiring symlinks at files that do not exist — which used to
leave the account vhost failing nginx -t and every later reload on the
box failing with it. Certificate symlinks are wired only once every file
nginx will load — certificate, chain and private key — is actually
readable; the cleanup sweep defers while another issuance holds the lock;
and the nightly renewal legs honour the dont-overwrite marker, so an
operator-installed custom certificate survives the night and platform
upgrades. Disabling Encryption clears the per-site LE control files, and
a same-name platform migrate re-enables Encryption with the site's own
stashed level and key. In the vhost templates, nosniff and
SAMEORIGIN are re-stated in every location that sets its own headers —
nginx cancels inherited headers there — so aggregated assets, image
derivatives, file downloads and Boost-cached HTML carry the same pair as
the rest of the site.
Whole-server moves grow refusals. A migration between boxes on
different BOA releases is refused outright — a target missing a
central-map nginx variable fails nginx -t box-wide, so the gate has no
override and names the fix instead. The migration tools run one
state-mutating verb at a time, owner-proven by liveness; cutover aborts
either restore the source or park resumably with the resume command
printed; pending delete tasks are purged before a move so an interrupted
delete can never travel and execute against freshly migrated production;
and xtrim — the staged shrink tool — now proves the target serves each
SITE, refusing a 200 that is byte-identical to the target's catch-all
answer for an impossible hostname. Search survives the crossing too:
prep-target measures which Solr versions the source really uses and
refuses a target that does not mirror them, the new solrtrim tool
retires unused Solr versions safely (archive first, deny before delete,
one-year index-write bar), and xmass restore-solr re-arms a rolled-back
source in one step. Underneath it all, fetched tools now revalidate
hourly and conditionally, stamp themselves with the source's publication
time, and re-fetch on byte drift — so a fix published mid-cycle reaches
the fleet within the hour, and a box that upgrades between tool waves
picks the current tools back up within minutes.
Classic Ægir estates, adopted. The aegir2boa toolset drilled its way
through three hard populations this cycle. Encrypted estates: stage 1
flips an apache_ssl estate to nginx_ssl for real, baselines every
HTTPS site with genuine SNI and hostname verification, and cutover is
refused when the target answers with its catch-all page instead of the
site; a new peer verb arranges reachability on both boxes — firewall
allow and ignore lists, temp-block clear, a dedicated migration key —
instead of a runbook asking for hand-edits. Ubuntu sources: vanilla Ægir
estates on 20.04 and 22.04 are first-class, with the era's MySQL 8.0,
PHP 7.4 and Apache layouts read rather than assumed. And Drupal 6: each
site's own install profile now travels through adoption (any custom
profile used to fail the import), and a reverted import removes the
vhosts it rendered so a retry cannot lose to them. On Percona 8.4
targets, BOA now advertises native authentication in the server
handshake, so legacy sites on the PHP 5.6 pool keep their database
connection on the web as well as the command line — a deliberately
8.x-only lane, since the 9.x series removes native authentication
outright. And a staged Percona series upgrade whose package phase dies
aborts loudly before any tuning, with every wait bounded and diagnostics
reading the log the server actually writes.
The catalogue, current again. Four distributions return to the
catalogue rebuilt from upstream on current cores: Varbase 10.1.2 on
Drupal 11.4 — the first working fresh Varbase install since July —
plus OpenFed 13.6.6, Opigno LMS 3.2.7 and Open Social 13.0.2
on the Drupal 10.6 line — with farmOS 4.0.5 and Thunder 8.4.1 refreshed
alongside, and Varbase building on the catalogue's current Drupal 11.4
core. The Drupal CMS platform now ships the migration
pipeline modules and a build-time pathauto correction, so it works as a
Drupal 7 upgrade target without per-site Composer surgery. A new
staticbuild catalogue audit HEAD-checks every catalogue entry's
tarball on the distro mirror, so a de-published tarball is caught before
a release instead of costing every box ninety seconds of silent retries
per codebase generation. Pure-FTPd joins the prebuilt package set — FTPS
installs in seconds instead of a compile — and hosted systems carry the
FTP and image-optimisation extras by default. Memory management learns
restraint: the Valkey cache ceiling is now a hit-rate control loop that
converges on measured demand instead of a ratchet that grew with every
grant it made, and memorytuner renders a per-box needs ledger — per
consumer, with growth slopes and a measured OS reserve — that observes
and names, but never applies.
Also in this release: the launchers no longer print a clean completion
line beside their own ALERT, so the documented done signal means what it
says; prebuilt package dependencies are pre-installed so a first install
stops scrolling dpkg errors, and a prebuilt package rebuilt by a
companion bump — the OpenSSL wave made this visible — is republished and
verified against the OpenSSL and ICU the box expects, so mirrors never
serve stale binaries; the mydumper/myloader pair is reconciled to
one coherent build on every pass, ending the mismatched-pair import
failures (#1935);
_INSTALL_MYQUICK_SRC is retired as an operator switch; a
Debian-to-Devuan cloud conversion removes cloud-init when classic
networking is provably self-sufficient, closing a snapshot restore that
could lock root out of a converted cloud VM; Google's
special-case crawler ranges (AdsBot, Mediapartners, the SERP favicon
fetcher) are whitelisted from Google's own list so a favicon fetch can
never be banned out of your search results (operators overriding
_NGINX_HARVEST_UA_EXEMPT must quote the value now that the default list
contains a space); and the complete technical
index is in the
CHANGELOG.
Component Versions
| Component | Version |
|---|---|
| Nginx | 1.31.4 |
| OpenSSL | 3.5.8 LTS (modern build) |
| Valkey | 9.1.1 |
| OpenSSH | 10.5p1 |
| PHP | 8.5.9, 8.4.24, 8.3.33 (8.4 default CLI/FPM), 8.2.33 available |
| Percona Server | 8.4 current, 8.0 transitional, 5.7 legacy |
| Composer | 2.10.2 |
| Drush 8 (classic) | 8.5.5 |
| Drupal 7 core (D7ES) | 7.105.2 |
| Apache Solr | 9.10.1 |
| Java | 21.0.12 (21 line), 17.0.20 (17 line), 11.0.32 (11 line) |
| Pure-FTPd | 1.0.54 (prebuilt package) |
| New Relic | 12.9.0.38 |
| Unbound | 1.26.0 |
| Backup stack | Python 3.14.6 + Duplicity 3.1.0 |
| Backdrop CMS | latest stable, resolved from the mirror at build time |
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: /operating/os-lifecycle/manual-boa-upgrade
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/