TL;DR — Quick Summary
BorgBackup guide: deduplicated, encrypted, compressed backups on Linux. Install, automate with systemd, remote SSH repos, Borgmatic, and disaster recovery.
BorgBackup (borg) is a deduplicating, compressed, and encrypted backup tool for Linux that can reduce backup storage by 50–90% compared to traditional full or incremental backups. This guide covers everything from installation through Borgmatic automation, remote SSH backups, and disaster recovery testing.
Prerequisites
- Linux system (Ubuntu 22.04+, Debian 12+, RHEL 9+, or Fedora 38+).
- Root or sudo access on the machine to back up.
- A backup destination: local disk, external drive, or remote server with SSH access.
- For remote backups: BorgBackup installed on both client and backup server.
Why BorgBackup?
Traditional backup tools copy files unchanged. BorgBackup uses content-defined chunking — it splits every file into variable-length blocks, hashes each block, and only stores blocks that have never been seen before. This produces dramatic space savings:
- Deduplication — 10 daily backups of a 100 GB server may use only 110 GB total.
- AES-256-CTR encryption — Data is encrypted before leaving the source machine.
- Authenticated MACs — BLAKE2b or SHA-256 ensure backups have not been tampered with.
- Multiple compression options —
lz4(fast),zstd(balanced),lzma(smallest). - SSH transport — Back up to any remote server with no special daemon required.
- FUSE mounting — Browse backup archives like a regular filesystem.
Installation
Debian / Ubuntu
sudo apt update && sudo apt install borgbackup -y
Fedora / RHEL / Rocky Linux
sudo dnf install borgbackup -y
Latest version via pip
pip install --user borgbackup
# Verify
borg --version
Initialize a Repository
A BorgBackup repository is the storage container that holds all your backup archives.
Local repository
borg init --encryption=repokey-blake2 /backup/borg-repo
Remote repository over SSH
borg init --encryption=repokey-blake2 borg@backupserver:/backup/borg-repo
You will be prompted for a passphrase. This passphrase protects the encryption key. Without it, your backups cannot be decrypted.
Export the repository key immediately
borg key export /backup/borg-repo ~/borg-repo-key.txt
Store borg-repo-key.txt and the passphrase in a separate location from the backup repository — a password manager, offline USB drive, or printed paper copy. Loss of both the repo key and passphrase means permanent data loss.
Encryption mode comparison
| Mode | Key location | Use case |
|---|---|---|
repokey-blake2 | Inside the repo | Easiest; recommended for most users |
keyfile-blake2 | On the client only | Maximum security; key never leaves client |
none | N/A | Internal networks only; no encryption |
Create Backups
Basic archive
export BORG_PASSPHRASE='your-strong-passphrase'
export BORG_REPO='/backup/borg-repo'
borg create \
--stats \
--progress \
--compression lz4 \
"$BORG_REPO::{hostname}-{now:%Y-%m-%dT%H:%M}" \
/etc /home /var/www /opt \
--exclude '*.log' \
--exclude '*.tmp' \
--exclude '/home/*/.cache' \
--exclude '/home/*/.local/share/Trash'
Compression options
| Option | Speed | Ratio | Best for |
|---|---|---|---|
lz4 | Fastest | Moderate | Daily automated backups |
zstd,3 | Fast | Good | General use |
zstd,11 | Moderate | Excellent | Storage-constrained setups |
lzma,6 | Slow | Maximum | Archival; rarely accessed |
Sample output
Archive name: webserver-2026-03-22T03:00
Original size: 48.21 GB
Compressed size: 13.74 GB
Deduplicated size: 1.08 GB ← only new data stored
Duration: 1 minutes 32.54 seconds
List and Mount Archives
List all archives in a repository
borg list /backup/borg-repo
Show archive contents
borg list /backup/borg-repo::webserver-2026-03-22T03:00
Mount an archive for FUSE browsing
mkdir -p /mnt/borg-restore
borg mount /backup/borg-repo::webserver-2026-03-22T03:00 /mnt/borg-restore
# Browse and copy files normally
ls /mnt/borg-restore/home/alice/
# Unmount when done
borg umount /mnt/borg-restore
FUSE mounting requires fuse or fuse3 to be installed (sudo apt install fuse3).
Extract Files
Full archive extraction
cd /tmp/restore
borg extract /backup/borg-repo::webserver-2026-03-22T03:00
Partial restore (specific paths only)
borg extract /backup/borg-repo::webserver-2026-03-22T03:00 \
home/alice/documents \
etc/nginx
Dry run (list what would be extracted)
borg extract --dry-run --list /backup/borg-repo::webserver-2026-03-22T03:00
Pruning Old Archives
borg prune removes archives that no longer meet your retention policy. Run it after every backup to prevent unbounded storage growth.
borg prune \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=6 \
--keep-yearly=2 \
--list \
/backup/borg-repo
| Flag | Archives kept |
|---|---|
--keep-daily=7 | Last backup from each of the past 7 days |
--keep-weekly=4 | Last backup from each of the past 4 weeks |
--keep-monthly=6 | Last backup from each of the past 6 months |
--keep-yearly=2 | Last backup from each of the past 2 years |
After pruning, run compaction to reclaim disk space from deleted archives:
borg compact /backup/borg-repo
Automation with systemd Timer
A systemd timer is more reliable than cron for backup automation — it logs to journald, retries on missed runs, and integrates with dependency management.
/etc/systemd/system/borg-backup.service
[Unit]
Description=BorgBackup daily backup
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=root
Environment=BORG_PASSPHRASE=your-strong-passphrase
Environment=BORG_REPO=/backup/borg-repo
ExecStart=/usr/bin/borg create --stats --compression lz4 \
$BORG_REPO::{hostname}-{now:%%Y-%%m-%%dT%%H:%%M} \
/etc /home /var /opt \
--exclude '*.log' --exclude '/home/*/.cache'
ExecStartPost=/usr/bin/borg prune --keep-daily=7 --keep-weekly=4 --keep-monthly=6 $BORG_REPO
ExecStartPost=/usr/bin/borg compact $BORG_REPO
/etc/systemd/system/borg-backup.timer
[Unit]
Description=BorgBackup daily timer
[Timer]
OnCalendar=daily
RandomizedDelaySec=30min
Persistent=true
[Install]
WantedBy=timers.target
Enable and start
systemctl daemon-reload
systemctl enable --now borg-backup.timer
systemctl list-timers borg-backup.timer
Monitor logs
journalctl -u borg-backup.service --since today
Remote Backups over SSH
Restrict the SSH key on the backup server
In ~/.ssh/authorized_keys on the backup server, prefix the public key with a forced command to prevent the backup key from being used for anything except borg:
command="borg serve --restrict-to-path /backup/borg-repo",restrict ssh-rsa AAAA...yourkey...
The restrict keyword disables port forwarding, agent forwarding, and X11. This limits the blast radius if the backup client is compromised.
Client configuration
export BORG_REPO='borg@backupserver:/backup/borg-repo'
export BORG_RSH='ssh -i /root/.ssh/borg_ed25519 -o StrictHostKeyChecking=yes'
borg create "$BORG_REPO::{hostname}-{now:%Y-%m-%dT%H:%M}" /etc /home
BorgBase and rsync.net
Managed BorgBackup hosting eliminates the need to maintain a backup server:
| Service | Price | Notes |
|---|---|---|
| BorgBase | Free 10 GB / $2/month for more | Designed for borg; append-only repos available |
| rsync.net | $0.008/GB/month | borg pre-installed; full SSH access |
| Local disk | Hardware cost | Fastest; no network dependency |
Borgmatic: Higher-Level Wrapper
Borgmatic replaces custom shell scripts with a declarative YAML configuration. It runs create, prune, compact, and check in one command and supports hooks for pre/post-backup actions.
Installation
pip install borgmatic
/etc/borgmatic/config.yaml
repositories:
- path: /backup/borg-repo
label: local
source_directories:
- /etc
- /home
- /var/www
- /opt
exclude_patterns:
- '*.log'
- '*.tmp'
- /home/*/.cache
encryption_passphrase: "your-strong-passphrase"
compression: lz4
keep_daily: 7
keep_weekly: 4
keep_monthly: 6
keep_yearly: 2
checks:
- name: repository
frequency: 2 weeks
- name: archives
frequency: 1 month
hooks:
before_backup:
- echo "Starting backup $(date)"
after_backup:
- echo "Backup finished $(date)"
on_error:
- echo "Backup FAILED at $(date)" | mail -s "Borg error on $(hostname)" admin@example.com
healthchecks:
ping_url: https://hc-ping.com/your-uuid-here
Run borgmatic manually
borgmatic --verbosity 1
Systemd timer for borgmatic
# borgmatic ships a systemd timer — enable it:
systemctl enable --now borgmatic.timer
Monitoring and Repository Health
Repository info
borg info /backup/borg-repo
Verify repository integrity
borg check /backup/borg-repo
Run borg check monthly to detect silent data corruption. Borgmatic can automate this on a configurable schedule (see checks: in the config).
Disaster Recovery Procedure
- Install BorgBackup on the replacement system.
- Transfer the repo key (the exported key file) to the new system.
- Set credentials:
export BORG_PASSPHRASE='your-passphrase' export BORG_REPO='borg@backupserver:/backup/borg-repo' - List available archives:
borg list "$BORG_REPO" - Extract the most recent archive:
cd / borg extract "$BORG_REPO::webserver-2026-03-22T03:00" - Verify the restore — check that critical files and services work before cutting over production traffic.
Always test restores on a regular schedule (quarterly minimum). A backup you have never tested is a backup you cannot trust.
Borg vs Restic vs Duplicati vs rsync vs Timeshift
| Feature | BorgBackup | Restic | Duplicati | rsync | Timeshift |
|---|---|---|---|---|---|
| Deduplication | Yes | Yes | No | No | Yes (hard links) |
| Encryption | AES-256 | AES-256 | AES-256 | No (native) | No |
| Compression | lz4/zstd/lzma | zstd | Deflate | No | No |
| Remote backends | SSH, BorgBase | S3, B2, SFTP, many | S3, FTP, WebDAV, many | SSH (rsync daemon) | Local only |
| GUI | No | Vorta (third-party) | Yes (web UI) | No | Yes |
| Borgmatic support | Yes | No | No | No | No |
| Best for | Servers, DevOps | Multi-cloud flexibility | Desktop users | Simple mirroring | Desktop system restore |
Summary
- Deduplification stores only unique data chunks — 10 daily backups of 100 GB typically use ~110 GB.
- Always export the repo key (
borg key export) and store it separately from the backup. - Use repokey-blake2 encryption for authenticated AES-256 protection.
- Prune with
borg pruneand free space withborg compactafter every backup run. - Automate with systemd timer for reliable scheduling with journald logging.
- Restrict SSH keys on backup servers with
command="borg serve ..."inauthorized_keys. - Use Borgmatic to replace shell scripts with maintainable YAML configuration.
- Test restores quarterly — a backup never tested is not a backup.