Architecture overview & BOA fork model
A BOA host runs an omega8cc fork of the Ægir hosting stack on Devuan, Nginx-only, Percona-only, with a Master/Satellite multi-instance layout that upstream Ægir does not have.
This page fixes the mental model in place — what the layers are, where they live on disk, and exactly where BOA's fork diverges from upstream — so the rest of this section can stay concrete.
Layered view
┌────────────────────────────────────────────────────────────────┐
│ Operator (root) Tenant (o1, o2, … via o1.ftp lshell)│
│ barracuda / boa / Aegir UI (Satellite frontend) │
│ octopus CLI Restricted SFTP (o1.ftp) │
├────────────────────────────────────────────────────────────────┤
│ Aegir Master (Barracuda) │
│ /var/aegir/ aegir/distro/NNN (one frontend per host) │
│ central Nginx config + master/db server nodes │
├────────────────────────────────────────────────────────────────┤
│ Aegir Satellite (Octopus) Aegir Satellite … │
│ /data/disk/o1/ /data/disk/o2/ │
│ aegir/distro/NNN aegir/distro/NNN │
│ platforms/ static/ platforms/ static/ │
│ sites under each platform │
├────────────────────────────────────────────────────────────────┤
│ Provision (Drush backend) .drush/sys/provision │
│ hostmaster-install / provision-verify / -install / │
│ -migrate / -backup / -clone │
├────────────────────────────────────────────────────────────────┤
│ Services (host-side, managed by Barracuda) │
│ Nginx · PHP-FPM (multi-version) · Percona MySQL · │
│ Redis/Valkey · Solr (opt.) · CSF · AppArmor · Postfix │
├────────────────────────────────────────────────────────────────┤
│ OS: Devuan (no systemd) │
└────────────────────────────────────────────────────────────────┘
Two halves of Ægir: front-end and back-end
Hostmaster (front-end) is a Drupal 7 install profile (the omega8cc fork of upstream Ægir Hostmaster). Operators and tenants drive it as a web UI. Every UI action — creating a site, migrating a platform, scheduling a backup — generates a task node.
Provision (back-end) is a Drush extension that turns those task nodes into server-side actions:
- creating databases
- writing Nginx vhosts
- running
drush site-install - taking dumps
- copying files
Provision is
installed under .drush/sys/provision — /var/aegir/.drush/sys/provision
on the Master and /data/disk/<user>/.drush/sys/provision for each
Octopus instance.
BOA actively removes the bare upstream
.drush/provision path on both Master and every Octopus user
(master.sh.inc and satellite.sh.inc rm -rf .../.drush/{provision,drush_make}),
so the legacy .drush/provision location never persists.
Hosting (Drupal modules) is the suite of sub-modules that provide the Drupal node types (site, platform, server, client, task, alias, package, …) and the admin UI for them. The entity model is in Entity & service model; the task plumbing is in Task queue engine.
Master + Satellite
The Master/Satellite split is a BOA-specific layering upstream Ægir does not have. Both halves are full Ægir frontends; they differ in who owns them and what they host.
| Layer | Owner | Lives at | Purpose |
|---|---|---|---|
| Master | aegir system user, run by Barracuda |
/var/aegir/ |
One per host. Holds the central Nginx vhost set + the master/db server nodes that Satellites attach to. Not used to host tenant sites. |
| Satellite | o1, o2, … system users, run by Octopus |
/data/disk/o1/, /data/disk/o2/, … |
One per tenant. Hosts the tenant's Drupal sites; has its own Ægir UI, its own Drush, its own platforms, its own DB user namespace. |
A fresh BOA install creates one Master plus one Satellite (o1). More
Satellites are added with boa in-octopus my@email o2 lts. The full
multi-instance model — instance roots, the o1 instance-owner vs the
o1.ftp lshell account, and the isolation boundary — is detailed in
Multi-Octopus model.
File-system layout
The canonical paths an operator works with. The Master's instance root is
/var/aegir; an Octopus instance's root is /data/disk/<user>
(_ROOT="/data/disk/${_USER}", set in both OCTOPUS.sh.txt and
satellite.sh.inc). The Hostmaster codebase for either root lives under
<root>/aegir/distro/NNN, where NNN is a zero-padded numeric counter
(_nextnum), not an upstream-style hostmaster-7.x-3.x directory.
| Path | What lives here |
|---|---|
/var/aegir/ |
Master Ægir frontend root |
/var/aegir/aegir/distro/NNN/ |
Master Hostmaster Drupal codebase (numeric counter, e.g. 001) |
/var/aegir/config/server_master/nginx/ |
Generated master Nginx vhost set (vhost.d/, post.d/) |
/var/aegir/.drush/ |
Master Drush aliases — master alias is hm.alias.drushrc.php; server_master.alias.drushrc.php / server_localhost.alias.drushrc.php are the server contexts |
/var/aegir/.drush/sys/provision/ |
Master Provision backend |
/data/disk/o1/ |
Octopus instance o1 root (one of N) |
/data/disk/o1/aegir/distro/NNN/ |
Satellite Hostmaster codebase (hostmaster.alias.drushrc.php points here) |
/data/disk/o1/static/ |
Per-instance control / static tree — .cnf overrides, platform list, fpm.info |
/data/disk/o1/platforms/ |
Drupal platforms (codebases) for this instance |
/data/disk/o1/.drush/ |
Per-instance Drush aliases + .drush/sys/provision |
/home/o1.ftp/ |
Separate lshell SFTP home for the o1.ftp sub-user (static/ symlinks back to the instance root) |
/root/.barracuda.cnf |
Host-level control file (reference) |
/root/.${USER}.octopus.cnf |
Per-Octopus control file, e.g. /root/.o1.octopus.cnf |
/opt/etc/fpm/ |
Common FPM pool config (fpm-pool-common.conf, -legacy, -modern); per-version pools live under /opt/php<v>/etc/pool.d/ |
/var/log/boa/ |
BOA operational logs (install, upgrade, load incidents, monitor checks) |
The o1 instance owner owns /data/disk/o1/; the lshell-restricted SFTP
account is the separate o1.ftp user homed at /home/o1.ftp/ (there is a
matching o1.web web-runtime user). Do not conflate the instance owner
with the .ftp shell account — they are distinct identities with
distinct homes.
What runs continuously after install
| Cadence | Script | Purpose |
|---|---|---|
| every minute (self-loops ×10, ~5 s apart) | aegir/tools/system/second.sh |
Own cron entry (not launched from minute.sh): load sampling + auto-pause + the hackcheck/hackftp/escapecheck scanners and process guards |
| every minute (self-loops, box-class cadence) | aegir/tools/system/minute.sh |
Own cron entry: fans out the per-service auto-healing watchdogs (nginx, php, mysql, redis/valkey, unbound, java, …) in _ITER passes |
daily (15 4) |
aegir/tools/system/owl.sh |
Nightly maintenance orchestrator (installed as /var/xdrago/owl.sh): log rotation, control-file conversion, night/ workers |
| every minute (niced + ioniced) | aegir/tools/system/runner.sh |
Ægir task-queue runner → hosting-dispatch |
| per service | aegir/tools/system/monitor/check/*.sh (27 check scripts on disk; ~25 launched) |
nginx, mysql, php, redis/valkey, unbound, java, system, hackcheck, escapecheck, … |
second.sh and minute.sh are each their own per-minute cron entry
(neither is launched from the other); each self-loops with sleep between
passes to cover the whole minute at roughly 5-second granularity, so the
effective cadence is ~5 s, not literal one-second. second.sh loops a
fixed 10 passes × 5 s. minute.sh fans out the per-service auto-healing
watchdogs in _ITER passes spaced _SLEEP seconds apart, box-class
dependent (NORMAL = 9 × 5 s; CI = 1 × 5 s; SLOW = 3 × 18 s; overridable via
_MONITOR_FANOUT_ITER / _MONITOR_FANOUT_SLEEP).
The nightly owl.sh is the former
daily.sh, reworked into an orchestrator that runs per-account, per-site,
and global workers under aegir/tools/system/night/ (shared library
night.inc.sh; workers 10-account.sh, 20-sites.sh,
90-global-post.sh); log archiving/rotation and the INI control-file
conversion remain, while the old daily Drupalgeddon hacked-core check is
retired post-5.10.3 — its control files /root/.force.drupalgeddon.cnf
and static/control/drupalgeddon.info are auto-purged fleet-wide by BOA
self-update, and the drush extension remains a manual user-space tool.
The Ægir task queue is processed from cron by runner.sh — there is no
resident queue daemon (see Task queue engine). The
monitor stack is documented in Monitoring; the
full nightly run is covered in
Nightly owl.
Proxy-node role
A host can be declared a proxy node rather than a hosting node by
creating /root/.proxy.cnf. It is a presence marker — nothing reads its
contents — and since the 2026-08-09 narrowing it stands down only the two
cadence rows a proxy has no use for: the nightly orchestrator and the task
queue. Twelve BOA tools exit 0 the moment they see it: the task-queue
runner (runner.sh), the nightly orchestrator (owl.sh), usage.sh,
manage_solr_config.sh, move_sql.sh, checksql.sh, purge_binlogs.sh,
the four database jobs (mysql_backup.sh, mysql_cleanup.sh,
mysql_repair.sh, mysql_cluster_backup.sh), and mycnfup — all of them
work on local sites or the local database, which a proxy does not have,
and the database gates double as the guarantee that nothing ever restarts
the MySQL a finalize intentionally stopped.
Three build-side paths honour it negatively: a barracuda run skips the
Percona system-table check and both the start and the reload of
Valkey/Redis together with PHP-FPM. Nginx itself is exempt — it is
registered for boot (update-rc.d nginx defaults, alongside cron) and
started or restarted unconditionally, so a rebooted proxy comes back
serving.
What it does not stand down is everything a live, internet-facing
relay still needs: minute.sh and the per-service watchdogs it fans out,
second.sh with its brute-force/escape scanners and its own guard
fan-out, the whole */5 clear.sh channel (tool self-updates, mirror CSF
allows, autoupboa), the daily graceful.sh hygiene (including the
rsyslog watchdog the scanners read through), the manage_ltd_users.sh
host hardening, and loadreport --log — so a proxy node auto-heals,
defends and updates itself like any other box.
The file is never made immutable, and neither hosted normalisation pass
creates or erases it — unlike the tier markers, it is not fleet-managed
state.
A second, unrelated role marker works the same way: /root/.standby.cnf
declares the box a passive replication standby, gating individual jobs
rather than stopping cron — its full lifecycle and the exact stand-down
roster are on
Failover and recovery scenarios.
Install & upgrade flow (high level)
A fresh install from a vanilla Devuan/Debian VPS chains, from one operator command:
autoinit— on a Debian base, removes systemd and migrates to the matching Devuan release. The target is version-aware, not a single universal release:trixie → excalibur,bookworm → daedalus,chimaera → daedalus,bullseye → chimaera,buster → beowulf. Skipped if already on the current Devuan. Logs to/root/.autoinit.logand/root/.autoinit-verbose.log.barracuda install/upgrade— installs the host stack (Nginx, Percona, PHP-FPM, Redis/Valkey, CSF, AppArmor, …) and builds the Master Ægir frontend.octopus install/upgrade— creates the first Octopus instance (o1) with its own Satellite frontend and enables Let's Encrypt.
Upgrades thereafter run via SKYNET (tags on 5.x-pro / 5.x-lts
trigger automatic self-upgrade across enrolled hosts) or manually with
barracuda up-lts / up-pro (the only accepted upgrade verbs are
up-dev / up-pro / up-lts). The Master Hostmaster move during upgrade
is handled by AegirUpgrade.sh.txt, which runs a fixed five-function
pipeline (_hostmaster_mv_up, _hostmaster_dr_up, _hostmaster_go_up,
_hostmaster_dr_tt, _hostmaster_mi_up) inside a settings.php-presence
guard — the actual drush hostmaster-migrate runs in _hostmaster_mi_up.
Where this diverges from upstream Ægir
| Concern | Upstream Ægir | BOA |
|---|---|---|
| Web server | Apache (default) or Nginx | Nginx exclusively |
| OS | Debian / Ubuntu | Devuan only (Debian accepted only as a migration-in base) |
| Database | MySQL / MariaDB / Percona | Percona MySQL only (5.7 / 8.0 / 8.4) |
| Install | apt install aegir3-* |
barracuda / octopus / boa CLI |
| Multi-tenancy | Single-instance per host; multi-server via remote nodes | Master + N Satellites per host via the Octopus model |
| Hostmaster path | hostmaster-7.x-3.x/ |
<root>/aegir/distro/NNN (numeric counter) |
| Provision path | .drush/provision/ |
.drush/sys/provision/ (bare path actively removed) |
| Fork repos | aegir-project/* (drupal.org + GitLab) |
omega8cc/* on GitHub |
| SSL | manual / contrib | hosting_le + dehydrated, auto-renewed daily |
| Release cadence | drupal.org release flow | continuous, SKYNET-driven |
The omega8cc fork is authoritative for BOA behaviour: there is no meaningful upstream to rebase from, and any upstream doc that contradicts the table above is wrong on a BOA host.
Related
- Entity & service model — server / service / site / platform / client node types and the corrected permissions matrix.
- Task queue engine — the cron-driven dispatch chain.
- Multi-Octopus model — the multi-instance layout and isolation boundary.
- Control files & INI —
.barracuda.cnf/.octopus.cnfand the per-instance control tree. - Reference appendix — the consolidated variable and command indexes.