The Backup You Didn’t Make Is the One You’ll Need
Let’s skip the sermon about why backups matter. If you’re reading this, you either already know or you recently found out in the most inconvenient way possible. The question isn’t whether to back up — it’s which tool makes it likely you’ll actually do it consistently and reliably.
Three tools dominate the modern Linux backup landscape for self-hosters and home lab operators: Restic, Borg, and Kopia. All three use deduplication — the technique that means backing up the same data twice doesn’t double your storage usage. All three encrypt data at rest. All three are actively maintained in 2026. They differ in language, approach, backend support, and how much they’ll frustrate you.
Why Deduplication Matters
Without deduplication, a daily backup of a 100GB directory gives you 365 × 100GB = 36.5TB per year. With deduplication, your backup repository only stores unique chunks of data. If 95GB of your data doesn’t change between backups, each backup adds about 5GB of new data. Total storage: much more reasonable.
Deduplication works by splitting files into chunks, hashing each chunk, and only storing chunks that haven’t been seen before. Each “snapshot” (backup point in time) is really just a set of references to the chunks that make it up. This is also why restorations are fast — the tool assembles the snapshot by reading only the chunks it needs.
The practical implication: you can keep 90 days of daily backups for a server where data changes slowly, and the storage cost is much closer to 1× than 90× the data size.
Restic: The Crossplatform Workhorse
Restic is written in Go, runs on every platform that matters (Linux, macOS, Windows, *BSD), and has the most backends of any backup tool in this comparison. If you need to back up to S3, Backblaze B2, SFTP, rclone destinations, Azure Blob, or a local path, Restic handles all of it with the same CLI.
Getting Started
# Install
apt install restic
# or
curl -L https://github.com/restic/restic/releases/latest/download/restic_linux_amd64.bz2 | bunzip2 > /usr/local/bin/restic
chmod +x /usr/local/bin/restic
# Initialize a local repository
restic init --repo /mnt/backup/myrepo
# Enter a password (and store it somewhere safe)
# Or initialize an S3 repository
export AWS_ACCESS_KEY_ID=your_key
export AWS_SECRET_ACCESS_KEY=your_secret
restic init --repo s3:s3.amazonaws.com/mybucket/restic
# Or Backblaze B2
export B2_ACCOUNT_ID=your_account
export B2_ACCOUNT_KEY=your_key
restic init --repo b2:mybucket:restic
Running Backups
# Backup a directory
restic backup /home/user /etc --repo /mnt/backup/myrepo
# Backup with tags
restic backup /var/www --repo /mnt/backup/myrepo --tag web,daily
# Exclude patterns
restic backup /home/user --repo /mnt/backup/myrepo \
--exclude="*.log" \
--exclude=".cache" \
--exclude="node_modules"
# Verify repository integrity
restic check --repo /mnt/backup/myrepo
Restore and Browse
# List snapshots
restic snapshots --repo /mnt/backup/myrepo
# Browse snapshot contents
restic ls --repo /mnt/backup/myrepo SNAPSHOT_ID
# Mount repository as FUSE filesystem (browse like a directory)
restic mount --repo /mnt/backup/myrepo /tmp/restic-mount
# Restore specific snapshot
restic restore SNAPSHOT_ID --target /tmp/restore --repo /mnt/backup/myrepo
# Restore specific files
restic restore SNAPSHOT_ID --target /tmp/restore \
--include "/home/user/documents" \
--repo /mnt/backup/myrepo
Retention and Pruning
# Keep 7 daily, 4 weekly, 6 monthly snapshots
restic forget --repo /mnt/backup/myrepo \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--prune
Automation Script
#!/bin/bash
# /usr/local/bin/restic-backup.sh
export RESTIC_REPOSITORY="s3:s3.amazonaws.com/mybucket/restic"
export RESTIC_PASSWORD="your-encrypted-password"
export AWS_ACCESS_KEY_ID="your_key"
export AWS_SECRET_ACCESS_KEY="your_secret"
# Backup
restic backup /home /etc /var/www \
--exclude="*.log" \
--exclude=".cache" \
--exclude="**/node_modules" \
--tag daily
# Prune
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
# Verify
restic check
echo "Backup completed: $(date)"
Borg: The Compression Champion
BorgBackup (Borg) is written in Python and C, focused on Linux/macOS, and features exceptional compression. Borg uses LZ4, zlib, LZMA, and zstd compression algorithms. For text-heavy data (logs, code, configs), Borg’s compression ratios are often significantly better than Restic’s.
Borg’s killer feature for many users is borgmatic — a wrapper that handles configuration, scheduling, and alerting, so your entire backup policy lives in a YAML file.
Getting Started with Borg
# Install
apt install borgbackup
# Initialize repository (local)
borg init --encryption=repokey /mnt/backup/borg-repo
# Set a passphrase
# Initialize remote (over SSH)
borg init --encryption=repokey user@backup-server:/mnt/backup/borg-repo
Running Backups
# Create archive
borg create /mnt/backup/borg-repo::'{hostname}-{now:%Y-%m-%d}' \
/home /etc \
--exclude '*.log' \
--exclude '**/.cache' \
--compression lz4 # or zstd,9 for better compression
# List archives
borg list /mnt/backup/borg-repo
# Info about an archive
borg info /mnt/backup/borg-repo::archive-name
Borgmatic: The Right Way to Run Borg
# Install borgmatic
pip install borgmatic
# or
apt install borgmatic
# Generate config
borgmatic config generate > /etc/borgmatic/config.yaml
# /etc/borgmatic/config.yaml
location:
source_directories:
- /home
- /etc
- /var/www
repositories:
- path: /mnt/backup/borg-repo
label: local
- path: user@backup-server:/mnt/backup/borg-repo
label: remote
storage:
encryption_passphrase: "your-passphrase"
compression: lz4
archive_name_format: '{hostname}-{now:%Y-%m-%d_%H-%M-%S}'
retention:
keep_daily: 7
keep_weekly: 4
keep_monthly: 6
consistency:
checks:
- name: repository
- name: archives
check_last: 3
hooks:
before_backup:
- echo "Starting backup at $(date)"
after_backup:
- echo "Backup completed at $(date)"
on_error:
- echo "Backup FAILED at $(date)" | mail -s "Backup Error" admin@example.com
# Run backup
borgmatic create --verbosity 1
# Restore
borgmatic restore --archive latest
# Schedule (add to crontab)
0 2 * * * /usr/local/bin/borgmatic create --verbosity 0 --syslog-verbosity 1
Docker with Borg
# docker-compose.yml
services:
borgmatic:
image: b3vis/borgmatic
volumes:
- /home:/mnt/source/home:ro
- /etc:/mnt/source/etc:ro
- /mnt/backup:/mnt/backup
- ./borgmatic.yaml:/etc/borgmatic.d/config.yaml:ro
environment:
- TZ=America/New_York
- BORGMATIC_CRON_SCHEDULE=0 2 * * *
restart: unless-stopped
Kopia: The New Kid With a Web UI
Kopia is the newest of the three, written in Go like Restic, but adding a web UI and desktop application that the others lack. It’s excellent for mixed environments where you want server-side automation and a GUI for desktop backup management.
# Install
curl -s https://kopia.io/docs/installation/linux-install-source.sh | bash
# or download from GitHub releases
# Initialize repository (local)
kopia repository create filesystem --path /mnt/backup/kopia-repo
# Initialize S3 repository
kopia repository create s3 \
--bucket=mybucket \
--access-key=KEY \
--secret-access-key=SECRET \
--prefix=kopia/
# Connect to existing repository
kopia repository connect s3 --bucket=mybucket --access-key=KEY --secret-access-key=SECRET
Running Backups
# Create a snapshot
kopia snapshot create /home/user
# List snapshots
kopia snapshot list
# Show snapshot content
kopia snapshot show SNAPSHOT_ID
# Restore
kopia snapshot restore SNAPSHOT_ID /tmp/restore
# Mount as FUSE
kopia mount all /tmp/kopia-mount
Retention Policies
# Set retention policy for a directory
kopia policy set /home/user \
--keep-latest 14 \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6
# Show policy
kopia policy show /home/user
Kopia Server (Web UI)
# Start Kopia server
kopia server start \
--address=0.0.0.0:51515 \
--server-username=admin \
--server-password=yourpassword
# Access at http://your-server:51515
The web UI shows repository statistics, allows browsing snapshots, and initiates restores — genuinely useful for non-technical users who need to recover their own files.
The Comparison Table
| Feature | Restic | Borg | Kopia |
|---|---|---|---|
| Language | Go | Python/C | Go |
| Platforms | All | Linux/macOS | All |
| Compression | LZ4, Zstd | LZ4, LZMA, Zstd | Zstd, LZ4, Gzip |
| Deduplication | Yes (content-defined) | Yes (content-defined) | Yes (content-defined) |
| Encryption | Yes (AES-256) | Yes (AES-256) | Yes (AES-256) |
| S3 backend | Yes | Via rclone | Yes (native) |
| B2 backend | Yes (native) | Via rclone | Yes (native) |
| SFTP | Yes | Yes (native) | Yes |
| Web UI | No | No (borgmatic has basic) | Yes |
| Desktop app | No | No | Yes |
| Wrapper tool | resticprofile | borgmatic | Built-in |
| Speed | Fast | Fast | Fast |
| Compression quality | Good | Excellent | Good |
| Learning curve | Low | Medium | Low |
| Active development | Yes | Yes | Yes |
The 3-2-1 Backup Strategy
No comparison is complete without the rule:
- 3 copies of your data
- 2 different storage media types
- 1 copy offsite
In practice for a home lab:
- Primary data (your NAS/server)
- Local backup (external drive or second server via Borg/Restic)
- Remote backup (Backblaze B2 or S3 via Restic/Kopia)
# Example: Restic to both local and B2
restic backup /home --repo /mnt/local-backup/myrepo --tag daily
restic backup /home --repo b2:mybucket:restic --tag daily
# Or Borgmatic with two repo targets (local + remote SSH)
Which One Should You Use?
Use Restic if: You want the widest backend support, cross-platform operation, and a simple CLI without wrappers. Best for scripted server backups with cloud storage.
Use Borg if: You’re on Linux, care about compression ratios, and want borgmatic’s YAML-driven policy management. Best for backing up large amounts of text/log data or when storage is at a premium.
Use Kopia if: You want a web UI, you’re managing a mixed fleet of servers and desktops, or you want a single tool that works on both your server and your partner’s laptop.
All three beat not having backups. Pick one, automate it, test your restores (this part is crucial — a backup you’ve never tested is a guess, not a safety net), and go do something else with your weekend.