A Sable backup is one sealed file that carries everything a node needs to be rebuilt from nothing: its configuration, its DNS data, its people, and its keys. Restoring it onto a machine that has never run Sable produces the same deployment, signing the same zones with the same DNSSEC keys and talking to the same integrations.
| Section | Contents |
|---|---|
configuration |
sable.toml exactly as it was written, comments included |
zones |
Every zone, its records, and its per-zone DNSSEC and transfer settings |
authorization |
Users with their password hashes, roles and grants, and API token hashes |
secrets |
The encrypted secret vault and the key file that opens it: DNSSEC private keys, TSIG shared secrets, UniFi credentials, and ACME DNS provider credentials |
trust_anchors |
Persisted RFC 5011 trust points and their anchors |
certificates |
Manual certificate and private key, plus the whole ACME storage directory including the account key |
cluster |
Cluster manifest, node trust anchor, enrollment state, and state snapshots |
Query logs, query statistics, browser sessions, and the persisted DNS cache stay behind. They are operational data rather than the definition of the deployment, they are unbounded, and a restored node rebuilds them on its own. Export query logs separately from Logs if you need them.
Every backup is encrypted with a passphrase you choose. This is not optional: the archive contains the secret vault key, and anyone holding an unsealed copy holds every DNSSEC private key and integration credential on the node.
The file is sealed with AES-256-GCM under a key derived by Argon2id. There is no recovery path. A lost passphrase is a lost backup, so store it wherever you already keep credentials, not next to the archive.
Settings → Backup has both halves.
Downloading asks for a passphrase twice, builds the archive, and hands back a single-use link. The link expires after five minutes and works exactly once, so a backup never sits in browser history or a proxy cache waiting to be fetched again.
The archive is held in memory and never written to the node's disk, so the staged link survives a page reload but not a restart of Sable. Rebuilding one takes a moment; the trade is that a file holding every private key on the node is never left lying in the data directory.
Both operations show their real progress: each stage named in the bar is the work actually under way, and the count is the stages already finished rather than a timer pretending to be one. Sealing and opening an archive are their own stages because Argon2id makes them the slowest single step, which is why the bar pauses there. A restore also measures its upload in the browser, since that leg is the one part of the operation the server cannot see.
One operation runs at a time. Starting a second while one is in flight is refused rather than queued, because a backup and a restore would otherwise contend for the same files.
Choosing a file identifies it before anything happens: the console reads the archive's unencrypted envelope header in the browser and reports which host it came from, when it was taken, and which Sable release wrote it. A file that is not a backup is called out at that point rather than after an upload.
Restoring takes the file and its passphrase. It replaces zones, users, roles, API tokens, secrets, and trust anchors, and writes the configuration and key material back into place. Sable keeps serving the state it already had until it restarts, and the panel offers that restart when the restore finishes.
Keep this node's configuration restores the data but leaves the local
sable.toml alone. Use it when the target node's listeners, storage, and paths
are already correct and only its contents are stale.
Both halves have their own permissions. backup.create allows a download and
backup.restore allows a restore; neither is implied by settings.write,
because a backup carries credential material that a settings editor has no
business walking off with. The built-in Administrator and API
Administrator roles hold both. No other built-in role does.
The CLI works against the configuration file rather than a running server, so it is the right tool for a node that is stopped, broken, or brand new.
sable backup create --config /etc/sable/sable.toml --out /srv/backups/ns1.sablebackupsable backup inspect /srv/backups/ns1.sablebackupsable backup restore --config /etc/sable/sable.toml /srv/backups/ns1.sablebackupThe passphrase is read from --passphrase-file, then the
SABLE_BACKUP_PASSPHRASE environment variable, and finally from the terminal.
It is never taken from a command-line argument, where every process on the host
could read it.
| Flag | Effect |
|---|---|
--out file |
Where to write the archive (default sable-backup-<host>-<timestamp>.sablebackup) |
--passphrase-file path |
Read the passphrase from a file instead of prompting |
--section name |
Limit the capture or the restore to one section (repeatable) |
--keep-config |
Restore only: leave the local configuration in place |
--database-driver name |
Restore only: override the backed-up database driver |
--database-dsn dsn |
Restore only: override the backed-up database DSN |
sable backup inspect reads only the unencrypted envelope header, so it can
report when a backup was taken, from which host, and by which Sable release
without the passphrase. Everything else needs it.
-
Install Sable on the new host with
sable install, then stop the service. A running Sable holds the configuration watcher and its own view of the zones, so restoring underneath it leaves the two disagreeing until a restart.sudo systemctl stop sable
-
Restore the archive. If the new host stores its database somewhere else, say so; without the override the restored configuration names a database this host cannot reach.
sudo sable backup restore --config /etc/sable/sable.toml /srv/backups/ns1.sablebackup
-
Start the service and check that zones answer and the console signs in with the restored accounts.
sudo systemctl start sable
Restore never discards the configuration it displaces. The file that was there
is kept as sable.toml.pre-restore next to the restored one.
The cluster section carries this node's membership: its manifest, its trust anchor, and the state snapshot it last agreed on.
Restore the primary first. Its zones, policy, authorization, and runtime configuration are the state the cluster replicates, so a restored primary brings the rest back into line on their next synchronization.
Restoring onto a replica is rarely what you want. A replica applies whatever the primary publishes, so a restore there is overwritten on the next sync. The console disables the restore button on a replica for that reason. To rebuild a replica, restore it and then re-enrol it against the primary, or simply enrol a fresh node.
If you are restoring a single node out of a cluster that no longer exists, restore it and then delete the cluster from Cluster → Delete Cluster, which returns it to standalone operation.
sable backup create is a normal command and expects nothing but read access
to the configuration and the database, so a timer is enough:
SABLE_BACKUP_PASSPHRASE=$(cat /etc/sable/backup.pass) \
sable backup create --config /etc/sable/sable.toml --out /srv/backups/sable-$(date +%F).sablebackupKeep the passphrase file readable only by the user the timer runs as, and keep it somewhere the backups themselves are not. A backup and its passphrase in the same place is a backup with no passphrase at all.