Native files symlinking
How BOA keeps each site's writable files and private directories in the account's static store, symlinked back into the platform, with a warn-not-fail safety model.
BOA keeps each site's writable files and private directories outside the
platform docroot, in the owning Octopus account's static store, and links them
back into the site:
sites/<url>/files -> /data/disk/<account>/static/files/<url>/files
sites/<url>/private -> /data/disk/<account>/static/files/<url>/private
Only a symlink lives in the platform, so:
- a site's uploads survive platform rebuilds and code redeploys untouched;
- every site's data has one per-account home under
static/files/; - because the store is a single directory tree, the whole store can be
relocated onto attached
/mntstorage with migratefs while the per-site links keep working through it.
Where the subsystem acts
The subsystem acts at three points:
- New-site install: Provision's post-install hook has the just-created real
files/privatemoved into the store and symlinked, before the first verify writes the vhost. - Clone and Migrate/rename: after the target verify, the new site is
re-homed into its own store with
--force-unshare, which breaks the inherited link into the source name's data even when a sharing control file exists — a fresh clone or renamed site never opted into the share. - The gated nightly batch: converts pre-existing plain-directory sites and
archives deleted-site orphan stores — opt-in everywhere except the
omega8.cc-hosted (
.aegir.cc) fleet, where it is seeded on by default.
Existing unconverted sites are deliberately not touched by a normal install or verify; only the nightly auto-fix or a manual run moves data at a time an operator chose.
Safety model
The safety model is uniform across all of it:
- Every path is warn-not-fail: low disk, a missing tool, or any non-zero
step logs a warning and the task still succeeds — a conversion falls back to
plain real directories, and a clone unshare that cannot complete leaves a
still-shared link flagged with an operator-actionable
[ALERT]for a manual re-run once space allows; never a dangling link, never an aborted install or clone. - Moves are crash-safe and rc-checked: a symlink is never created over a failed or partial move, and an interrupted run is self-healed on the next pass.
- Stale and orphaned stores are archived, never deleted — moved into
static/files/.archived/<stamp>/, with pruning left strictly to the operator. - Root-managed conversion: because the store is root-managed while Provision
tasks run unprivileged, the conversion always runs as root through a hardened
NOPASSWD sudo wrapper (
/usr/local/bin/fix-drupal-site-symlinks.sh) that fail-closed validates its arguments and can reach only the narrow single-site apply — never the global batch/live modes.
Scope is /data/disk/<account> Octopus accounts only; the master hostmaster
account keeps plain directories.
Kill-switches and file sharing
Two kill-switch tiers disable native symlinking without a code change:
- box-wide
/data/conf/disable_native_files_symlink.cnf; - per-account
/data/disk/<account>/static/control/no_native_files_symlink.info.
Deliberate cross-site file sharing remains possible via
static/control/share.files.<site>.info, honoured everywhere except cloning.
Cross-cutting
- The Clone and Migrate tasks whose logs now carry the
[native-symlink]success line (and, on low disk, an operator-actionable[ALERT]) are in Migration & cloning; relocating the account-levelstatic/filesstore itself onto attached storage is migratefs. - The nightly window the automation shares — cadence, heavy-task skips, and the other night workers — is in the monitor stack; the task-queue pause mechanism it holds is the task queue.
- The sudoers entry for the wrapper and the AppArmor
mrixexec edges added to every PHP profile are in Security & isolation (AppArmor). - The backup subsystem whose per-account
backupsdirectories the nightly relocation moves is Backups. - The
_AUTOSYMLINK_*/_ORPHAN_FILES_REPORTvariables are catalogued in the host control-file reference and the Reference appendix.
Native files symlinking — overview & safety model
The store layout and event model for native files symlinking, plus the privilege and account scope, the warn-not-fail safety properties, kill-switches and file sharing.
Files-symlink tools — autosymlink, sudo wrapper, symlinkinfo
The three executables behind the subsystem: the autosymlink worker and its modes, the hardened sudo wrapper, and the read-only symlinkinfo history query, with logs.
Nightly automation — updatesymlinks
The updatesymlinks scheduler around autosymlink: the auto-fix and orphan-report sub-modes, the nightly cron line, the task-queue pause and grace, and the heavy-task skips.
Files-symlinking configuration reference
The three barracuda.cnf variables that govern the nightly automation, how Barracuda persists them, the defaults by system class, and the full kill-switch control-file catalogue.
Orphan stores & the .archived archive
How a deleted site's leftover store is detected by the strict alias-and-vhost test, archived into a dated .archived directory rather than deleted, and pruned only by you.
Backups on the static filesystem
The nightly relocation of an account's backups and backup-exports onto its static filesystem, gated on a different-device test, with its no-op default and kill-switches.
Why a dry run is NOT CLEAN — the EXPLAINED section
Why one anomaly marks a whole dry run NOT CLEAN and blocks batch conversion, and how the read-only EXPLAINED section re-probes each finding with its diagnosis and fix.