Backup Strategies: Protecting Data with rsync, Borg, and Restic

A reliable backup strategy is non-negotiable. Hardware fails, ransomware strikes, and human error can wipe out years of data in seconds. This guide covers the three most popular Linux backup tools, automation with cron and systemd, and the principles that keep your data safe.

The 3-2-1 Rule

The foundation of any backup strategy:

  • 3 copies of your data (the original plus two backups)
  • 2 different storage media (local disk + remote/cloud)
  • 1 copy offsite (geographically separate)

Following this rule ensures that no single failure -- fire, theft, disk crash, or ransomware -- can destroy all copies.

rsync

rsync is the workhorse for efficient file synchronisation. It transfers only the differences between source and destination.

Basic Usage

# Sync a directory to a backup location
rsync -avz /srv/data/ /mnt/backup/data/

# Sync over SSH to a remote host
rsync -avz --delete /srv/data/ user@backup-host:/backups/data/

# Dry run -- see what would change without modifying anything
rsync -avz --delete --dry-run /srv/data/ /mnt/backup/data/

Flag reference: - -a -- archive mode (recursive, preserves permissions, timestamps, etc.) - -v -- verbose output - -z -- compress data during transfer - --delete -- remove files from destination that no longer exist in source

Exclude Patterns

rsync -avz --delete   --exclude='*.tmp'   --exclude='.cache/'   --exclude-from='/etc/rsync-excludes.txt'   /srv/data/ /mnt/backup/data/

Borg Backup

Borg provides deduplicating, compressed, encrypted backups. It is ideal for systems with many similar files or frequent backups of slowly changing data.

Initialize a Repository

# Local repository
borg init --encryption=repokey /mnt/backup/borg-repo

# Remote repository over SSH
borg init --encryption=repokey ssh://user@backup-host/backups/borg-repo

Create an Archive

borg create --stats --progress   /mnt/backup/borg-repo::'{hostname}-{now:%Y-%m-%d_%H:%M}'   /etc /home /srv   --exclude '/home/*/.cache'

List and Prune Archives

# List all archives
borg list /mnt/backup/borg-repo

# Prune old archives (keep 7 daily, 4 weekly, 6 monthly)
borg prune --keep-daily=7 --keep-weekly=4 --keep-monthly=6   /mnt/backup/borg-repo

# Compact the repository to reclaim space after pruning
borg compact /mnt/backup/borg-repo

Restore

# Restore to a specific directory
cd /tmp/restore
borg extract /mnt/backup/borg-repo::myhost-2026-04-15_02:00

Restic

Restic is another deduplicating backup tool with native support for cloud storage backends (S3, B2, Azure, GCS).

Initialize a Repository

# Local repository
restic init --repo /mnt/backup/restic-repo

# S3 backend
export AWS_ACCESS_KEY_ID="your-key"
export AWS_SECRET_ACCESS_KEY="your-secret"
restic init --repo s3:s3.amazonaws.com/my-backup-bucket

Create a Backup

restic backup --repo /mnt/backup/restic-repo   /etc /home /srv   --exclude-file=/etc/restic-excludes.txt   --tag server-daily

List Snapshots

restic snapshots --repo /mnt/backup/restic-repo

Forget and Prune

# Apply a retention policy and remove old data
restic forget --repo /mnt/backup/restic-repo   --keep-daily 7 --keep-weekly 4 --keep-monthly 12   --prune

Restore

restic restore latest --repo /mnt/backup/restic-repo   --target /tmp/restore

Automation with Cron

Schedule backups with cron for set-and-forget reliability:

# /etc/cron.d/backup-daily
[email protected]

# Borg backup at 2:00 AM every day
0 2 * * * root /usr/local/bin/backup-borg.sh >> /var/log/borg-backup.log 2>&1

# rsync mirror at 3:00 AM
0 3 * * * root rsync -avz --delete /srv/ /mnt/backup/srv/ >> /var/log/rsync.log 2>&1

Automation with systemd

For more control, use a systemd timer:

# /etc/systemd/system/restic-backup.service
[Unit]
Description=Restic daily backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-restic.sh
Environment=RESTIC_REPOSITORY=/mnt/backup/restic-repo
Environment=RESTIC_PASSWORD_FILE=/etc/restic-password
# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Run Restic backup daily

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl enable --now restic-backup.timer

Remote Backups

Over SSH

Both Borg and Restic support SSH natively. Set up key-based authentication and optionally restrict the key to backup commands only in ~/.ssh/authorized_keys:

command="borg serve --restrict-to-path /backups",restrict ssh-ed25519 AAAA... backup-client

To S3-Compatible Storage

Restic supports S3 natively. For Borg, use a FUSE-mounted S3 bucket or rclone as an intermediary.

Restore Testing

A backup you have never restored is a backup you do not have. Schedule quarterly restore drills:

#!/usr/bin/env bash
# restore-test.sh -- verify the latest backup is usable
set -euo pipefail

RESTORE_DIR=$(mktemp -d)
restic restore latest --repo /mnt/backup/restic-repo --target "$RESTORE_DIR"

# Verify key files exist
test -f "$RESTORE_DIR/etc/passwd"
test -d "$RESTORE_DIR/srv/data"

echo "Restore test PASSED"
rm -rf "$RESTORE_DIR"

Return to the DevOps hub or continue to Ansible Guide and Git for Sysadmins.