Debian

BorgBackup with Borgmatic on Ubuntu / Debian / Rocky Linux

Most Linux backup guides stop at showing you tar or rsync and call it a day. BorgBackup goes further with deduplication, compression, and encryption built in, which means your second backup takes seconds instead of minutes because only changed data gets stored. Pair it with Borgmatic (a configuration-driven wrapper) and you get scheduled, automated backups with retention policies, database hooks, and monitoring integration from a single YAML file.

Original content from computingforgeeks.com - post 164366

This guide covers installing BorgBackup and Borgmatic on Ubuntu 24.04 (with notes for Debian 13 and Rocky Linux 10), initializing encrypted repositories, running manual and automated backups, restoring files, and setting up systemd timers for hands-off operation. If you already use Restic or Kopia, this gives you a solid comparison point since Borg takes a different approach to deduplication and repo management.

Tested March 2026 on Ubuntu 24.04.4 LTS (kernel 6.8.0-101) with BorgBackup 1.2.8, Borgmatic 2.1.3

Prerequisites

  • Ubuntu 24.04/22.04, Debian 13/12, or Rocky Linux 10/AlmaLinux 10
  • Root or sudo access
  • At least 5 GB free disk space for the backup repository (more for larger systems)
  • For remote backups: SSH access to the backup server with key-based authentication

Install BorgBackup and Borgmatic

Ubuntu / Debian

BorgBackup is in the default repositories. Borgmatic installs cleanly via pipx, which keeps it isolated from system Python packages:

sudo apt update
sudo apt install -y borgbackup pipx
sudo pipx install borgmatic

Add the pipx binary path so borgmatic is available system-wide:

sudo pipx ensurepath
sudo su -
export PATH="/root/.local/bin:$PATH"

Verify both tools are installed:

borg --version
borgmatic --version

You should see the versions confirmed:

borg 1.2.8
2.1.3

Rocky Linux / AlmaLinux / RHEL

On RHEL-family systems, BorgBackup is available from EPEL. Borgmatic is not packaged in EPEL, so install it with pipx:

sudo dnf install -y epel-release
sudo dnf install -y borgbackup pipx
sudo pipx install borgmatic
sudo pipx ensurepath
export PATH="/root/.local/bin:$PATH"

Initialize an Encrypted Borg Repository

Before Borgmatic enters the picture, it helps to understand the raw Borg commands. A Borg repository is a directory that stores all your backup archives. Create it with encryption enabled (you should always encrypt backups):

sudo mkdir -p /backup
sudo borg init --encryption=repokey /backup/borg-repo

Borg prompts for a passphrase. Choose something strong and store it separately. The repokey mode stores the encryption key inside the repository (encrypted with your passphrase). Borg prints a warning reminding you to back up the key:

IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
If you used a repokey mode, the key is stored in the repo, but you should back it up separately.
Use "borg key export" to export the key, optionally in printable format.
Write down the passphrase. Store both at safe place(s).

Export the key immediately and store it somewhere safe (a password manager, a USB drive in a fireproof safe, or both):

sudo borg key export /backup/borg-repo /root/borg-key-backup.txt

Create Your First Backup with Borg

To avoid typing the passphrase every time, store it in a file with restricted permissions:

echo "YourStrongPassphrase" | sudo tee /root/.borg-passphrase > /dev/null
sudo chmod 600 /root/.borg-passphrase
export BORG_PASSPHRASE=$(cat /root/.borg-passphrase)

Now create a backup of /etc and /var/log with zstd compression:

sudo BORG_PASSPHRASE=$(cat /root/.borg-passphrase) borg create \
  --stats --compression zstd \
  /backup/borg-repo::baseline-$(date +%Y%m%d) \
  /etc /var/log

Borg shows detailed statistics after the backup completes:

Repository: /backup/borg-repo
Archive name: baseline-20260324
Archive fingerprint: 76c4aed853fed3e228c907d48d624aad...
Time (start): Tue, 2026-03-24 22:16:48
Time (end):   Tue, 2026-03-24 22:16:49
Duration: 0.59 seconds
Number of files: 866
                       Original size      Compressed size    Deduplicated size
This archive:               19.75 MB              1.18 MB              1.15 MB
All archives:               19.75 MB              1.17 MB              1.22 MB

