Backups on the static filesystem

A backup of a native-symlinked site can be large: the backup tar follows the files/private symlinks (dereferences the store), so the tarball holds the full file data. Those backups land in /data/disk/<account>/backups on the root partition — a disk-full risk for a big account whose files live on attached storage.

For such accounts the nightly per-account maintenance relocates backups and backup-exports onto the static filesystem and replaces them with symlinks:

/data/disk/<account>/backups         -> /data/disk/<account>/static/files/.backups
/data/disk/<account>/backup-exports  -> /data/disk/<account>/static/files/.backup-exports

The Aegir paths are unchanged — backup_path and aegir_backup_export_path keep working through the symlinks (the same nightly run re-asserts the export path to <account>/backup-exports in its hostmaster settings block). Both targets live under static/files, so they share one filesystem and the backup-download hardlinks between backups and backup-exports keep working (hardlinks cannot cross filesystems). The leading-dot names are skipped by the site/orphan scan, like static/files/.archived — they can never be mistaken for site stores. The nightly local purges glob through the symlinks unchanged (-mtime +_PURGE_BACKUPS on backups, -mtime +_PURGE_TMP on backup-exports).

When it acts

The relocation is gated on static/files resolving (symlinks followed) to a different device than the account root — a stat -c '%d' comparison. On a default single-filesystem box static/files sits on the root device, there is nowhere better to put backups, and the run is a deliberate no-op. It only acts once an account's static/files is on attached storage — typically after a migratefs relocation.

A backup directory that does not exist yet is left alone: Aegir creates it on first use and a later nightly run relocates it. Once both paths are symlinks the nightly pass just re-verifies the targets and creates a missing store directory — no lock, no queue pause (the steady-state fast path). A symlink pointing at an unexpected target is never touched; it is logged for operator review.

One-time migration safety

Moving existing backups is the only destructive-looking step, and it is built to never lose one:

  • Incremental, low-space. rsync --remove-source-files copies file by file and removes each source only after it is copied — peak extra space on the tight root filesystem is roughly one file, not a full second copy.
  • Fail-open. On any failure the real directory stays in place and no symlink is created; the directory is replaced only after it emptied cleanly. A non-empty leftover is logged and left for review. A backup is never deleted.
  • Ownership preserved. The source's owner:group is captured first and applied to the store directory and (with chown -h) to the symlink itself.
  • Serialised. One account migrates at a time, guarded by a real flock on /run/.boa_backups_relocate.flock — the kernel releases it if the process dies, so there is no stale-lock guessing.

Task-queue interlock

So that no backup task writes into a directory being moved, the migration holds the Aegir task queue with the dedicated stop file /run/boa_queue_stop.pid (its own PID; an existing hold is respected, never overwritten):

  • runner.sh honours it twice — the parent exits immediately, and each per-account child dispatch skips too, so a pause set after a runner started still holds every dispatch.
  • Any already-running task is drained first (bounded wait, ~60 s); if one is still active the relocation defers to the next night rather than move a backup mid-write, and the interlock is re-checked once more right before each move.
  • The mechanism is self-healing by design: the run removes the stop file only if it created it and still owns it (recorded PID verified), clear.sh purges a leaked one as soon as its owner PID is gone, and /run clears on reboot — so it cannot freeze the queue. The same generic stop file is used by the nightly symlink automation; the queue side is described on Task queue.

Verification

readlink /data/disk/<account>/backups
readlink /data/disk/<account>/backup-exports

On a relocated account both print the static/files/.backups / .backup-exports targets; on a single-filesystem box both remain real directories. The per-account nightly log records the outcome with backups-on-static: lines — relocated <dir> -> <target> (static filesystem) on success, move failed / not empty after move / could not symlink when a step was skipped fail-open (the data is then still in place, or safe in the store awaiting a manual relink).

Kill-switches

On by default where the filesystem gate applies; disable without a code change:

Control file Scope
/data/conf/disable_backups_on_static_fs.cnf box-wide — all accounts on this host
/data/disk/<account>/static/control/no_backups_on_static_fs.info one Octopus account

While present the nightly pass returns before doing anything — it stops future relocation but never moves already-relocated data back; undoing a relocation is a manual operation. The full control-file catalogue is on the Configuration leaf.

Known caveat

Pre-existing backupsbackup-exports hardlink pairs are de-linked by the one-time move — the two directories migrate in separate rsync runs (no -H), so old tarballs briefly cost double space, on the static filesystem (the target), not the tight root one. The duplication ages out with the normal purge sweeps — _PURGE_TMP clears the backup-exports copy, _PURGE_BACKUPS the backups copy. Backups taken after relocation hardlink normally, since both directories are then co-located on one filesystem.

Related pages

  • Overview & safety model — the symlink layout whose dereferenced backups this page is about.
  • Configuration — every control file and cnf variable of the symlinking subsystem.
  • Backups overview — per-account backup directories may be symlinks; what that means for off-site include/exclude sets.
  • Task queue — how the runner dispatches tasks and honours queue pauses.
  • migratefs storage relocation — how static/files ends up on a separate filesystem in the first place.