What has to be backed up
Three things, and they are not equally replaceable.
| What | Where | If you lose it |
|---|---|---|
SERVER_ENCRYPTION_KEY | .env.prod | The CA private key is unrecoverable, even with a perfect database backup. Every host must be re-bootstrapped. |
| The database | Postgres volume | You lose servers, policies, users, requests, and the audit log. |
| Session recordings | /data/recordings in the API container | You lose replay history. Often subject to a retention requirement. |
DANGER
A database backup without SERVER_ENCRYPTION_KEY is close to worthless — the CA private key and stored credentials in it are encrypted with that key. Back the key up separately, somewhere that is not the server it runs on, and confirm you can actually read it.
Backing up
The repository ships two scripts. Both write to ./backups/ and keep 14 days.
./scripts/backup-db.sh # pg_dump, gzipped
./scripts/backup-recordings.sh # tars the recordings volumeThey take the compose project name as an argument if yours is not shellius.
A reasonable cron:
15 2 * * * cd /opt/shellius && ./scripts/backup-db.sh >> /var/log/shellius-backup.log 2>&1
45 2 * * 0 cd /opt/shellius && ./scripts/backup-recordings.sh >> /var/log/shellius-backup.log 2>&1./backups/ lives next to your .env.prod, so it is on the same machine as the thing it is protecting. Ship it somewhere else — object storage, another host, anything — or it will not survive the failure you are backing up for.
Restoring the database
Stop the API first so nothing writes while you restore:
docker compose -f docker-compose.prod.yml stop backend
gunzip -c backups/db-2026-09-20_02-15-00.sql.gz \
| docker exec -i shellius-postgres-1 psql -U shellius -d shellius
docker compose -f docker-compose.prod.yml start backendRestoring into a database that already has data will conflict. Restore into an empty database — either a fresh volume or a dropped and recreated one. Be certain which you are pointing at.
Restoring recordings
gunzip -c backups/recordings-2026-09-20_02-45-00.tar.gz \
| docker exec -i shellius-backend-1 tar -C /data -xf -Prove the restore works
A backup you have never restored is a hypothesis. Once a quarter:
- Restore the latest dump into a scratch deployment with a copy of the real
SERVER_ENCRYPTION_KEY. - Sign in.
- Confirm the certificate authority public key matches production. This is the real test — it proves the key decrypts the CA.
- Confirm servers, policies, and audit history are present.
If step 3 fails, your key backup is wrong, and you would only have found out during an outage.
What is not in a backup
Certificates are short-lived and are not worth restoring; they will be reissued. Host-side state (/etc/ssh/shellius_ca.pub, the agent token) is not backed up by Shellius either — it is reproduced by re-bootstrapping the host.