Add daily encrypted borgmatic backup service

- /docker/backup: borgmatic container (daily 03:00 Berlin via BACKUP_CRON)
- Backs up /docker (ro) to local encrypted repo /var/backups/borg (repokey-blake2)
- Postgres prod+dev captured via pg_dumpall; live PG data/logs/build artifacts excluded
- Retention: keep_daily 7, keep_weekly 4, keep_monthly 6; runs prune/compact/create/check
- Secrets in backup/.env (gitignored, chmod 600)
This commit is contained in:
2026-05-31 22:29:46 +02:00
parent 02b4fe1fc0
commit e7a7cafa89
5 changed files with 163 additions and 0 deletions
+44
View File
@@ -49,3 +49,47 @@ After editing a function, `cd /docker/supabase && docker compose restart functio
- `supabase-edge-functions` reads `REDIS_URL` from `/docker/supabase/.env`.
- bandwidth-worker polls `http://frps:7500/api/proxy/http` every 60s; deltas go
to `public.usage_samples` and `public.tunnels.bytes_used` via PostgREST.
## Backups
Daily encrypted backups via **borgmatic** (`/docker/backup`).
| Service | Compose dir | Container | Schedule | Image |
|-----------|-----------------|-----------|---------------------|------------------------------------------------|
| borgmatic | /docker/backup | borgmatic | daily 03:00 (Berlin)| ghcr.io/borgmatic-collective/borgmatic:latest |
- **Source:** `/docker` (mounted read-only). **Repository:** `/var/backups/borg`
(local host disk for v1; remote planned later). **Encryption:** repokey-blake2.
- **Databases:** prod (`supabase-db`) + dev (`supabase-dev-db`) captured via
`pg_dumpall` (roles + all DBs), streamed into the archive. The container is
attached to `supabase_default` + `supabase-dev_default` to reach them.
- **Excluded:** live PG data dirs (`supabase/volumes/db/data`), logs,
`caddy/.../autosave.json`, `.remediation-backup`, `node_modules`, `.next`.
- **Retention:** keep_daily 7, keep_weekly 4, keep_monthly 6.
- **Schedule:** built-in cron via `BACKUP_CRON` env (`0 3 * * *`), running
`borgmatic --stats -v 0` (default action set: prune, compact, create, check).
- **Secrets:** `/docker/backup/.env` (chmod 600, gitignored) holds
`POSTGRES_PASSWORD_PROD`, `POSTGRES_PASSWORD_DEV`, `BORG_PASSPHRASE`.
**Store `BORG_PASSPHRASE` offsite — losing it makes the repo unrecoverable.**
### Operations
```sh
cd /docker/backup
docker compose up -d # start the scheduler
docker compose run --rm --entrypoint borgmatic borgmatic list # archives
docker compose run --rm --entrypoint borgmatic borgmatic create --stats # manual backup
docker compose run --rm --entrypoint borgmatic borgmatic check # verify integrity
```
Restore a database dump:
```sh
cd /docker/backup
ARCH=$(docker compose run --rm --entrypoint borgmatic borgmatic list --json \
| python3 -c "import sys,json;print(json.load(sys.stdin)[0][\"archives\"][-1][\"archive\"])")
docker compose run --rm -v /tmp/restore:/restore --workdir /restore \
--entrypoint borgmatic borgmatic extract --archive "$ARCH" \
--path "borgmatic/postgresql_databases/supabase-db:5432/all"
# then: psql -U postgres -f /tmp/restore/borgmatic/postgresql_databases/supabase-db:5432/all
```