19.75 MB of data compressed down to 1.18 MB. That’s a 94% reduction. The deduplication column matters more once you have multiple backups, because Borg only stores unique data chunks across all archives.

Incremental Backups Are Almost Free

Make a change to the system (install a package, edit a config) and run another backup:

sudo BORG_PASSPHRASE=$(cat /root/.borg-passphrase) borg create \
  --stats --compression zstd \
  /backup/borg-repo::after-changes-$(date +%Y%m%d-%H%M) \
  /etc /var/log

The second backup is dramatically faster and smaller:

Duration: 0.31 seconds
                       Original size      Compressed size    Deduplicated size
This archive:               19.76 MB              1.19 MB            385.63 kB
All archives:               39.50 MB              2.36 MB              1.66 MB

Only 385.63 kB of new deduplicated data was stored. The backup completed in 0.31 seconds. This is why Borg works so well for daily automated backups: after the initial full backup, each subsequent run only transfers the delta.

List, Inspect, and Delete Archives

List all archives in the repository:

sudo BORG_PASSPHRASE=$(cat /root/.borg-passphrase) borg list /backup/borg-repo

Each archive is timestamped with its fingerprint:

baseline-20260324               Tue, 2026-03-24 22:16:48 [76c4aed853fe...]
after-changes-20260324-2217     Tue, 2026-03-24 22:17:07 [9be1a8b40ebd...]

View overall repository statistics with borg info:

sudo BORG_PASSPHRASE=$(cat /root/.borg-passphrase) borg info /backup/borg-repo

The output confirms the repository’s encryption status, cache location, and total deduplicated size:

Repository ID: 237a2fdc1790d6604add7629043c5c24...
Location: /backup/borg-repo
Encrypted: Yes (repokey)
                       Original size      Compressed size    Deduplicated size
All archives:               39.50 MB              2.36 MB              1.66 MB

To see exactly what changed between two archives, use borg diff:

sudo BORG_PASSPHRASE=$(cat /root/.borg-passphrase) borg diff \
  /backup/borg-repo::baseline-20260324 after-changes-20260324-2217

Borg shows the byte-level differences for each changed file, which is useful for auditing what happened between backups.

Restore Files from a Backup

Extract specific files from an archive into a target directory:

sudo mkdir -p /tmp/borg-restore
cd /tmp/borg-restore
sudo BORG_PASSPHRASE=$(cat /root/.borg-passphrase) borg extract \
  /backup/borg-repo::baseline-20260324 etc/hostname

The extracted files appear in the current directory with their original path structure. Verify the restore:

cat /tmp/borg-restore/etc/hostname

To restore an entire archive (full system restore), run borg extract without specifying paths. Do this from a live USB or rescue environment if restoring /etc and system directories on a running system.

Set Up Borgmatic for Automated Backups

Running raw borg commands works, but Borgmatic wraps everything into a single YAML configuration file and handles repo creation, backup, pruning, and consistency checks in one command. Generate the default config:

sudo mkdir -p /etc/borgmatic
sudo borgmatic config generate --destination /etc/borgmatic/config.yaml

The generated file has every option commented out with examples. Replace it with a production-ready config. Open the file:

sudo vi /etc/borgmatic/config.yaml

Use this as a starting point (adjust paths and retention to your needs):

source_directories:
    - /etc
    - /home
    - /var/log
    - /root

