Borgmatic recipes — declarative backup config for borg
Borg is a great backup engine; borgmatic is the YAML-driven wrapper that turns borg into a hands-off scheduled backup system. You declare what to back up, what to skip, retention policy, healthcheck pings, pre/post hooks, and borgmatic handles cron/timer invocation, locking, and reporting. This article gives you copy-paste-ready recipes for the common LYLIX VPS scenarios.
Install
# Debian / Ubuntu
apt install borgbackup borgmatic
# AlmaLinux (EPEL needed for borgbackup, borgmatic via pip)
dnf install epel-release
dnf install borgbackup
pip3 install borgmatic
Borgmatic config lives at /etc/borgmatic/config.yaml by default. The recipes below go there (or under /etc/borgmatic.d/ if you want to split per-repo configs).
Recipe 1: single-server, off-host to Borgbase / rsync.net
Lowest-friction setup. Borgbase / rsync.net charge a flat monthly fee for borg-compatible storage and handle the server-side. You provide an SSH URL and a passphrase.
source_directories:
- /etc
- /home
- /var/www
- /var/lib/postgresql
- /opt/myapp
repositories:
- path: ssh://user@borgbase-or-rsync.net/./repo
label: offsite
exclude_patterns:
- '*/.cache'
- '*/node_modules'
- /var/cache
- /tmp/*
# Retention: 7 daily, 4 weekly, 6 monthly, 1 yearly
keep_daily: 7
keep_weekly: 4
keep_monthly: 6
keep_yearly: 1
# Run integrity check monthly (not every backup -- it's slow)
checks:
- name: repository
frequency: 1 month
- name: archives
frequency: 1 month
# Healthchecks ping (use Healthchecks.io or self-hosted)
healthchecks:
ping_url: https://hc-ping.com/your-uuid-here
# Encryption + passphrase from file (don't commit it!)
encryption_passphrase: !include /etc/borgmatic/passphrase.txt
Then schedule:
# systemd timer (preferred — bundled with borgmatic)
systemctl enable --now borgmatic.timer
The timer runs daily; borgmatic respects the frequency directives for the checks so they don't run every day.
Recipe 2: database-aware backups with hooks
Borgmatic's database hook integration dumps your databases as part of the same backup run, so the dumps end up inside the borg archive without staging files manually.
postgresql_databases:
- name: all
hostname: localhost
username: postgres
format: custom
mysql_databases:
- name: all
hostname: localhost
username: root
# Reads ~/.my.cnf for the password if not specified here
options: --single-transaction --routines --triggers --events --hex-blob
Borgmatic runs the dumps before the backup, includes them in the archive, then cleans up the staging files. On restore, borgmatic restore --archive latest reverses the process — pulls the dumps out, runs them back into the live database.
Recipe 3: multi-target (offsite + onsite)
If you want a fast local restore path plus an off-host copy, declare two repositories. Borgmatic backs up to both in sequence.
repositories:
- path: /mnt/local-backup-disk/repo
label: local
- path: ssh://user@offsite-host/./repo
label: offsite
# Same retention for both, or split via separate config files in /etc/borgmatic.d/
The local copy gives you 30-second restores for "I deleted the wrong file" cases. The off-host copy is your real DR.
Recipe 4: large data + WAL archiving for PostgreSQL
For databases over ~50 GB where logical dumps take too long, do nightly file-level backups of the data directory paired with continuous WAL archiving (see the dedicated PostgreSQL WAL article).
source_directories:
- /var/lib/postgresql/15/main
- /var/lib/postgresql/wal_archive
before_backup:
- psql -U postgres -c "SELECT pg_backup_start('borgmatic')"
after_backup:
- psql -U postgres -c "SELECT pg_backup_stop()"
# Don't dump separately -- the file-level snapshot + WAL is the backup
postgresql_databases: []
The before_backup / after_backup hooks tell PostgreSQL "I'm doing a base backup" so the WAL stream stays consistent with the file copy.
Pre/post hooks for application coordination
If your application has its own backup logic (FreePBX®'s backup module, Mailcow's helper script, Nextcloud's maintenance mode), wrap it in borgmatic hooks so a single cron job covers everything:
before_backup:
- /usr/local/bin/maintenance-mode-on
- /usr/sbin/fwconsole backup --backup=auto-daily
after_backup:
- /usr/local/bin/maintenance-mode-off
If a hook fails, borgmatic logs it and continues by default; set before_backup_after_error if you want failures to abort the whole run.
Common pitfalls
- Passphrase loss = data loss. Borg can't decrypt without the passphrase. Store it in your password manager AND printed in a sealed envelope in the safe AND in a second password manager owned by a different person. See the encrypted-backup key management article.
- Repository moves break borg's cache. If you change the SSH URL or move the repo, run
borg break-lockand re-run; first backup after the move is slow as borg rebuilds the local cache. - Compaction needs scheduling. Add
compact: trueunderchecks:or runborg compactperiodically; otherwise the repo grows even when archives are pruned. - SSH key auth required. Borgmatic doesn't prompt for SSH passwords; configure
ssh-agentor a key dedicated to backup with no passphrase, kept in/root/.ssh/with0600.
Output monitoring
Pair borgmatic with the healthchecks integration shown above so silent failures get caught. The healthcheck side alerts when a ping doesn't arrive in the expected window; set the window slightly longer than your slowest expected backup so warnings don't fire on legitimate long runs.
Also Read
Powered by WHMCompleteSolution