0041. Every instance keeps a backup copy the control plane can't delete
Status: accepted, 2026-10-30. Refines 0014: backupsd keeps retention, except where
a destination is protected.
Context
backupsd ran retention (restic forget --prune) from the control plane with credentials that can delete, and the
instance wrote to one SFTP destination. Whoever got root on the control plane — an attacker, a mistake, a script —
could delete every snapshot, and the backups would be gone with the server they exist for. Encrypting the
repository doesn't help against deletion.
Decision
- Protection is a property of a destination, and it is proven. A destination is
vault (append-only,
a private repository per client), versioned (an S3 bucket keeping old versions for days, written with a key
that can't delete versions) or locked (an S3 bucket with Object Lock). SFTP accounts, local folders and
Telegram channels never are: whoever can write there can delete. backupsd proves protection at creation and
weekly by trying to delete a canary; a destination that lets it pages as critical.
- Retention of protected copies isn't the control plane's. backupsd never forgets on vaults. A vault prunes on
its own, by a time-based policy set on its server, so a flood of new snapshots can't push old ones
out; it can also keep no passwords and leave pruning to whoever holds the recovery kit. Versioned and locked
buckets keep what the control plane deletes for as long as their rules say.
- The vault is xvii-node.
xvii-node vault on any server serves restic's REST protocol append-only, paired
with backups by a string; the control plane's token there can add clients and read their state, and nothing
else.
- The posture asks for it. Every platform source should have a copy within its target in a protected
destination and in one off the control plane's server; the suggested plan writes the primary and the protected
destination directly, as two independent copies.
Consequences
- An instance needs a second server or a second provider; storage grows by what the protection window keeps.
- A vault that prunes holds its repositories' passwords: it belongs on a server none of the instance's people or
services can log in to.
- Point-in-time archives (ADR 0039) don't go to vaults; nightly dumps do.
- Reading a versioned bucket as it was before an attack takes rclone's view of the bucket at a time, which the
recovery kit prints.
- Design:
superpowers/specs/2026-10-30-backups-dr-design.md in this repository.