BorgBackup: Deduplicating Backup with Borgmatic
Space-efficient encrypted backups with Borg. Automate with Borgmatic for hands-off protection.
BorgBackup (Borg) is a deduplicating backup program with compression and encryption. Combined with Borgmatic, it provides an enterprise-grade backup solution perfect for homelabs. This guide covers everything from installation to advanced automation.
Why BorgBackup?
BorgBackup offers exceptional features for homelab environments:
- Extreme deduplication: Content-defined chunking saves massive amounts of space
- Compression: Multiple algorithms (lz4, zstd, zlib) reduce storage requirements
- Encryption: AES-256 encryption with different modes for various security needs
- Space efficiency: Only stores unique data blocks across all backups
- Fast backups: Only transfers changed data, backed by efficient chunking
- Reliable: Atomic commits ensure repository integrity
- Mountable: Browse and restore files by mounting backups as filesystems
- Remote support: SSH-based remote repositories with excellent performance
BorgBackup vs Other Solutions
Borg vs Restic:
- Borg: Better deduplication, faster, more mature
- Restic: More backends, easier to use, written in Go
Borg vs Duplicity:
- Borg: Much faster, better deduplication, modern architecture
- Duplicity: Older, simpler, uses standard formats
Borg vs rsync:
- Borg: Deduplication, encryption, compression, versioning
- rsync: Simple mirroring, no built-in versioning or encryption
Part 1: Installing BorgBackup
Installation on Debian/Ubuntu
Install from distribution packages:
sudo apt update
sudo apt install borgbackup -y For the latest version, use the official repository:
# Add BorgBackup repository
sudo add-apt-repository ppa:costamagnagianfranco/borgbackup
sudo apt update
sudo apt install borgbackup -y Verify installation:
borg --version Installation on Other Systems
Fedora/CentOS/RHEL:
sudo dnf install borgbackup -y From Binary (Latest Version):
# Download latest release
wget https://github.com/borgbackup/borg/releases/download/1.2.7/borg-linux64
sudo mv borg-linux64 /usr/local/bin/borg
sudo chmod +x /usr/local/bin/borg Install with pip (for latest features):
sudo apt install python3-pip python3-dev libacl1-dev libssl-dev -y
sudo pip3 install borgbackup Part 2: Setting Up a Borg Repository
Local Repository
Create a local backup repository:
# Create directory for repository
sudo mkdir -p /mnt/backup/borg-repo
# Initialize repository with encryption
borg init --encryption=repokey /mnt/backup/borg-repo You’ll be prompted to enter a passphrase. This encrypts your backups.
Remote Repository (SSH)
Set up SSH keys for passwordless access:
# Generate SSH key if you don't have one
ssh-keygen -t ed25519 -C "backup-key"
# Copy to backup server
ssh-copy-id backup-user@backup-server Initialize remote repository:
borg init --encryption=repokey backup-user@backup-server:/path/to/repo Encryption Modes
BorgBackup offers several encryption modes:
repokey (Recommended):
- Key stored in repository
- Passphrase protects the key
- Easy to use, good security
borg init --encryption=repokey /path/to/repo keyfile:
- Key stored in ~/.config/borg/keys/
- More secure, requires key backup
- Good for critical data
borg init --encryption=keyfile /path/to/repo authenticated:
- No encryption, only authentication
- Fast, for already encrypted data
- Use with encrypted storage
borg init --encryption=authenticated /path/to/repo none:
- No encryption or authentication
- Fastest, for public/non-sensitive data
borg init --encryption=none /path/to/repo Export and Backup Repository Key
CRITICAL: Export your repository key!
# Export key
borg key export /path/to/repo backup-key.txt
# Store securely (offline, password manager, etc.)
# Without this key, you cannot recover your backups! Part 3: Creating Backups
Basic Backup Command
Create your first backup:
borg create /mnt/backup/borg-repo::backup-2025-12-17 /home /etc /var/lib/docker/volumes The ::backup-2025-12-17 part is the archive name. Each backup is an archive.
Backup with Progress and Statistics
borg create --progress --stats /mnt/backup/borg-repo::backup-$(date +%Y-%m-%d) /home /etc /var/lib/docker/volumes Compression Options
BorgBackup supports multiple compression algorithms:
lz4 (Fast, recommended for most cases):
borg create --compression lz4 /mnt/backup/borg-repo::backup-$(date +%Y-%m-%d) /home zstd (Excellent balance of speed and ratio):
borg create --compression zstd,3 /mnt/backup/borg-repo::backup-$(date +%Y-%m-%d) /home zlib (Better compression, slower):
borg create --compression zlib,6 /mnt/backup/borg-repo::backup-$(date +%Y-%m-%d) /home auto (Automatic selection):
borg create --compression auto,lz4 /mnt/backup/borg-repo::backup-$(date +%Y-%m-%d) /home Exclusion Patterns
Exclude files and directories:
borg create /mnt/backup/borg-repo::backup-$(date +%Y-%m-%d) /home --exclude '*/node_modules/*' --exclude '*.tmp' --exclude '*/.cache/*' --exclude '*/Downloads/*' Use an exclude file:
# Create /root/.borg-exclude
cat > /root/.borg-exclude << 'EOF'
*.log
*.tmp
*~
.DS_Store
.cache/
node_modules/
__pycache__/
*.pyc
.git/
*.iso
*.img
thumbs.db
Thumbs.db
EOF
# Use in backup
borg create /mnt/backup/borg-repo::backup-$(date +%Y-%m-%d) /home --exclude-from /root/.borg-exclude Archive Naming Conventions
Use consistent, informative archive names:
# Date-based
borg create ::backup-$(date +%Y-%m-%d)
# Date and time
borg create ::backup-$(date +%Y-%m-%d-%H%M)
# Hostname and date
borg create ::$(hostname)-$(date +%Y-%m-%d)
# With tag
borg create ::daily-$(date +%Y-%m-%d) Part 4: Managing Archives
List Archives
View all archives in repository:
borg list /mnt/backup/borg-repo List files in specific archive:
borg list /mnt/backup/borg-repo::backup-2025-12-17 List with file details:
borg list --short /mnt/backup/borg-repo::backup-2025-12-17 Archive Information
Get archive statistics:
borg info /mnt/backup/borg-repo::backup-2025-12-17 Repository statistics:
borg info /mnt/backup/borg-repo Comparing Archives
Show differences between archives:
borg diff /mnt/backup/borg-repo::backup-2025-12-16 backup-2025-12-17 Part 5: Restoring Data
Extract Entire Archive
Restore complete archive:
# Extract to current directory
borg extract /mnt/backup/borg-repo::backup-2025-12-17
# Extract to specific location
mkdir /tmp/restore
cd /tmp/restore
borg extract /mnt/backup/borg-repo::backup-2025-12-17 Extract Specific Files
Restore specific paths:
borg extract /mnt/backup/borg-repo::backup-2025-12-17 home/user/important.txt etc/nginx/nginx.conf Use patterns:
borg extract /mnt/backup/borg-repo::backup-2025-12-17 --pattern '+home/user/*.conf' --pattern '-home/user/.cache' Mount Archive for Browsing
Mount repository as filesystem:
# Create mount point
mkdir /mnt/borg-mount
# Mount repository
borg mount /mnt/backup/borg-repo /mnt/borg-mount
# Browse archives
ls /mnt/borg-mount/
ls /mnt/borg-mount/backup-2025-12-17/home/user/
# Copy files
cp /mnt/borg-mount/backup-2025-12-17/home/user/important.txt /home/user/
# Unmount when done
borg umount /mnt/borg-mount Mount specific archive:
borg mount /mnt/backup/borg-repo::backup-2025-12-17 /mnt/borg-mount Part 6: Pruning and Retention
Prune Old Archives
BorgBackup’s prune command removes old archives based on retention rules:
borg prune --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 3 /mnt/backup/borg-repo More retention options:
borg prune --keep-last 5 --keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --keep-yearly 3 /mnt/backup/borg-repo Dry run to see what would be deleted:
borg prune --dry-run --list --keep-daily 7 --keep-weekly 4 /mnt/backup/borg-repo Compact Repository
After pruning, compact to reclaim space:
borg compact /mnt/backup/borg-repo Combined prune and compact:
borg prune --keep-daily 7 --keep-weekly 4 --keep-monthly 12 /mnt/backup/borg-repo
borg compact /mnt/backup/borg-repo Part 7: Repository Maintenance
Check Repository Integrity
Basic integrity check:
borg check /mnt/backup/borg-repo Verify all data:
borg check --verify-data /mnt/backup/borg-repo Check specific archives:
borg check --verify-data /mnt/backup/borg-repo::backup-2025-12-17 Repair Corrupted Repository
If corruption is detected:
borg check --repair /mnt/backup/borg-repo Part 8: Installing Borgmatic
Borgmatic provides declarative configuration and automation for BorgBackup.
Install Borgmatic
Via pip (recommended):
sudo apt install python3-pip -y
sudo pip3 install --upgrade borgmatic Via distribution packages:
sudo apt install borgmatic -y Verify installation:
borgmatic --version Generate Configuration
Create initial configuration:
sudo mkdir -p /etc/borgmatic
sudo generate-borgmatic-config This creates /etc/borgmatic/config.yaml.
Part 9: Configuring Borgmatic
Basic Configuration
Edit /etc/borgmatic/config.yaml:
# Location of Borg repositories
repositories:
- /mnt/backup/borg-repo
# Paths to backup
source_directories:
- /home
- /etc
- /var/lib/docker/volumes
- /opt
# Paths to exclude
exclude_patterns:
- '*.tmp'
- '*.log'
- '*/.cache/*'
- '*/node_modules/*'
- '*/__pycache__/*'
- '*.pyc'
- '.git/'
# Repository storage options
storage:
compression: auto,lz4
archive_name_format: '{hostname}-{now:%Y-%m-%d-%H%M%S}'
# Retention policy
retention:
keep_hourly: 24
keep_daily: 7
keep_weekly: 4
keep_monthly: 12
keep_yearly: 3
# Consistency checks
consistency:
checks:
- name: repository
frequency: 2 weeks
- name: archives
frequency: 1 month
# Hooks for notifications
hooks:
before_backup:
- echo "Starting backup at $(date)"
after_backup:
- echo "Backup completed at $(date)"
on_error:
- echo "Backup failed at $(date)" Advanced Configuration
Enhanced configuration with multiple repositories and features:
repositories:
- path: /mnt/backup/borg-repo
label: local
- path: ssh://backup-user@backup-server/~/borg-repo
label: offsite
source_directories:
- /home
- /etc
- /var/lib/docker/volumes
- /opt
- /root
exclude_patterns:
- '*.tmp'
- '*.log'
- '*/.cache/*'
- '*/node_modules/*'
- '*/__pycache__/*'
- '*.pyc'
- '.git/'
- '/home/*/.local/share/Trash'
- '/home/*/Downloads'
exclude_if_present:
- .nobackup
storage:
compression: auto,zstd,3
archive_name_format: '{hostname}-{now:%Y-%m-%d-%H%M%S}'
checkpoint_interval: 1800
encryption_passphrase: "your-encryption-password"
ssh_command: ssh -i /root/.ssh/backup_key
retention:
keep_within: 3H
keep_hourly: 24
keep_daily: 7
keep_weekly: 4
keep_monthly: 12
keep_yearly: 3
prefix: '{hostname}-'
consistency:
checks:
- name: repository
frequency: 2 weeks
- name: archives
frequency: 1 month
- name: data
frequency: 6 months
hooks:
before_backup:
- echo "Starting backup at $(date)" >> /var/log/borgmatic.log
- curl -fsS -m 10 --retry 5 https://hc-ping.com/YOUR-UUID/start > /dev/null
after_backup:
- echo "Backup completed at $(date)" >> /var/log/borgmatic.log
- curl -fsS -m 10 --retry 5 https://hc-ping.com/YOUR-UUID > /dev/null
on_error:
- echo "Backup FAILED at $(date)" >> /var/log/borgmatic.log
- curl -fsS -m 10 --retry 5 https://hc-ping.com/YOUR-UUID/fail > /dev/null
- 'echo "Backup failed on $(hostname)" | mail -s "Backup Failed" [email protected]'
postgresql_databases:
- name: all
mysql_databases:
- name: all Environment Variables for Credentials
Store sensitive data securely:
# Create environment file
sudo nano /etc/borgmatic/environment
# Add variables
export BORG_PASSPHRASE="your-encryption-password"
export BORG_RSH="ssh -i /root/.ssh/backup_key" Update systemd service to load environment:
sudo systemctl edit borgmatic.timer Add:
[Service]
EnvironmentFile=/etc/borgmatic/environment Part 10: Running Borgmatic
Manual Execution
Run backup manually:
sudo borgmatic With verbose output:
sudo borgmatic --verbosity 1 List archives:
sudo borgmatic list Show repository info:
sudo borgmatic info Validate Configuration
Check configuration file:
sudo borgmatic config validate Extract with Borgmatic
Extract entire archive:
sudo borgmatic extract --archive latest Extract to specific directory:
sudo borgmatic extract --archive latest --destination /tmp/restore Extract specific paths:
sudo borgmatic extract --archive latest --path home/user/important.txt Part 11: Automation with Systemd
Borgmatic includes systemd timer by default.
Enable Systemd Timer
sudo systemctl enable --now borgmatic.timer
sudo systemctl list-timers borgmatic View timer status:
sudo systemctl status borgmatic.timer Customize Timer Schedule
Edit timer:
sudo systemctl edit borgmatic.timer Change schedule:
[Timer]
OnCalendar=
OnCalendar=daily
OnCalendar=*-*-* 02:00:00
RandomizedDelaySec=30min
Persistent=true Reload systemd:
sudo systemctl daemon-reload
sudo systemctl restart borgmatic.timer Monitor Execution
View logs:
sudo journalctl -u borgmatic.service -f Check last run:
sudo systemctl status borgmatic.service Part 12: Database Backups
PostgreSQL Integration
Borgmatic can automatically backup PostgreSQL databases:
hooks:
postgresql_databases:
- name: myapp
hostname: localhost
port: 5432
username: postgres
password: your-password
- name: all
hostname: localhost Create .pgpass for authentication:
echo "localhost:5432:*:postgres:your-password" > /root/.pgpass
chmod 600 /root/.pgpass MySQL/MariaDB Integration
hooks:
mysql_databases:
- name: wordpress
hostname: localhost
port: 3306
username: root
password: your-password
- name: all
hostname: localhost
username: root
options: --single-transaction Create .my.cnf for credentials:
sudo nano /root/.my.cnf [client]
user=root
password=your-password sudo chmod 600 /root/.my.cnf Docker Volume Backups
Stop containers before backup:
hooks:
before_backup:
- docker stop nginx
- docker stop database
after_backup:
- docker start database
- docker start nginx Part 13: Monitoring and Notifications
Healthchecks.io Integration
Add to borgmatic configuration:
hooks:
before_backup:
- curl -fsS -m 10 --retry 5 https://hc-ping.com/YOUR-UUID/start > /dev/null
after_backup:
- curl -fsS -m 10 --retry 5 https://hc-ping.com/YOUR-UUID > /dev/null
on_error:
- curl -fsS -m 10 --retry 5 https://hc-ping.com/YOUR-UUID/fail > /dev/null Email Notifications
Install mail utilities:
sudo apt install mailutils -y Configure in borgmatic:
hooks:
on_error:
- 'echo "Backup failed on $(hostname) at $(date)" | mail -s "❌ Backup Failed: $(hostname)" [email protected]'
after_backup:
- 'echo "Backup completed successfully on $(hostname) at $(date)" | mail -s "✅ Backup Success: $(hostname)" [email protected]' Ntfy.sh Push Notifications
hooks:
after_backup:
- 'curl -d "Backup completed on $(hostname)" ntfy.sh/your-topic'
on_error:
- 'curl -H "Priority: high" -d "Backup FAILED on $(hostname)" ntfy.sh/your-topic' Custom Monitoring Script
Create /usr/local/bin/borgmatic-monitor.sh:
#!/bin/bash
HOSTNAME=$(hostname)
LOGFILE="/var/log/borgmatic-monitor.log"
HEALTHCHECK_URL="https://hc-ping.com/YOUR-UUID"
EMAIL="[email protected]"
# Start signal
curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL/start" > /dev/null
# Run borgmatic
if borgmatic --verbosity 1 >> "$LOGFILE" 2>&1; then
echo "$(date): Backup completed successfully" >> "$LOGFILE"
curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL" > /dev/null
echo "Backup completed on $HOSTNAME at $(date)" | mail -s "✅ Backup Success: $HOSTNAME" "$EMAIL"
else
echo "$(date): Backup FAILED" >> "$LOGFILE"
curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL/fail" > /dev/null
echo "Backup FAILED on $HOSTNAME at $(date). Check $LOGFILE" | mail -s "❌ Backup Failed: $HOSTNAME" "$EMAIL"
fi Part 14: Remote Repository Setup
SSH Server Configuration
On backup server, install BorgBackup:
sudo apt install borgbackup -y Create backup user:
sudo useradd -m -s /bin/bash borgbackup
sudo mkdir -p /home/borgbackup/.ssh Add client SSH key:
# On client, copy public key
cat ~/.ssh/id_ed25519.pub
# On server, add to authorized_keys
sudo nano /home/borgbackup/.ssh/authorized_keys
# Paste public key
sudo chown -R borgbackup:borgbackup /home/borgbackup/.ssh
sudo chmod 700 /home/borgbackup/.ssh
sudo chmod 600 /home/borgbackup/.ssh/authorized_keys Create repository directory:
sudo mkdir -p /backup/repos
sudo chown borgbackup:borgbackup /backup/repos Restrict SSH Command
For security, restrict SSH access to Borg only:
Edit /home/borgbackup/.ssh/authorized_keys:
command="borg serve --restrict-to-path /backup/repos",restrict ssh-ed25519 AAAA... user@client Initialize Remote Repository
From client:
borg init --encryption=repokey borgbackup@backup-server:/backup/repos/client-hostname Part 15: Advanced Features
Append-Only Mode
Protect against ransomware by enabling append-only:
On server:
borg init --encryption=repokey --append-only /backup/repos/client-hostname Or configure in SSH authorized_keys:
command="borg serve --restrict-to-path /backup/repos --append-only" Quota Management
Limit repository size:
On server, configure quota in SSH command:
command="borg serve --restrict-to-path /backup/repos --storage-quota 500G" Using Borg with Multiple Machines
Create separate repository for each machine:
# Machine 1
borg init --encryption=repokey /mnt/backup/borg-repo/server1
# Machine 2
borg init --encryption=repokey /mnt/backup/borg-repo/server2 Or use single repository with hostname prefixes:
# borgmatic config
storage:
archive_name_format: '{hostname}-{now:%Y-%m-%d-%H%M%S}' Part 16: Security Best Practices
Encryption
- Use repokey or keyfile: Always encrypt your backups
- Strong passphrases: Use 20+ character random passphrases
- Export and backup keys: Store repository keys offline
- Separate credentials: Different passphrases per repository
Access Control
- SSH key-based auth: Never use password authentication
- Restrict SSH commands: Use
borg servewith restrictions - Append-only mode: Prevent deletion by compromised clients
- User separation: Dedicated backup user with minimal permissions
Network Security
- SSH only: Never expose Borg over HTTP
- Firewall rules: Restrict SSH access to backup clients
- VPN/Tailscale: Additional network isolation
- Key management: Rotate SSH keys periodically
Verification
Create verification script /usr/local/bin/borg-verify.sh:
#!/bin/bash
REPO="/mnt/backup/borg-repo"
export BORG_PASSPHRASE="your-passphrase"
# Check repository
echo "Checking repository integrity..."
borg check "$REPO"
# Verify random archive
ARCHIVE=$(borg list "$REPO" --short | shuf -n 1)
echo "Verifying archive: $ARCHIVE"
borg check --verify-data "$REPO::$ARCHIVE"
# Test extract
echo "Testing extraction..."
mkdir -p /tmp/borg-test
borg extract "$REPO::$ARCHIVE" etc/hostname --destination /tmp/borg-test
if [ -f /tmp/borg-test/etc/hostname ]; then
echo "✅ Verification successful"
rm -rf /tmp/borg-test
exit 0
else
echo "❌ Verification failed"
exit 1
fi Part 17: Performance Tuning
Optimize Compression
Test different compression algorithms:
# Fast backup (lz4)
borg create --compression lz4 ::test-lz4 /home
# Balanced (zstd)
borg create --compression zstd,3 ::test-zstd /home
# Maximum compression (zlib)
borg create --compression zlib,9 ::test-zlib /home
# Compare sizes
borg info ::test-lz4
borg info ::test-zstd
borg info ::test-zlib Checkpoint Intervals
For large backups, use checkpoints:
borg create --checkpoint-interval 1800 ::backup-large /home Or in borgmatic:
storage:
checkpoint_interval: 1800 Upload Buffer
Increase upload buffer for better performance:
export BORG_FILES_CACHE_TTL=20
export BORG_UPLOAD_BUFFER=20M Part 18: Troubleshooting
Common Issues
Lock timeout:
# List locks
borg list locks /mnt/backup/borg-repo
# Break lock (if safe)
borg break-lock /mnt/backup/borg-repo Repository integrity errors:
# Check repository
borg check /mnt/backup/borg-repo
# Repair if needed
borg check --repair /mnt/backup/borg-repo Out of space:
# Check space usage
borg info /mnt/backup/borg-repo
# Aggressive pruning
borg prune --keep-last 3 /mnt/backup/borg-repo
borg compact /mnt/backup/borg-repo Slow backups:
# Check what's being backed up
borg create --dry-run --list ::test /home
# Exclude large files
borg create --exclude '*.iso' --exclude '*.img' ::backup /home Debug Mode
Enable debug output:
borg create --debug --show-rc ::debug-backup /home Check borgmatic in debug mode:
borgmatic --verbosity 2 Conclusion
You now have a complete BorgBackup solution with Borgmatic automation. This setup provides:
- Highly efficient deduplicated backups
- Strong encryption and security
- Automated scheduled backups
- Database integration
- Monitoring and notifications
- Remote and local repository support
- Easy restore procedures
Next Steps
- Test your backups: Regular restore tests are critical
- Monitor backup status: Set up health checks and alerts
- Document recovery procedures: Write down exact restore steps
- Export repository keys: Store them securely offline
- Plan for growth: Monitor repository size and adjust retention
Additional Resources
Remember: Backups without tested restores are just expensive hopes. Test your restore procedures regularly!