BorgBackup: Incremental and Deduplicated Backup
BorgBackup is a backup tool that uses deduplication and compression to drastically reduce space used. A daily backup of a 20 GB server typically takes only 1-2 GB thanks to block deduplication of unchanged data.
02
Installation
bash
# Ubuntu / Debian
apt install borgbackup -y
# CentOS / AlmaLinux
dnf install borgbackup -y
# Verify
borg --version
03
Create a Borg repository
The repository is where all backups are saved:
bash
# Local repository (on disk or external mount)
borg init --encryption=repokey /mnt/backup/my-server
# Remote repository via SSH (on another server)
borg init --encryption=repokey user@backup-server:/path/to/repo
Borg will ask you to create a passphrase: save it somewhere safe. Without it you can't recover your backups.
Run borg key export /mnt/backup/my-server /root/borg-key-backup.txt and keep the file in a safe place separate from the server. Without key + passphrase the backups are inaccessible.
04
First backup
bash
# Create an archive (snapshot) of the server
borg create \
--stats \
--progress \
--compression lz4 \
/mnt/backup/my-server::backup-{now:%Y-%m-%d} \
/etc \
/home \
/root \
/var/www \
/var/lib/mysql \
--exclude /var/lib/mysql/*.pid \
--exclude /home/*/.cache \
--exclude /root/.cache
05
Automatic backup script
bash
cat > /usr/local/bin/borg-backup.sh << 'SCRIPT'
#!/bin/bash
# Configuration
REPO="/mnt/backup/my-server"
export BORG_PASSPHRASE="your_passphrase"
# Log
LOG="/var/log/borg-backup.log"
exec >> $LOG 2>&1
echo "=== Backup started: $(date) ==="
# Create the backup
borg create \
--stats \
--compression lz4 \
"$REPO::backup-{now:%Y-%m-%d_%H%M}" \
/etc /home /root /var/www /var/lib/mysql \
--exclude '/home/*/.cache' \
--exclude '/root/.cache' \
--exclude '*.pyc' \
--exclude '*.log'
BACKUP_EXIT=$?
# Pruning: maintain retention policy
borg prune \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
"$REPO"
PRUNE_EXIT=$?
echo "=== Backup completed: $(date) (backup: $BACKUP_EXIT, prune: $PRUNE_EXIT) ==="
SCRIPT
chmod +x /usr/local/bin/borg-backup.sh
Schedule with cron
bash
echo "0 2 * * * root /usr/local/bin/borg-backup.sh" > /etc/cron.d/borg-backup
06
Backup to remote server via SSH
bash
# Configure SSH keys without password for backup
ssh-keygen -t ed25519 -f /root/.ssh/id_borg -N ""
ssh-copy-id -i /root/.ssh/id_borg.pub user@backup-server
# Init the remote repo
BORG_PASSPHRASE="passphrase" borg init \
--encryption=repokey \
--rsh "ssh -i /root/.ssh/id_borg" \
user@backup-server:/backup/my-server
# Backup to remote repo
borg create \
--rsh "ssh -i /root/.ssh/id_borg" \
user@backup-server:/backup/my-server::backup-{now:%Y-%m-%d} \
/etc /home /root /var/www
07
List and verify backups
bash
# List all archives in the repository
borg list /mnt/backup/my-server
# List files in a specific archive
borg list /mnt/backup/my-server::backup-2025-01-15
# Archive info (sizes, deduplication)
borg info /mnt/backup/my-server::backup-2025-01-15
# Verify repository integrity
borg check /mnt/backup/my-server
08
Restore
bash
# Restore entire archive to current directory
cd /tmp/restore
borg extract /mnt/backup/my-server::backup-2025-01-15
# Restore only a specific file or folder
borg extract /mnt/backup/my-server::backup-2025-01-15 etc/nginx/nginx.conf
# Restore to specific directory
borg extract --destination /tmp/restore /mnt/backup/my-server::backup-2025-01-15 var/www/html
09
How much space does Borg save?
Real example with daily backups for 30 days of a 10 GB server:
| Method | Space used |
|---|---|
| Complete copy × 30 | 300 GB |
| rsync incremental × 30 | ~80 GB |
| Borg (deduplicated) | ~15 GB |
The difference is largest with frequent backups of data that changes little.
Related articles
