Skip to content

Powered by Grav

BOA-5.88.855 — Kraken Edition

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:

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: /operating/os-lifecycle/manual-boa-upgrade

© 2026 BOA Documentation. All rights reserved.