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.
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
| Item | Ubuntu 24.04 / Debian 13 | Rocky Linux 10 / AlmaLinux 10 |
|---|---|---|
| BorgBackup package | apt install borgbackup | dnf install epel-release borgbackup |
| Borgmatic | pipx install borgmatic | pipx 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/tcp | firewall-cmd --add-service=ssh --permanent |
| SELinux | Not applicable | No 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 exportand 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 1so 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
| Command | What it does |
|---|---|
borgmatic config generate | Generate a sample config with all options |
borgmatic config validate | Check config for syntax errors |
borgmatic rcreate --encryption repokey | Initialize a new encrypted repository |
borgmatic create --stats | Run a backup and show statistics |
borgmatic list | List all archives in the repository |
borgmatic info | Show repository size and encryption info |
borgmatic prune --list | Remove old archives per retention policy |
borgmatic extract --archive latest | Restore the most recent archive |
borgmatic borg break-lock | Remove a stale lock from a crashed backup |
borgmatic borg key export REPO FILE | Export 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.