exclude_patterns:
    - "*.pyc"
    - /home/*/.cache
    - /var/log/journal

repositories:
    - path: /backup/borg-repo
      label: local

encryption_passcommand: cat /root/.borg-passphrase

compression: auto,zstd

keep_daily: 7
keep_weekly: 4
keep_monthly: 6
keep_yearly: 1

checks:
    - name: repository
      frequency: 2 weeks
    - name: archives
      frequency: 1 month

The encryption_passcommand tells Borgmatic to read the passphrase from a file instead of prompting. The keep_* options control how many archives to retain after pruning: 7 daily, 4 weekly, 6 monthly, 1 yearly. Validate the config before using it:

sudo borgmatic config validate

You should see the validation pass:

All configuration files are valid

Initialize the Repository via Borgmatic

If you haven’t already created the repo with raw Borg, Borgmatic can do it:

sudo borgmatic rcreate --encryption repokey

Run Your First Borgmatic Backup

Create a backup with statistics output:

sudo borgmatic create --stats --verbosity 1

Borgmatic reads the config, connects to the repository, and creates an archive:

local: Creating archive
Creating archive at "/backup/borg-repo::ubuntu-borg-2026-03-24T22:18:27.311489"
Duration: 1.09 seconds
Number of files: 1935
                       Original size      Compressed size    Deduplicated size
This archive:               19.40 MB              9.30 MB              9.04 MB

summary:
/etc/borgmatic/config.yaml: Successfully ran configuration file

Borgmatic automatically names archives using the hostname and timestamp pattern {hostname}-{now}. A second backup after installing a package took 0.39 seconds and stored only 51.47 kB of new deduplicated data.

Manage Archives with Borgmatic

List all archives:

sudo borgmatic list

The output shows all archives with timestamps:

local: Listing archives
ubuntu-borg-2026-03-24T22:18:27.311489 Tue, 2026-03-24 22:18:27 [e541a01c...]
ubuntu-borg-2026-03-24T22:18:47.604749 Tue, 2026-03-24 22:18:47 [186c749a...]

Prune old archives according to the retention policy in your config:

sudo borgmatic prune --list --verbosity 1

Borg shows which archives it keeps and which it removes based on your keep_* rules:

Keeping archive (rule: daily #1):        ubuntu-borg-2026-03-24T22:18:47.604749
Keeping archive (rule: daily[oldest] #2): ubuntu-borg-2026-03-24T22:18:27.311489

Extract a specific file from the latest archive:

sudo borgmatic extract --archive latest --path etc/hostname --destination /tmp/restore

For a full restore, omit --path to extract the entire archive.

Schedule Backups with Systemd Timers

Systemd timers are more reliable than cron for long-running tasks because they handle missed runs (from system downtime) and support randomized delays to avoid I/O storms. Create the service unit:

sudo vi /etc/systemd/system/borgmatic.service

Add the following configuration:

[Unit]
Description=borgmatic backup
Wants=network-online.target
After=network-online.target
ConditionACPower=true

[Service]
Type=oneshot
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7
ExecStartPre=sleep 1m
ExecStart=/root/.local/bin/borgmatic --verbosity -2 --syslog-verbosity 1
TimeoutStartSec=3h

[Install]
WantedBy=multi-user.target

The Nice=19 and IOSchedulingPriority=7 ensure backups run at the lowest CPU and I/O priority, so they don’t interfere with production workloads. ConditionACPower=true skips backups on battery power (useful for laptops). Now create the timer:

sudo vi /etc/systemd/system/borgmatic.timer

Set it to run daily with a randomized 3-hour delay:

[Unit]
Description=Run borgmatic backup daily

[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=3h

[Install]
WantedBy=timers.target

The Persistent=true ensures missed backups (from downtime) run immediately when the system comes back up. Enable and start the timer:

sudo systemctl daemon-reload
sudo systemctl enable borgmatic.timer
sudo systemctl start borgmatic.timer

Confirm the timer is active:

systemctl list-timers borgmatic.timer

The output shows when the next backup will run:

NEXT                            LEFT    LAST PASSED UNIT            ACTIVATES
Wed 2026-03-25 02:10:21 UTC  3h 51min  -         -  borgmatic.timer borgmatic.service

Back Up to a Remote Server via SSH

Local backups protect against software failures but not hardware failures. For off-site protection, Borg supports remote repositories over SSH. Set up key-based authentication to the backup server first:

sudo ssh-keygen -t ed25519 -f /root/.ssh/id_borg -N ""
sudo ssh-copy-id -i /root/.ssh/id_borg.pub [email protected]

Install BorgBackup on the remote server (it must be available on both ends). Then update your Borgmatic config to use the remote repository:

repositories:
    - path: ssh://[email protected]/./borg-repo
      label: remote
    - path: /backup/borg-repo
      label: local

ssh_command: ssh -i /root/.ssh/id_borg -o BatchMode=yes

With two repositories configured, Borgmatic backs up to both in sequence. If one fails, the other still completes. Initialize the remote repo before the first run:

sudo borgmatic rcreate --encryption repokey --repository ssh://[email protected]/./borg-repo

Installation Differences: Ubuntu vs Rocky Linux

ItemUbuntu 24.04 / Debian 13Rocky Linux 10 / AlmaLinux 10
BorgBackup packageapt install borgbackupdnf install epel-release borgbackup
Borgmaticpipx install borgmaticpipx install borgmatic (not in EPEL)
Pipx binary path/root/.local/bin/root/.local/bin
Systemd timer path/etc/systemd/system//etc/systemd/system/
Firewall (SSH remote)ufw allow 22/tcpfirewall-cmd --add-service=ssh --permanent
SELinuxNot applicableNo special policy needed (backups write to standard paths)

Troubleshooting Common Issues

Error: “Failed to create/acquire the lock”

Another Borg process is already accessing the repository. Wait for it to finish, or if a previous run crashed, break the stale lock:

sudo borgmatic borg break-lock

Only do this if you are certain no other backup is running. A stale lock usually means a previous borgmatic run was killed (power loss, OOM killer, manual termination).

Error: “Repository does not exist”

The repository path in your Borgmatic config doesn’t match an initialized Borg repo. Either the path is wrong, the parent directory doesn’t exist, or you haven’t run borgmatic rcreate yet. Check the path and initialize the repo.

Error: “passphrase supplied in BORG_PASSPHRASE is incorrect”

The passphrase file contains a trailing newline or the wrong passphrase. Verify with cat -A /root/.borg-passphrase and check for extra $ characters at the end of lines. Recreate the file with echo -n "passphrase" | sudo tee /root/.borg-passphrase to avoid trailing newlines.

Borgmatic command not found after pipx install

Pipx installs binaries to /root/.local/bin which may not be in the PATH for systemd services. The systemd unit file should use the full path: ExecStart=/root/.local/bin/borgmatic. For interactive shells, run sudo pipx ensurepath and open a new terminal.

Backup taking too long or using too much memory

Borg’s chunking and deduplication use memory proportional to the number of unique chunks. For very large repositories, set a cache limit in your Borgmatic config with upload_rate_limit: 10000 (in kB/s) for remote repos, or add exclusions for large directories you don’t need backed up (/var/log/journal is a common culprit).

Best Practices for Production Borg Backups

  • Export and store your key separately – Run borg key export and keep the key file in a password manager or offline storage. Without both the key and passphrase, your backups are permanently inaccessible.
  • Test restores regularly – A backup you haven’t tested is a backup that might not work. Schedule a quarterly test restore to a scratch directory and verify file integrity.
  • Use append-only mode for remote repos – If the backup client gets compromised, an attacker could delete your backups. Configure the remote repo with borg config /path/to/repo append_only 1 so the client can only add new archives, never delete existing ones.
  • Monitor backup success – Borgmatic integrates with Healthchecks.io, Cronitor, PagerDuty, and ntfy. Add a healthchecks: section to your config with a ping URL so you get alerted when backups fail silently.
  • Keep local and remote copies – Configure two repositories in Borgmatic (one local, one remote via SSH) for a basic 3-2-1 strategy. Borgmatic backs up to both sequentially from a single config.

Borgmatic Quick Reference

CommandWhat it does
borgmatic config generateGenerate a sample config with all options
borgmatic config validateCheck config for syntax errors
borgmatic rcreate --encryption repokeyInitialize a new encrypted repository
borgmatic create --statsRun a backup and show statistics
borgmatic listList all archives in the repository
borgmatic infoShow repository size and encryption info
borgmatic prune --listRemove old archives per retention policy
borgmatic extract --archive latestRestore the most recent archive
borgmatic borg break-lockRemove a stale lock from a crashed backup
borgmatic borg key export REPO FILEExport the encryption key

Summary

BorgBackup’s deduplication and compression mean your incremental backups measure in kilobytes, not megabytes. Borgmatic wraps the entire workflow (create, prune, check) into a single config file that a systemd timer runs daily. With encryption enabled, append-only remote repos, and a tested restore procedure, you have a backup system that handles both accidental deletions and disk failures. For complementary protection, pair Borg with Timeshift for system snapshots on desktops, or use a separate tool for database-specific backups where point-in-time recovery matters.

Related Articles

Containers How To Provision PV on Kubernetes using Local Path Provisioner Arch Linux How To Analyze Disk usage on Linux using ncdu Ubuntu How To Install XAMPP On Ubuntu 24.04|22.04 Php Build and Install PHP 8,7 on Ubuntu 18.04 (Bionic Beaver)

Leave a Comment

Press ESC to close