ATHELOS
Automation

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
  • .next build 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-backups or 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-backups bucket
  • 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 32

Store 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 .env

Fill 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.sh

You should see restic initialize the repository and upload the first snapshot. Check the output for errors.

Verify the snapshot exists:

source .env
restic snapshots

Automating 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.timer

Verify

sudo systemctl status soc-backup.timer
systemctl list-timers | grep soc-backup

The 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 50

Or follow live:

journalctl -u soc-backup.service -f

Retention

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 snapshots

Restore 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/file

Verify integrity

restic check

This 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:

  1. Spin up a second machine or a Docker container with a fresh Postgres
  2. Restore the latest snapshot into it
  3. Verify the database loads without errors
  4. Verify a few evidence files are intact
  5. 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