SpipCP
Backups

Append-only & immutability

The security story behind backups — two separate credentials (an add-only backup lane and a delete-capable prune lane), how rest-server enforces append-only, where provider object-lock fits, and the one gap self-hosted object stores still have.

The whole reason to take backups is the bad day. The worst bad day is when the thing that compromised a site also deletes its backups. SpipCP is built so that can't happen by accident or by an attacker holding a site's credentials — because the credential a backup uses cannot delete anything.

Two keys, two lanes

Every storage target has two separate credentials, and they reach the repository through two separate lanes:

LaneCredentialWhat it can do
Backup lanethe backup keyAdd new backup data. Never delete. Every site backup, the panel self-backup, and every restore (which only reads) ride this lane.
Prune lanethe prune keyDelete old snapshots. Used only by the retention pruner and the manual "delete backup" action.

A backup process literally never holds the delete-capable key. So a compromised site — which can at most reach the credential a backup runs with — can write a new backup, but cannot wipe the history.

The panel holds the repo keys, not the nodes

The restic repository password (which encrypts the backup contents) and the storage credentials are held by the panel, encrypted at rest. They're handed to a backup as a process/environment secret for one operation — never written into a command line (so they can't leak into ps or a log) and never stored on a node.

The rest-server append-only lane

On a self-hosted storage node, rest-server runs with --append-only. That makes the two lanes server-enforced, not just client-promised:

  • The backup user can PUT new data, but the server refuses every delete it asks for — even if the client tried to delete, the box says no.
  • The prune user reaches a separate, loopback-only lane on the box that can delete. It's only used by the panel's pruner, and it's not exposed to the network.

So even a backup client that has been fully taken over can't destroy a snapshot: the refusal happens on the server, on a box the compromised site has no other access to.

Provider object-lock

For an S3 bucket brought as storage on AWS S3 or Cloudflare R2, object-lock can additionally be enabled — the provider makes objects immutable for a retention window, so nothing, not even a delete-capable key, can remove them until the lock expires. That's the strongest immutability available: it survives even a compromised prune key.

The honest gap: self-hosted object stores

Why a self-hosted storage node runs rest-server, not Garage

Self-hosted S3 stand-ins — Garage, SeaweedFS, RustFS — cannot enforce append-only or object-lock today. With one of those, a client holding the bucket key can delete objects, and there's no server-side refusal to stop it. SpipCP doesn't paper over that: a self-hosted storage node runs rest-server (which can enforce append-only), and provider object-lock is only offered on AWS S3 / R2 (which can enforce it). Where immutability can't be guaranteed, the panel says so rather than implying a protection that isn't there.

The safety floor on top of all this

Even with all the above, the panel adds one more guard: it will never delete the last verified-restorable backup. A retention rule (or a manual delete) that would leave a site with no good backup is refused unless explicitly confirmed via "leave with no backup." Immutability stops an attacker; the safety floor stops an accidental deletion. See Backups → deletion.

On this page