Server - Backup - Borgmatic Backup
The previous article installed Borg and borgmatic on February and set up the SSH key that connects to the NAS. This article configures borgmatic: writing the config file, initialising the repositories, and running the first backup manually to confirm everything works.
The following article covers scheduling, so borgmatic runs automatically on a timer, and notifications, so you find out if something goes wrong.
Before you start
Three things need to be in place before this article makes sense.
Borg and borgmatic must be installed on February. The install article covers this.
The SSH key at /etc/borg/ssh/id_ed25519 must exist, and its public key must be installed on the NAS with a forced command pointing to the February repository. If you can run the following and get a connection that immediately closes rather than an error, the SSH setup is complete:
sudo ssh -i /etc/borg/ssh/id_ed25519 borg-backup@nas.burnage.yourdomain.net
The NAS backup server must have the Burnage and Lighthouse repositories initialised on its end, or be ready for borgmatic to initialise them here. The NAS Setup article covers the server side. If the NAS is not set up yet, come back to this article once it is.
Directory structure
The install article created /etc/borg. Check it is present and has the right structure:
sudo ls -la /etc/borg/
You should see:
drwx------ 3 root root 4096 ...
drwx------ 2 root root 4096 ... keys/
drwx------ 2 root root 4096 ... ssh/
-rw------- 1 root root 411 ... ssh/id_ed25519
-rw-r--r-- 1 root root 96 ... ssh/id_ed25519.pub
Create the borgmatic configuration directory if it does not already exist:
sudo mkdir -p /etc/borgmatic
The passphrase
borgmatic uses repokey-blake2 encryption by default, which stores the key inside the repository but requires a passphrase to unlock it. The passphrase is the thing you must not lose.
Generate a strong passphrase. If you have xkcdpass installed:
xkcdpass --numwords 7
Or use your password manager’s generator. Whatever you use, store it somewhere you will still have it if February is completely gone: KeePassXC under Infrastructure > Backup > February Repository Passphrase works well. The KeePass database itself should be backed up separately.
Without the passphrase and the SSH private key, the backup repository cannot be decrypted. There is no recovery path. Keep both.
Notification script
borgmatic can run a script when a backup fails. This is how you find out something went wrong rather than discovering the gap months later when you need a restore.
Create the script:
sudo tee /etc/borgmatic/notify.sh << 'EOF'
#!/usr/bin/env bash
#
# Notify root of borgmatic backup error.
#
# Called by borgmatic with four arguments:
# $1 - configuration filename
# $2 - repository path
# $3 - error message
# $4 - command output
mail -s "Borgmatic Error on ${HOSTNAME}" root << MAIL
borgmatic backup on ${HOSTNAME} failed.
Configuration file: $1
Repository: $2
Error message: $3
Command output:
$4
Check the systemd journal on ${HOSTNAME} for details:
sudo journalctl -u borgmatic --since yesterday
MAIL
EOF
sudo chmod 0700 /etc/borgmatic/notify.sh
For this to deliver mail, February needs a local mail transport configured. If you are not routing local mail anywhere yet, a simple alternative is to write errors to a dedicated log file and pick them up via monitoring later. The notification script approach is the most direct option if mail is working.
borgmatic configuration
borgmatic uses a single YAML config file. The upstream source uses the legacy location: / storage: / retention: multi-section schema from borgmatic v1.7 and earlier. borgmatic v1.8+ uses a flat schema, which is what February is running.
Generate a commented config template to reference:
sudo generate-borgmatic-config -d /etc/borgmatic/config.yaml.example
Then write the actual config:
sudo tee /etc/borgmatic/config.yaml << 'EOF'
# borgmatic configuration for February
# Flat schema (borgmatic >= 1.8)
# See: https://torsion.org/borgmatic/docs/reference/configuration/
# -----------------------------------------------------------------------
# Source directories
# -----------------------------------------------------------------------
source_directories:
- /etc
- /home
- /root
- /var/log
- /var/spool/cron
- /usr/local/bin
- /usr/local/sbin
# -----------------------------------------------------------------------
# Repositories
# -----------------------------------------------------------------------
repositories:
- path: ssh://borg-backup@nas.burnage.yourdomain.net/volume1/BorgBackup/{hostname}
label: local-nas
- path: ssh://borg-backup@nas.lighthouse.yourdomain.net/volume1/BorgBackup/{hostname}
label: remote-nas
# -----------------------------------------------------------------------
# Storage settings
# -----------------------------------------------------------------------
encryption_passphrase: "your-seven-word-passphrase-goes-here"
compression: auto,zstd
ssh_command: ssh -i /etc/borg/ssh/id_ed25519
# -----------------------------------------------------------------------
# Retention policy
# -----------------------------------------------------------------------
keep_daily: 7
keep_weekly: 4
keep_monthly: 6
keep_yearly: 1
# -----------------------------------------------------------------------
# Consistency checks
# -----------------------------------------------------------------------
checks:
- name: repository
frequency: always
- name: archives
frequency: 2 weeks
# -----------------------------------------------------------------------
# Exclude patterns
# -----------------------------------------------------------------------
exclude_patterns:
- '**/.cache'
- '**/cache'
- /var/cache
- /var/tmp
- /tmp
- /run
- /proc
- /sys
- /dev
- /lost+found
exclude_caches: true
exclude_if_present:
- .nobackup
# -----------------------------------------------------------------------
# Hooks
# -----------------------------------------------------------------------
on_error:
- /etc/borgmatic/notify.sh "{configuration_filename}" "{repository}" "{error}" "{output}"
before_backup:
- echo "Starting borgmatic backup on $(date)"
after_backup:
- echo "Backup completed on $(date)"
EOF
sudo chmod 0600 /etc/borgmatic/config.yaml
Replace your-seven-word-passphrase-goes-here with the passphrase you generated. Replace the NAS hostnames with the actual hostnames or IP addresses on your network. If the Lighthouse NAS connects via VPN, the VPN must be up for the remote repository backup to succeed; borgmatic will report an error for the remote repository and continue with the local one.
Validate the configuration
Before doing anything else, check the config parses correctly:
sudo borgmatic config validate
If there are errors, borgmatic will tell you which line and what the problem is. The most common issues are YAML indentation (spaces only, no tabs) and mismatched quotes.
Initialise the repositories
This step creates the Borg repositories on the NAS. It only runs once. If the repository directories do not exist on the NAS, the NAS forced command must be configured with --storage-quota and the right path before this will succeed.
Initialise both repositories:
sudo borgmatic init --encryption repokey-blake2
borgmatic will prompt for confirmation on each repository. When initialisation completes, Borg creates a keyfile inside each repository (for repokey mode, the key is stored in the repo itself, so you only need the passphrase to access it from any machine with SSH access to the NAS).
Confirm the repositories were created:
sudo borgmatic list
If the repositories are empty and healthy, borgmatic will report no archives found, which is correct at this stage.
Run the first backup
Run the first backup manually with verbose output so you can watch what happens:
sudo borgmatic create --verbosity 1 --list --stats
The first run transfers everything from the source directories. Depending on how much is in /etc, /home, and /var/log, this may take a few minutes. The --list flag shows each file as it is processed. The --stats flag prints a summary at the end showing original size, compressed size, and deduplicated size.
A successful stats block looks something like:
------------------------------------------------------------------------------
Original size Compressed size Deduplicated size
This archive: 87.43 MB 34.21 MB 34.19 MB
All archives: 87.43 MB 34.21 MB 34.19 MB
------------------------------------------------------------------------------
If you see errors for the remote NAS and the VPN is not currently up, that is expected. borgmatic exits with a non-zero status code if any repository fails, even if others succeeded. The local-nas archive is the important one to confirm for now.
Confirm the archive
List the archives to verify the backup was stored:
sudo borgmatic list
You should see one archive per repository that was reachable, named something like february-2026-05-09T10:00:00.000000.
To see what is inside the archive:
sudo borgmatic list --archive latest --find /etc/hostname
This searches the most recent archive for a specific file. If it comes back with a result, the archive is intact and searchable.
What is next
borgmatic is now configured and has created its first backup. The next article covers scheduling borgmatic to run daily via a systemd timer, and adding notification hooks so you are alerted if a backup fails. An unmonitored backup is only marginally better than no backup at all.
The three things you need to access this backup are the SSH private key at
/etc/borg/ssh/id_ed25519, the repository passphrase, and network access to the NAS. If all three are gone, the backup is inaccessible. Keep the passphrase somewhere that survives a total loss of February.