DocumentationChangelog
Administration

Backups

Two things hold state, one of them is your entire company, and a backup nobody has restored is a hypothesis. The shortest page here, and the one that matters most.

What to back up

The Postgres database
The book of record, the ledger, the CRM, the Brain, every register. Back this up like what it is.
The dev-session disk
Git checkouts and engine state. Treat as reproducible — they are clones — unless you keep long-running session state you care about.
The encryption key
Not a backup, an escrow. It lives in your password manager, and it is what makes a restored database usable rather than a pile of ciphertext.

A nightly dump

~/backup.sh
#!/bin/bash
set -euo pipefail
cd ~/control
out=~/backups/control-$(date -I).dump
docker compose exec -T db \
pg_dump -U talon -Fc talon_control > "$out"
find ~/backups -name 'control-*.dump' -mtime +30 -delete
terminal
mkdir -p ~/backups && chmod +x ~/backup.sh
( crontab -l 2>/dev/null; echo "15 3 * * * /home/<user>/backup.sh" ) | crontab -
Report the run into Control
Control has a backup-run register, and the compliance dashboard reads it for freshness. Post each run to /api/backups/report with a write-scoped talon_ctl_ token kept only on that box, and let a reporting failure be non-fatal — the dump already happened, and a failed report must not fail the job.

Get it off the box

A backup on the same disk as the database is not a backup. Add an upload step to any object store — the volume here costs pennies a month — and record that destination rather than the local path.

Restore drills

Do this one, rather than reading it. Restore yesterday's dump into a scratch database and count a table:

terminal
docker compose exec -T db createdb -U talon restore_test
docker compose exec -T db pg_restore -U talon -d restore_test \
< ~/backups/control-$(date -I).dump
docker compose exec -T db psql -U talon -d restore_test \
-c 'select count(*) from "Customer";'
docker compose exec -T db dropdb -U talon restore_test

Log the drill in Control so the freshness control has evidence a drill happened at all, not merely that dumps keep running. Quarterly is the floor.

The key is not in the backup

Escrow separately, and test that too
TALON_CONTROL_ENCRYPTION_KEY is not in the dump, and it is not derivable from it. A restore onto an instance with a different key gives you every customer, invoice and note intact — and not one working connection, because every stored credential is ciphertext under a key you no longer have. Keep the key where the backups are not, and prove you can still read it.