Backup with BorgBackup: Complete Deduplication and Encryption Guide
Introduction
BorgBackup (short for Borg) is a modern, sophisticated backup solution that revolutionizes how Linux systems handle data protection through advanced deduplication, compression, and authenticated encryption. Unlike traditional backup tools that store complete file copies for each backup interval, Borg splits data into content-defined chunks and stores each unique chunk only once across all backups. This approach, combined with efficient compression and strong encryption, makes Borg exceptionally space-efficient while maintaining security and performance.
Developed with lessons learned from earlier deduplication backup tools, BorgBackup has become the gold standard for efficient, secure backups in environments ranging from single-server deployments to large-scale infrastructure. Organizations managing terabytes of data with daily backup requirements have achieved storage reduction ratios exceeding 50:1 through Borg's deduplication capabilities, dramatically reducing storage costs while maintaining comprehensive backup histories.
This comprehensive guide explores BorgBackup from fundamental concepts through production deployment, covering installation, repository management, backup automation, deduplication mechanisms, encryption strategies, remote backups, restoration procedures, and real-world implementation scenarios aligned with the 3-2-1 backup rule.
Understanding BorgBackup Architecture
How BorgBackup Works
BorgBackup implements a sophisticated multi-layered architecture:
Content-defined chunking: Instead of backing up entire files, Borg splits data into variable-sized chunks (typically 1-4MB) using a rolling hash algorithm. This ensures that inserting data at the beginning of a file doesn't affect chunk boundaries of the remaining content.
Global deduplication: Borg maintains a global chunk index across all backups. When creating new backups, Borg checks if each chunk already exists in the repository. Only new, unique chunks are stored, regardless of whether identical data appears in different files, directories, or backup archives.
Compression: Each chunk is individually compressed before storage, using algorithms like LZ4 (fast), zstd (balanced), or zlib (high compression). This provides additional space savings beyond deduplication.
Authenticated encryption: All data is encrypted client-side before transmission to the repository. Borg supports multiple encryption modes including authenticated encryption with AES-256-CTR + HMAC-SHA256, ensuring both confidentiality and integrity.
Repository structure: Backups are stored as "archives" within a "repository". Each archive represents a point-in-time backup, but all archives within a repository share the same deduplicated chunk pool.
BorgBackup vs Traditional Backup Solutions
BorgBackup vs rsync/rsnapshot:
- Rsync/rsnapshot: File-level deduplication via hard links
- Borg: Block-level deduplication across all data
- Rsync/rsnapshot: Human-readable directory structures
- Borg: Encrypted, deduplicated repository format
- Rsync/rsnapshot: No built-in encryption
- Borg: Mandatory encryption with authenticated modes
BorgBackup vs traditional tar backups:
- Tar: Each backup is a separate archive, full file copies
- Borg: Global deduplication pool, chunk-level storage
- Tar: Optional compression per archive
- Borg: Per-chunk compression with multiple algorithms
- Tar: Unencrypted by default
- Borg: Encrypted by default
BorgBackup vs cloud backup services:
- Cloud services: Often proprietary, vendor lock-in
- Borg: Open source, format documentation available
- Cloud services: Variable pricing, data egress fees
- Borg: Use any storage backend (local, SSH, S3-compatible)
- Cloud services: Encryption keys may be managed by provider
- Borg: Client-side encryption, you control keys
Key Features and Benefits
Space efficiency: Deduplication ratios of 10:1 to 50:1 or higher depending on data redundancy and backup frequency.
Performance: Incremental backups are extremely fast as only new/changed chunks are processed and stored.
Security: Authenticated encryption protects against both unauthorized access and tampering.
Compression: Multiple compression algorithms with varying speed/ratio trade-offs.
Integrity verification: Built-in consistency checking detects corruption.
Mount capability: Mount any archive as read-only filesystem for browsing and selective restoration.
Pruning: Flexible retention policies automatically remove old backups while preserving deduplicated chunks still referenced by retained archives.
Cross-platform: Works on Linux, macOS, BSD, Windows (via WSL).
Installation
Installing BorgBackup
BorgBackup is available through standard package managers:
Ubuntu/Debian:
# Update package lists
sudo apt update
# Install BorgBackup
sudo apt install borgbackup
# Verify installation
borg --version
CentOS/Rocky Linux/RHEL:
# Enable EPEL repository
sudo dnf install epel-release
# Install BorgBackup
sudo dnf install borgbackup
# Verify installation
borg --version
Install from binary (latest version):
# Download latest binary
cd /tmp
wget https://github.com/borgbackup/borg/releases/download/1.2.7/borg-linux64
chmod +x borg-linux64
# Move to system path
sudo mv borg-linux64 /usr/local/bin/borg
# Verify
borg --version
Expected output:
borg 1.2.x
Installing BorgBackup from Source
For the latest features or custom builds:
# Install build dependencies (Ubuntu/Debian)
sudo apt install python3-dev python3-pip python3-virtualenv \
libacl1-dev libssl-dev liblz4-dev libzstd-dev pkg-config
# Create virtual environment
python3 -m venv ~/borg-env
source ~/borg-env/bin/activate
# Install via pip
pip install borgbackup
# Verify
borg --version
Repository Initialization
Creating Your First Repository
A Borg repository is the container for all your backup archives:
Local repository:
# Create repository directory
mkdir -p /backup/borg-repo
# Initialize repository with encryption
borg init --encryption=repokey /backup/borg-repo
Remote repository via SSH:
# Initialize on remote server
borg init --encryption=repokey user@backup-server:/backup/borg-repo
Initialize with passphrase:
# Borg will prompt for passphrase
borg init --encryption=repokey /backup/borg-repo
# Enter new passphrase:
# Enter same passphrase again:
# Repository created successfully
Understanding Encryption Modes
BorgBackup offers several encryption modes with different security/convenience trade-offs:
repokey (recommended for most users):
- Encryption key stored in repository
- Protected by passphrase
- Repository can be cloned/moved easily
- Easier disaster recovery
keyfile:
- Encryption key stored in
~/.config/borg/keys/ - More secure (attacker needs both repo and keyfile)
- Must backup keyfile separately
- More complex disaster recovery
repokey-blake2 / keyfile-blake2:
- Same as above but using BLAKE2b instead of SHA-256
- Faster on modern CPUs
authenticated:
- No encryption, only authentication
- Detects tampering but data is readable
- Use only for non-sensitive data
none:
- No encryption or authentication
- Not recommended except for testing
Example with specific mode:
# Recommended: repokey mode
borg init --encryption=repokey /backup/borg-repo
# High security: keyfile mode
borg init --encryption=keyfile /backup/borg-repo
# Performance optimized
borg init --encryption=repokey-blake2 /backup/borg-repo
Key Management
Export encryption key (critical for disaster recovery):
# Export key to file
borg key export /backup/borg-repo /secure/location/borg-key-backup.txt
# Store passphrase securely
# Use password manager, encrypted file, or physical safe
Import key (during recovery):
# Import previously exported key
borg key import /backup/borg-repo /secure/location/borg-key-backup.txt
Change passphrase:
# Change repository passphrase
borg key change-passphrase /backup/borg-repo
Environment Variables for Automation
Set up environment variables for automated backups:
# Add to backup script or .bashrc
export BORG_REPO='/backup/borg-repo'
export BORG_PASSPHRASE='your-secure-passphrase'
# For remote repositories
export BORG_REPO='user@backup-server:/backup/borg-repo'
export BORG_RSH='ssh -i /root/.ssh/borg-backup-key'
Security warning: Storing passphrases in plain text reduces security. Consider:
- Using SSH agent for remote backups
- Storing passphrase in encrypted file
- Using systemd credentials or HashiCorp Vault
Creating Backups
Basic Backup Creation
Create your first backup archive:
# Create backup archive
borg create \
/backup/borg-repo::backup-2026-01-11 \
/home \
/etc \
/var/www
# Syntax: borg create REPOSITORY::ARCHIVE-NAME SOURCE [SOURCE...]
With timestamp:
# Use date in archive name
borg create \
/backup/borg-repo::backup-$(date +%Y%m%d-%H%M%S) \
/home /etc /var/www
Verbose output:
# Show detailed progress
borg create --progress --stats \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/home /etc /var/www
Output example:
Creating archive at "/backup/borg-repo::backup-20260111"
------------------------------------------------------------------------------
Archive name: backup-20260111
Archive fingerprint: abc123def456
Time (start): Sat, 2026-01-11 14:30:00
Time (end): Sat, 2026-01-11 14:35:42
Duration: 5 minutes 42.18 seconds
Number of files: 45231
------------------------------------------------------------------------------
Original size Compressed size Deduplicated size
This archive: 5.23 GB 3.87 GB 156.32 MB
All archives: 15.69 GB 11.61 GB 3.21 GB
------------------------------------------------------------------------------
Excluding Files and Directories
Optimize backups by excluding unnecessary data:
Using --exclude patterns:
borg create \
--exclude '*.tmp' \
--exclude '*.log' \
--exclude 'cache/' \
--exclude 'node_modules/' \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/home /var/www
Using exclude file:
Create /etc/borg/exclude-patterns.txt:
# Temporary files
*.tmp
*.swp
*.bak
~*
# Caches
.cache/
__pycache__/
*.pyc
node_modules/
vendor/
# Logs
*.log
/var/log/
# System directories
/proc/
/sys/
/dev/
/run/
/tmp/
# Build artifacts
*.o
*.so
.git/
Use in backup command:
borg create \
--exclude-from /etc/borg/exclude-patterns.txt \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/
Compression Options
Borg supports multiple compression algorithms:
No compression (fastest):
borg create --compression none \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/home
LZ4 (very fast, moderate compression):
borg create --compression lz4 \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/home
Zstd (balanced, recommended):
# Default level (3)
borg create --compression zstd \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/home
# Custom level (1-22, higher = better compression, slower)
borg create --compression zstd,10 \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/home
Zlib (high compression, slower):
# Level 0-9
borg create --compression zlib,9 \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/home
Adaptive compression (auto-detect compressibility):
borg create --compression auto,zstd,10 \
/backup/borg-repo::backup-$(date +%Y%m%d) \
/home
Production Backup Script
Comprehensive script for production environments:
#!/bin/bash
# /usr/local/bin/borg-backup.sh
set -e
# Configuration
export BORG_REPO='/backup/borg-repo'
export BORG_PASSPHRASE='your-secure-passphrase'
BACKUP_NAME="backup-$(date +%Y%m%d-%H%M%S)"
LOG_FILE="/var/log/borg-backup.log"
ADMIN_EMAIL="[email protected]"
# Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
# Error handler
error_exit() {
log "ERROR: $1"
echo "Borg backup failed: $1" | mail -s "Backup FAILED - $(hostname)" "$ADMIN_EMAIL"
exit 1
}
log "Starting Borg backup: $BACKUP_NAME"
# Pre-backup: Database dumps
log "Creating database dumps..."
mysqldump --all-databases --single-transaction | gzip > /var/backups/mysql-all.sql.gz || \
error_exit "MySQL dump failed"
# Create backup
log "Creating Borg archive..."
borg create \
--verbose \
--stats \
--progress \
--compression zstd,6 \
--exclude-from /etc/borg/exclude-patterns.txt \
"::$BACKUP_NAME" \
/home \
/etc \
/var/www \
/var/backups \
/opt \
/root 2>&1 | tee -a "$LOG_FILE"
if [ ${PIPESTATUS[0]} -ne 0 ]; then
error_exit "Borg create failed"
fi
# Prune old backups
log "Pruning old archives..."
borg prune \
--verbose \
--list \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=12 \
2>&1 | tee -a "$LOG_FILE"
if [ ${PIPESTATUS[0]} -ne 0 ]; then
error_exit "Borg prune failed"
fi
# Compact repository (free space from pruned archives)
log "Compacting repository..."
borg compact 2>&1 | tee -a "$LOG_FILE"
# Verify integrity (periodic check)
DAY_OF_MONTH=$(date +%d)
if [ "$DAY_OF_MONTH" == "01" ]; then
log "Running monthly integrity check..."
borg check --verify-data 2>&1 | tee -a "$LOG_FILE"
fi
log "Backup completed successfully: $BACKUP_NAME"
# Send success notification
echo "Backup completed successfully at $(date)" | \
mail -s "Backup SUCCESS - $(hostname)" "$ADMIN_EMAIL"
exit 0
Make executable:
sudo chmod +x /usr/local/bin/borg-backup.sh
Managing Archives and Retention
Listing Archives
View all backups in repository:
# List all archives
borg list /backup/borg-repo
# Output:
# backup-20260105-020000 Sat, 2026-01-05 02:00:00
# backup-20260106-020000 Sun, 2026-01-06 02:00:00
# backup-20260107-020000 Mon, 2026-01-07 02:00:00
List files in specific archive:
# List all files
borg list /backup/borg-repo::backup-20260111
# List specific directory
borg list /backup/borg-repo::backup-20260111 | grep '/etc/'
# List with details
borg list --short /backup/borg-repo::backup-20260111 /home/user/
Repository Information
Get repository statistics:
# Repository info
borg info /backup/borg-repo
# Output:
# Repository ID: abc123...
# Location: /backup/borg-repo
# Encrypted: Yes (repokey)
# Cache: /root/.cache/borg/abc123
# Security dir: /root/.config/borg/security/abc123
# Original size Compressed size Deduplicated size
# All archives: 150.23 GB 95.87 GB 12.34 GB
Archive-specific info:
# Info for specific archive
borg info /backup/borg-repo::backup-20260111
Pruning Archives
Implement retention policies automatically:
Prune command syntax:
borg prune \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=12 \
--keep-yearly=2 \
/backup/borg-repo
Retention options:
--keep-hourly=N: Keep N hourly backups--keep-daily=N: Keep N daily backups--keep-weekly=N: Keep N weekly backups (last backup of each week)--keep-monthly=N: Keep N monthly backups (last backup of each month)--keep-yearly=N: Keep N yearly backups (last backup of each year)
Example: GFS rotation:
borg prune \
--list \
--show-rc \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=6 \
--keep-yearly=2 \
/backup/borg-repo
Dry-run before actual pruning:
# Test pruning without deleting
borg prune \
--dry-run \
--list \
--keep-daily=7 \
--keep-weekly=4 \
/backup/borg-repo
Compacting Repository
After pruning, reclaim space:
# Compact repository (Borg 1.2+)
borg compact /backup/borg-repo
# Older versions: use
borg prune --keep-daily=7 /backup/borg-repo
# Space is automatically reclaimed
Deleting Specific Archives
Remove individual archives:
# Delete specific archive
borg delete /backup/borg-repo::backup-20260105
# Delete multiple archives
borg delete \
/backup/borg-repo::backup-20260105 \
/backup/borg-repo::backup-20260106
# Delete entire repository (DANGEROUS!)
borg delete /backup/borg-repo
Restoration Procedures
Mounting Archives
Mount backup as read-only filesystem for browsing:
# Create mount point
mkdir -p /mnt/borg-mount
# Mount latest archive
LATEST=$(borg list /backup/borg-repo | tail -1 | cut -d' ' -f1)
borg mount /backup/borg-repo::$LATEST /mnt/borg-mount
# Browse backup
ls -la /mnt/borg-mount/home/user/
# Unmount when done
borg umount /mnt/borg-mount
Mount all archives:
# Mount entire repository (all archives)
borg mount /backup/borg-repo /mnt/borg-mount
# Each archive appears as subdirectory
ls /mnt/borg-mount/
# backup-20260105-020000/
# backup-20260106-020000/
# backup-20260111-020000/
# Browse specific archive
ls /mnt/borg-mount/backup-20260111-020000/home/
# Unmount
borg umount /mnt/borg-mount
Extracting Files
Restore files from archives:
Extract entire archive:
# Extract to current directory
borg extract /backup/borg-repo::backup-20260111
# Extract to specific location
cd /restore-location
borg extract /backup/borg-repo::backup-20260111
Extract specific files/directories:
# Extract single file
borg extract /backup/borg-repo::backup-20260111 home/user/document.txt
# Extract directory
borg extract /backup/borg-repo::backup-20260111 etc/
# Extract multiple paths
borg extract /backup/borg-repo::backup-20260111 \
home/user/ \
etc/nginx/ \
var/www/
Extract with different paths:
# Strip leading path components
borg extract --strip-components=2 \
/backup/borg-repo::backup-20260111 \
home/user/documents/
# Results in: documents/ in current directory
Complete System Restoration
Restore entire system after disaster:
# Boot from live USB/rescue system
# Partition and format disks
parted /dev/sda mklabel gpt
parted /dev/sda mkpart primary ext4 1MiB 100%
mkfs.ext4 /dev/sda1
# Mount target filesystem
mount /dev/sda1 /mnt/target
# Initialize Borg (import key if needed)
export BORG_REPO='user@backup-server:/backup/borg-repo'
export BORG_PASSPHRASE='your-passphrase'
# Extract latest backup
cd /mnt/target
LATEST=$(borg list $BORG_REPO | tail -1 | cut -d' ' -f1)
borg extract "::$LATEST"
# Reinstall bootloader
mount --bind /dev /mnt/target/dev
mount --bind /proc /mnt/target/proc
mount --bind /sys /mnt/target/sys
chroot /mnt/target
grub-install /dev/sda
update-grub
exit
# Unmount and reboot
umount /mnt/target/dev /mnt/target/proc /mnt/target/sys
umount /mnt/target
reboot
Remote Backups
SSH-Based Remote Repositories
Backup to remote server over SSH:
Setup SSH authentication:
# Generate SSH key
ssh-keygen -t ed25519 -f ~/.ssh/borg-backup-key -N ""
# Copy to remote server
ssh-copy-id -i ~/.ssh/borg-backup-key.pub user@backup-server
# Test connection
ssh -i ~/.ssh/borg-backup-key user@backup-server "echo SSH OK"
Initialize remote repository:
export BORG_RSH='ssh -i ~/.ssh/borg-backup-key'
borg init --encryption=repokey user@backup-server:/backup/borg-repo
Create remote backup:
borg create \
--compression zstd,6 \
--exclude-from /etc/borg/exclude-patterns.txt \
user@backup-server:/backup/borg-repo::backup-$(date +%Y%m%d) \
/home /etc /var/www
Remote backup script:
#!/bin/bash
# /usr/local/bin/borg-remote-backup.sh
export BORG_REPO='user@backup-server:/backup/borg-repo'
export BORG_PASSPHRASE='your-secure-passphrase'
export BORG_RSH='ssh -i /root/.ssh/borg-backup-key'
borg create \
--compression zstd,6 \
--exclude-from /etc/borg/exclude-patterns.txt \
"::backup-$(hostname)-$(date +%Y%m%d-%H%M%S)" \
/home /etc /var/www /opt
borg prune \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=12
Append-Only Repositories
Protect against ransomware by preventing deletion:
Initialize append-only repository:
# On backup server, create repository
borg init --encryption=repokey /backup/borg-repo
# Configure as append-only
borg config /backup/borg-repo append_only 1
Restrict SSH access (on backup server):
Edit ~/.ssh/authorized_keys:
command="borg serve --append-only --restrict-to-path /backup/borg-repo",restrict ssh-ed25519 AAAA...
This allows clients to:
- Create new archives
- List archives
- Extract archives
But prevents:
- Deleting archives
- Modifying existing archives
- Pruning
Pruning append-only repos (server-side only):
# On backup server (manual or scheduled)
borg prune --keep-daily=7 --keep-weekly=4 /backup/borg-repo
Automation and Scheduling
Systemd Timer Implementation
Create service file (/etc/systemd/system/borg-backup.service):
[Unit]
Description=BorgBackup Service
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/borg-backup.sh
User=root
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
# Security hardening
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/backup /var/log /var/backups
# Timeout after 6 hours
TimeoutSec=21600
[Install]
WantedBy=multi-user.target
Create timer file (/etc/systemd/system/borg-backup.timer):
[Unit]
Description=BorgBackup Daily Timer
Requires=borg-backup.service
[Timer]
OnCalendar=daily
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=30min
[Install]
WantedBy=timers.target
Enable timer:
sudo systemctl daemon-reload
sudo systemctl enable --now borg-backup.timer
sudo systemctl list-timers borg-backup.timer
Cron-Based Scheduling
Alternative cron setup:
# Edit root crontab
sudo crontab -e
# Daily backup at 2 AM
0 2 * * * /usr/local/bin/borg-backup.sh >> /var/log/borg-cron.log 2>&1
Monitoring and Verification
Integrity Checking
Regular integrity verification:
# Quick check (metadata only)
borg check /backup/borg-repo
# Full check (verify data)
borg check --verify-data /backup/borg-repo
# Check specific archive
borg check /backup/borg-repo::backup-20260111
Automated monthly verification:
#!/bin/bash
# /usr/local/bin/borg-verify.sh
export BORG_REPO='/backup/borg-repo'
export BORG_PASSPHRASE='your-passphrase'
# Full verification
borg check --verify-data 2>&1 | tee /var/log/borg-verify.log
if [ ${PIPESTATUS[0]} -eq 0 ]; then
echo "Repository verification successful" | \
mail -s "Borg Verification OK" [email protected]
else
echo "Repository verification FAILED" | \
mail -s "Borg Verification FAILED" [email protected]
fi
Schedule monthly:
# First day of month at 3 AM
0 3 1 * * /usr/local/bin/borg-verify.sh
Backup Monitoring Script
#!/bin/bash
# /usr/local/bin/monitor-borg-backup.sh
export BORG_REPO='/backup/borg-repo'
export BORG_PASSPHRASE='your-passphrase'
MAX_AGE_HOURS=26
ADMIN_EMAIL="[email protected]"
# Get latest archive
LATEST=$(borg list --short "$BORG_REPO" | tail -1)
if [ -z "$LATEST" ]; then
echo "ERROR: No archives found in repository" | \
mail -s "Borg Monitoring ALERT" "$ADMIN_EMAIL"
exit 1
fi
# Get archive creation time
ARCHIVE_TIME=$(borg info "::$LATEST" | grep "^Time" | grep "start" | awk '{print $4, $5, $6}')
ARCHIVE_EPOCH=$(date -d "$ARCHIVE_TIME" +%s 2>/dev/null || date -j -f "%Y-%m-%d %H:%M:%S" "$ARCHIVE_TIME" +%s)
CURRENT_EPOCH=$(date +%s)
AGE_HOURS=$(( (CURRENT_EPOCH - ARCHIVE_EPOCH) / 3600 ))
if [ $AGE_HOURS -gt $MAX_AGE_HOURS ]; then
echo "WARNING: Latest backup is $AGE_HOURS hours old (>$MAX_AGE_HOURS)" | \
mail -s "Borg Backup Age Alert" "$ADMIN_EMAIL"
exit 1
else
echo "OK: Latest backup ($LATEST) is $AGE_HOURS hours old"
exit 0
fi
Real-World Implementation Scenarios
Scenario 1: Workstation Personal Backup
Requirements:
- User home directory
- Configuration files
- Daily automated backups
- 30-day retention
Setup:
# Initialize repository
borg init --encryption=repokey ~/backups/borg-repo
# Create backup script
cat > ~/bin/borg-backup.sh << 'EOF'
#!/bin/bash
export BORG_REPO="$HOME/backups/borg-repo"
export BORG_PASSPHRASE="my-secure-passphrase"
borg create \
--compression zstd,6 \
--exclude-from "$HOME/.config/borg/exclude.txt" \
"::backup-$(date +%Y%m%d-%H%M%S)" \
"$HOME"
borg prune --keep-daily=30
EOF
chmod +x ~/bin/borg-backup.sh
# Create exclude file
cat > ~/.config/borg/exclude.txt << 'EOF'
.cache/
Downloads/
.local/share/Trash/
*.tmp
node_modules/
EOF
# Schedule with cron
crontab -e
# Add: 0 12 * * * ~/bin/borg-backup.sh
Scenario 2: Web Server Production Backup
Requirements:
- Multiple websites
- Database dumps
- Remote backup repository
- Monitoring and alerts
Implementation:
#!/bin/bash
# /usr/local/bin/borg-production-backup.sh
set -e
export BORG_REPO='[email protected]:/backups/web-server'
export BORG_PASSPHRASE='strong-production-passphrase'
export BORG_RSH='ssh -i /root/.ssh/borg-key'
LOG="/var/log/borg-production.log"
ADMIN="[email protected]"
log() {
echo "[$(date)] $*" | tee -a "$LOG"
}
# Pre-backup: database dumps
log "Creating database dumps"
mkdir -p /var/backups/db-dumps
mysqldump --all-databases --single-transaction \
| gzip > /var/backups/db-dumps/mysql-all.sql.gz
sudo -u postgres pg_dumpall \
| gzip > /var/backups/db-dumps/postgresql-all.sql.gz
# Create backup
log "Creating Borg archive"
borg create \
--compression zstd,8 \
--exclude-from /etc/borg/exclude.txt \
--stats \
"::backup-$(hostname)-$(date +%Y%m%d-%H%M%S)" \
/var/www \
/etc \
/var/backups/db-dumps \
/opt
# Prune old backups
log "Pruning old archives"
borg prune \
--keep-hourly=24 \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=12
# Verify
log "Verifying repository"
borg check --last 1
log "Backup completed successfully"
echo "Production backup completed" | mail -s "Backup Success" "$ADMIN"
Scenario 3: Multi-Server Centralized Backup
Requirements:
- 10 application servers
- Central backup server
- Individual repositories per server
- Consolidated monitoring
Central backup server setup:
# /backup/borg-repos/
# ├── server01/
# ├── server02/
# ├── server03/
# ...
Per-server backup script:
#!/bin/bash
# On each application server
HOSTNAME=$(hostname -s)
export BORG_REPO="backup-server:/backup/borg-repos/$HOSTNAME"
export BORG_PASSPHRASE="passphrase-for-$HOSTNAME"
export BORG_RSH='ssh -i /root/.ssh/borg-key'
borg create \
--compression zstd,6 \
"::backup-$(date +%Y%m%d-%H%M%S)" \
/etc /home /var/www /opt
borg prune --keep-daily=7 --keep-weekly=4 --keep-monthly=6
Centralized monitoring (on backup server):
#!/bin/bash
# /usr/local/bin/monitor-all-backups.sh
REPOS_DIR="/backup/borg-repos"
MAX_AGE_HOURS=26
for repo in "$REPOS_DIR"/*; do
if [ -d "$repo" ]; then
server_name=$(basename "$repo")
export BORG_REPO="$repo"
# Get latest archive age
latest=$(borg list --short "$BORG_REPO" 2>/dev/null | tail -1)
if [ -z "$latest" ]; then
echo "WARNING: $server_name has no backups"
else
echo "OK: $server_name latest backup: $latest"
fi
fi
done
Troubleshooting
Repository Locked
Symptom: Failed to create/acquire the lock
Cause: Previous backup didn't complete cleanly
Solution:
# Check for running borg processes
ps aux | grep borg
# If no processes, break lock
borg break-lock /backup/borg-repo
# If process exists, wait or kill it
Cache Sync Issues
Symptom: Cache is newer than repository
Solution:
# Delete cache
rm -rf ~/.cache/borg/
# Rebuild cache
borg list /backup/borg-repo
Out of Space During Backup
Symptom: No space left on device
Solutions:
# Check repository size
borg info /backup/borg-repo
# Prune aggressively
borg prune --keep-daily=3 /backup/borg-repo
# Compact repository
borg compact /backup/borg-repo
# Check and increase storage
df -h /backup
Conclusion
BorgBackup represents a modern, sophisticated approach to data protection, combining deduplication, compression, and encryption to deliver efficient, secure backups. Its content-defined chunking and global deduplication enable dramatic storage savings while maintaining complete backup histories spanning months or years.
Key takeaways:
-
Initialize securely: Choose appropriate encryption mode and protect passphrases/keys carefully.
-
Optimize configuration: Use appropriate compression algorithms and exclude patterns for your use case.
-
Automate consistently: Implement systemd timers or cron jobs with robust error handling.
-
Prune regularly: Maintain retention policies to balance history with storage consumption.
-
Monitor actively: Verify backups complete successfully and run periodic integrity checks.
-
Test restoration: Regular restoration drills ensure confidence in recovery capabilities.
-
Secure properly: Use append-only mode, protect SSH keys, and encrypt repositories appropriately.
BorgBackup is particularly well-suited for environments with:
- Frequent backups of large datasets with incremental changes
- Need for long retention periods (months/years)
- Security requirements necessitating encryption
- Limited storage budgets benefiting from deduplication
Combined with proper planning, automation, monitoring, and the 3-2-1 backup rule (maintain Borg repositories locally, remotely, and on different media), BorgBackup provides enterprise-grade data protection suitable for everything from personal workstations to production infrastructure.


