Native files symlinking
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/, and — because the store is a single directory tree —
the whole store can be relocated onto attached /mnt storage with
migratefs while the
per-site links keep working through it.
The subsystem acts at three points. New-site install: Provision's
post-install hook has the just-created real files/private moved 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.
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.
And 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.
Two kill-switch tiers disable native symlinking without a code change: box-wide
/data/conf/disable_native_files_symlink.cnf, or 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.
Pages in this topic
- Overview — the store layout, the event table (install, clone, migrate/rename, name reuse, nightly), the privilege model and account scope, the safety properties, kill-switches, and deliberate file sharing.
- Tools reference —
autosymlink(global DRY / report / live / batch /--batch-if-cleanmodes and the narrow single-site mode), thefix-drupal-site-symlinks.shsudo wrapper, the read-onlysymlinkinfohistory query, verify commands, logs, and deployment. - Nightly automation —
updatesymlinks --auto-fixand--orphan-report, the hourly-night cron line, the task-queue pause and its grace, the heavy-task skip and per-night stamp, and--debug. - Configuration —
_AUTOSYMLINK_NIGHTLY,_ORPHAN_FILES_REPORT,_AUTOSYMLINK_PAUSE_GRACE, how Barracuda persists them to/root/.barracuda.cnf, the defaults-by-system-class story, and the full control-file catalogue. - Orphans & archiving — the strict alias+vhost
orphan test, the
.archived/<UTC-stamp>/layout and why it lives understatic/files, reuse-time archiving, the accumulation alert and its threshold, and operator-only pruning. - Backups on the static filesystem — the nightly
relocation of
backups/backup-exportsonto an attached-storage account's static filesystem, the different-device gate, and its kill-switches.
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.