PR 2: backup DB hooks for postgres, mariadb, mongodb, couchdb, sqlite
Created by: jedmund
Summary
Second PR in the backup series. PR 1 set up borgmatic running file-level snapshots; this one adds database consistency. Without it, restoring a snapshot of an actively-written DB recovers whatever crash-recoverable state happened to be on disk at 02:00, which is good enough for Postgres but not safe to rely on for SQLite or anything mid-transaction.
What gets backed up
Native borgmatic hooks (streamed dump, no temp files)
| Engine | Count | Databases |
|---|---|---|
| PostgreSQL | 9 | Immich, Mastodon, Synapse, MAS, n8n, Miniflux, Forgejo, Blinko, Draftboard |
| MariaDB | 1 | RomM (dumped as root) |
| MongoDB | 1 | Komodo admin DB |
Custom before_backup scripts (write to /var/backup/dumps/, then borgmatic snapshots that path)
-
dump-couchdb.sh: CouchDB onobsidian_livesync. Pulls_all_docs?include_docs=true&attachments=trueper non-system database to JSON. -
dump-sqlite.sh: SQLite.backupsnapshots for PocketID auth, Papra, Homebox, album-sort, the *arrs (Sonarr/Radarr/Lidarr/Prowlarr), qui, Pinchflat, Kavita, Stash, Tunarr.
What's not in this PR
- Plex library database (deep path with spaces; hot backup needs more careful handling).
- Named-volume state that isn't a database (e.g. Synapse media store).
- borg-ui (PR 3) and monitoring (PR 4).
Plumbing changes
-
compose.yaml.j2: borgmatic now joinsbackend-internal,shared-network, andproxy-networkso it can reach every DB container by hostname. - New
/var/backup/dumpsmount for the custom-hook output. -
Dockerfile: addssqlite3,jq, andcurlon top of the upstream borgmatic-collective image. -
env/borgmatic.env.j2: passes every DB password through as a separate env var;borgmatic.yamlreferences them via the{credential env VAR}syntax.
Vault keys consumed
All pre-existing in their respective group_vars/<stack>/vault.yml files. nuc-mini is a member of every relevant host group, so all values resolve at template time. No new vault entries required.
Documented in roles/backup/defaults/main.yml:
- Postgres:
immich_db_*,mastodon_db_*,synapse_db_*,mas_db_*,n8n_db_*,miniflux_db_*,forgejo_db_*,blinko_db_*,draftboard_db_* - MariaDB:
romm_db_root_password - MongoDB:
komodo_db_username,komodo_db_password - CouchDB:
couchdb_user,couchdb_password
Commits
backup: add database dump hooks across all stacksbackup: document DB hook coverage in README
Test plan
-
make deploy-backupbuilds the extended image and starts borgmatic -
docker inspect borgmatic -f '{{ range $k, $v := .NetworkSettings.Networks }}{{ $k }} {{ end }}'shows all three networks -
Inside the container: nc -zv immich_postgres 5432,nc -zv komodo_mongo 27017,nc -zv obsidian_livesync 5984all succeed -
Trigger a manual run: docker exec borgmatic borgmatic --verbosity 1 -
Logs show successful dumps for every Postgres, MariaDB, MongoDB hook -
ls /var/backup/dumps/couchdb/andls /var/backup/dumps/sqlite/show files after a run -
docker exec borgmatic borgmatic list --archive latestshows DB dumps in the archive (look forborgmatic/postgresql_databases/...paths and the/dumps/...paths) -
Pick one database, restore a dump to a test path, confirm it loads ( pg_restore,mongorestore,mariadb, or sqlite3 depending on engine)