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 optionslz4 (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

ModeKey locationUse case
repokey-blake2Inside the repoEasiest; recommended for most users
keyfile-blake2On the client onlyMaximum security; key never leaves client
noneN/AInternal 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

OptionSpeedRatioBest for
lz4FastestModerateDaily automated backups
zstd,3FastGoodGeneral use
zstd,11ModerateExcellentStorage-constrained setups
lzma,6SlowMaximumArchival; 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
FlagArchives kept
--keep-daily=7Last backup from each of the past 7 days
--keep-weekly=4Last backup from each of the past 4 weeks
--keep-monthly=6Last backup from each of the past 6 months
--keep-yearly=2Last 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:

ServicePriceNotes
BorgBaseFree 10 GB / $2/month for moreDesigned for borg; append-only repos available
rsync.net$0.008/GB/monthborg pre-installed; full SSH access
Local diskHardware costFastest; 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

  1. Install BorgBackup on the replacement system.
  2. Transfer the repo key (the exported key file) to the new system.
  3. Set credentials:
    export BORG_PASSPHRASE='your-passphrase'
    export BORG_REPO='borg@backupserver:/backup/borg-repo'
  4. List available archives:
    borg list "$BORG_REPO"
  5. Extract the most recent archive:
    cd /
    borg extract "$BORG_REPO::webserver-2026-03-22T03:00"
  6. 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

FeatureBorgBackupResticDuplicatirsyncTimeshift
DeduplicationYesYesNoNoYes (hard links)
EncryptionAES-256AES-256AES-256No (native)No
Compressionlz4/zstd/lzmazstdDeflateNoNo
Remote backendsSSH, BorgBaseS3, B2, SFTP, manyS3, FTP, WebDAV, manySSH (rsync daemon)Local only
GUINoVorta (third-party)Yes (web UI)NoYes
Borgmatic supportYesNoNoNoNo
Best forServers, DevOpsMulti-cloud flexibilityDesktop usersSimple mirroringDesktop 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 prune and free space with borg compact after every backup run.
  • Automate with systemd timer for reliable scheduling with journald logging.
  • Restrict SSH keys on backup servers with command="borg serve ..." in authorized_keys.
  • Use Borgmatic to replace shell scripts with maintainable YAML configuration.
  • Test restores quarterly — a backup never tested is not a backup.