Scheduled Backups
Encrypted offsite backups with restic and Backblaze B2.
Scheduled Backups
ATHELOS backs up automatically to encrypted offsite storage. This page covers how the backup system works, how to configure it, and how to restore from a backup.
What gets backed up
- Postgres database — full dump, compressed
- MinIO data directory — all evidence files
- Environment files —
.env,apps/web/.env.local,docker/.env - Backup scripts and configs —
backups/directory - Caddyfile — reverse proxy config, if present
Everything else is reproducible from code and doesn't need to be backed up. The repo is already on GitHub.
What does NOT get backed up
node_modules.nextbuild artifacts- Docker image layers
- Logs
These are either reproducible or ephemeral.
The backup tool: restic
ATHELOS uses restic for backups. Restic is a modern backup tool designed for encrypted, deduplicated, snapshot-based backups.
Why restic:
- Encrypted by default — AES-256 and ChaCha20-Poly1305
- Deduplicated — identical data stored once, saving space
- Snapshot-based — each backup is a complete point-in-time snapshot
- Verifiable — every backup can be integrity-checked
- Portable — backups can be moved between storage backends
The storage backend: Backblaze B2
Backups go to Backblaze B2 — object storage that's cheap and reliable.
Why B2:
- Cost — about $0.005 per GB per month for storage
- Egress is free for restores
- S3-compatible API — works with restic natively
- Private buckets — no public URLs
For a typical ATHELOS install, the backup set is a few hundred megabytes. Total cost: a few cents per month.
Setup
1. Create a B2 account
Sign up at backblaze.com. The free tier includes 10 GB of storage — enough for most ATHELOS installs.
2. Create a bucket
In the B2 dashboard, create a new bucket:
- Name —
athelos-backupsor similar - Privacy — Private
- Encryption — enabled
- Object Lock — optional, adds protection against accidental deletion
3. Create an application key
In B2, go to Application Keys. Create a new key with:
- Name —
athelos-restic - Allow access to bucket — only the
athelos-backupsbucket - Type of access — Read and Write
Never use the master application key. Always scope the key to one bucket.
Note the keyID and applicationKey values.
4. Generate a restic password
Restic encrypts backups with a password you provide. Generate one:
openssl rand -base64 32Store this password in your password manager and on paper. Without it, backups cannot be decrypted. If you lose it, the backups are lost.
5. Configure the backup environment
Create backups/.env from the template:
cd /home/kali/soc-solo-os/backups
cp .env.example .env
chmod 600 .envFill in:
RESTIC_REPOSITORY=b2:athelos-backups
RESTIC_PASSWORD=<your restic password>
B2_ACCOUNT_ID=<keyID from step 3>
B2_ACCOUNT_KEY=<applicationKey from step 3>6. Test the backup manually
./backup.shYou should see restic initialize the repository and upload the first snapshot. Check the output for errors.
Verify the snapshot exists:
source .env
restic snapshotsAutomating with systemd
The backup should run daily without intervention. ATHELOS uses a systemd timer.
Install the units
sudo cp soc-backup.service /etc/systemd/system/
sudo cp soc-backup.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable soc-backup.timer
sudo systemctl start soc-backup.timerVerify
sudo systemctl status soc-backup.timer
systemctl list-timers | grep soc-backupThe timer runs at 03:00 every day, with a randomized delay of up to 15 minutes to spread load.
Logs
journalctl -u soc-backup.service -n 50Or follow live:
journalctl -u soc-backup.service -fRetention
Old snapshots are pruned automatically:
- 7 daily — last week
- 4 weekly — last month
- 12 monthly — last year
- 1 yearly — long-term retention
Total: 24 snapshots at any time.
The restore procedure
An untested backup is not a backup. Test the restore monthly.
List available snapshots
cd /home/kali/soc-solo-os/backups
source .env
restic snapshotsRestore the database
./restore.sh db <snapshot-id>This downloads the database dump from the snapshot and pipes it to
psql. The current database is replaced.
Warning: this overwrites live data. Only run against a test instance or after confirming you want to lose current data.
Restore evidence files
./restore.sh files <snapshot-id>This restores the MinIO data directory to its original location.
Restore a specific file
./restore.sh path <snapshot-id> /path/to/fileVerify integrity
restic checkThis reads every snapshot and confirms nothing is corrupted. Run it monthly.
Password management
The restic password is critical. If lost, backups are unrecoverable.
Keep it in:
- Your password manager
- A physical copy (paper, safe, or safety deposit box)
- Optionally: a sealed envelope given to someone you trust
Do not store it in git. Do not email it. Do not paste it into a chat.
Testing the restore
Once a month:
- Spin up a second machine or a Docker container with a fresh Postgres
- Restore the latest snapshot into it
- Verify the database loads without errors
- Verify a few evidence files are intact
- Tear it down
If the restore works, the backup is real. If it doesn't, you found the problem before you needed the backup.
Cost expectations
For a typical ATHELOS install:
- Storage — under 1 GB (deduplicated), about $0.005 per month
- Egress — free on B2
- API calls — well within free tier
Total: a few cents per month. Cheaper than any SaaS backup service.
What if B2 goes down
Restic can write to any backend. To switch to a different one (S3,
Wasabi, a local NAS, a second B2 bucket), update RESTIC_REPOSITORY in
backups/.env.
The backup history stays intact if you migrate the repository. See restic's documentation on repository migration.
Where to go next
- Dependency audit — keeping dependencies secure
- Notifications — alerts on backup failures
- Reference: environment variables — full env var list