Encrypted backups with ssv and age
ssv backup scans like ssv scan, then streams the files straight into age, which encrypts them. An unencrypted copy of the archive is never written to disk. If age isn't installed, ssv backup stops before scanning and prints the commands that install it on your server; see also how to install age.
The backup contains every secret on the server, so protect it, and especially its key, accordingly.
Encryption keys (recommended)
Key-based backups can run unattended, and the key needed to decrypt them never has to be on the server.
-
On your own computer, not the server, create a key pair. Keep the key file somewhere safe, such as a password manager or an encrypted drive:
age-keygen -o ssv-main.keyPublic key: age10088g4ulpmqv7mcxtdx5q83llg0yrcgzx84czwky8fxatlyrfpcqc9d7tp -
Create a second, recovery key the same way and store it offline, separately from the first. Backups can then be decrypted with either key, so losing one doesn't lose your backups.
-
On the server, put the two public keys (the
age1...lines) in a recipients file. Public keys can only encrypt, so this file is not secret:sudo install -d -m 755 /etc/ssv sudo tee /etc/ssv/recipients.txt <<'EOF' age10088g4ulpmqv7mcxtdx5q83llg0yrcgzx84czwky8fxatlyrfpcqc9d7tp age1dsxf4ajxyxy8p03gekagw73zmc9lq3mkx5cmsjwdtwq8wkhpre0s4j09sf EOF -
Make a backup:
sudo install -d -m 700 /var/backups/ssv sudo ssv backup --recipients-file /etc/ssv/recipients.txt --output /var/backups/ssv/web01-$(date +%Y%m%d).ageCreating encrypted backup containing 6 files... Encrypted backup created: /var/backups/ssv/web01-20261007.age Files archived: 6 No plaintext tar archive was written to disk.
Instead of a recipients file you can give keys directly with --recipient age1..., repeated for each key. SSH public keys (ssh-ed25519 ... or ssh-rsa ...) also work as recipients.
Passphrase instead of keys
sudo ssv backup --output web01.age
age asks for a passphrase on the terminal. If you leave it empty, age generates a strong passphrase and prints it; write it down. Passphrase mode needs someone at the keyboard, so it can't be used from cron.
How backups behave
-
Without
--output, the backup is written to the current directory asserversecretvault-YYYYMMDD-HHMMSS.age. -
The backup file is readable by its owner only (mode
0600). -
An existing file is never overwritten; choose a new
--outputname instead. -
If the backup is interrupted (Ctrl-C, or the process is stopped), the partial file is removed.
-
If a file changes, disappears or is replaced between the scan and the moment it is backed up, it is left out and reported, and the rest of the backup continues:
Skipped /home/bob/public_html/.env: file changed after scan
What is inside
The backup is an age-encrypted tar archive. Each file keeps its full original path under files/, along with its owner, group and permissions. manifest.json, the last entry, records when and where the backup was made, the details of each file (as in ssv scan --json), and a skipped list of any files that were left out and why.
-rw------- alice/alice 24 2026-10-07 21:26 files/home/alice/app/.env
-rw-r----- alice/www-data 33 2026-10-07 21:26 files/home/alice/public_html/wp-config.php
-rw-r--r-- alice/alice 33 2026-10-07 21:26 files/home/alice/public_html/wp-config.php.bak
-rw-r--r-- bob/bob 14 2026-10-07 21:26 files/home/bob/public_html/.env
-rw-r--r-- bob/bob 13 2026-10-07 21:26 files/home/bob/public_html/.env.example
-rw-rw---- www-data/www-data 17 2026-10-07 21:26 files/var/www/shop/app/etc/env.php
-rw------- 0/0 2956 2026-10-07 21:26 manifest.json
Restoring from a backup
Restoring needs only age and tar, not ssv. Do it on a machine you trust that has the private key. Avoid keeping decrypted secrets on disk longer than necessary.
-
List the contents:
age -d -i ssv-main.key web01-20261007.age | tar -tvf -For a passphrase backup, leave out
-i ssv-main.key;ageasks for the passphrase. This applies to every command below. -
Check the manifest, in particular its
skippedlist:age -d -i ssv-main.key web01-20261007.age | tar -xOf - manifest.json | less -
As root, extract into a private staging directory. Running
taras root restores each file's owner, group and permissions:sudo install -d -m 700 /root/ssv-restore age -d -i ssv-main.key web01-20261007.age | sudo tar -xpf - -C /root/ssv-restoretarmatches owners by user and group name, which is right when restoring to a rebuilt server where the IDs may differ. To restore the original numeric IDs instead, add--numeric-owner. -
Copy back only the files you need, keeping their ownership and permissions:
sudo cp -a /root/ssv-restore/files/home/alice/app/.env /home/alice/app/.env -
Delete the staging directory, which holds unencrypted secrets:
sudo rm -rf /root/ssv-restore
Last updated 2026-10-08 · for ssv 0.2.0