How to Back Up Linux Servers to Backblaze B2 with Restic and Rclone (Encrypted, Automated, Pruned)

Summary: This guide shows how to back up a Linux server to Backblaze B2 using Restic with Rclone as the transport. You will set up encryption, implement a retention policy, automate runs with systemd timers, and test restores. The result is a fast, encrypted, and low-cost off-site backup that you control.

Why Restic + Rclone + Backblaze B2?

Restic is a modern, deduplicating backup tool with built-in encryption. Rclone provides wide storage compatibility and reliable transfers. Backblaze B2 offers affordable object storage with per-GB pricing. Together, they form a portable, verifiable, and cost-effective backup solution that works on any Linux distribution.

Prerequisites

- A Linux server (Ubuntu/Debian/RHEL/AlmaLinux, etc.) with sudo/root access
- Backblaze B2 account
- Basic terminal familiarity

Step 1: Create a B2 Bucket and Key

1) In Backblaze, create a bucket (e.g., mycompany-backups). Leave it private.
2) Create an Application Key restricted to that bucket. Copy the KeyID and Application Key now; you will not see the secret again.

Step 2: Install Restic and Rclone

sudo apt update && sudo apt install -y restic rclone

On RHEL/Fedora-based systems:
sudo dnf install -y restic rclone

Step 3: Configure Rclone for B2

We will keep Rclone’s config out of your home directory for clarity.

sudo mkdir -p /etc/rclone
sudo chmod 750 /etc/rclone

sudo rclone config create b2 b2 account <KeyID> key <ApplicationKey> hard_delete true --config /etc/rclone/rclone.conf

Verify the config:

sudo rclone lsd b2: --config /etc/rclone/rclone.conf

Step 4: Initialize the Restic Repository (via Rclone)

Create a password file and initialize the repository path inside the bucket.

sudo mkdir -p /etc/restic
echo "choose-a-strong-long-passphrase" | sudo tee /etc/restic/password > /dev/null
sudo chmod 600 /etc/restic/password

Initialize:

sudo env RCLONE_CONFIG=/etc/rclone/rclone.conf restic -r rclone:b2:mycompany-backups/restic --password-file /etc/restic/password init

Step 5: Exclusions and Environment File

Define what not to back up (caches, runtime, VM disks, etc.).

sudo tee /etc/restic/excludes.txt > /dev/null <<'EOF'
/proc/**
/sys/**
/dev/**
/run/**
/tmp/**
/var/tmp/**
/var/cache/**
*.iso
*.img
*.qcow2
EOF

Create an environment file to avoid repeating flags:

sudo tee /etc/restic/restic.env > /dev/null <<'EOF'
RESTIC_REPOSITORY=rclone:b2:mycompany-backups/restic
RESTIC_PASSWORD_FILE=/etc/restic/password
RCLONE_CONFIG=/etc/rclone/rclone.conf
RESTIC_CACHE_DIR=/var/cache/restic
EOF
sudo mkdir -p /var/cache/restic && sudo chown root:root /var/cache/restic && sudo chmod 700 /var/cache/restic

Step 6: Create a Backup Script

This script performs a backup, applies retention, and verifies the repository.

sudo tee /usr/local/bin/restic-backup.sh > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

# Sources to back up (adjust to your server)
SOURCES=(/etc /home /var/www)

# Nice/ionice to reduce system impact
nice -n 10 ionice -c2 -n7 \

env $(grep -v '^\s*#' /etc/restic/restic.env | xargs) \\
restic backup "${SOURCES[@]}" --exclude-file /etc/restic/excludes.txt --tag scheduled --one-file-system

# Retention policy: keep last 7 daily, 4 weekly, 6 monthly
env $(grep -v '^\s*#' /etc/restic/restic.env | xargs) \\
restic forget --prune --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --tag scheduled

# Optional consistency check (weekly via timer, or keep here for every run)
env $(grep -v '^\s*#' /etc/restic/restic.env | xargs) restic check --read-data-subset=1/20 || true
EOF
sudo chmod 750 /usr/local/bin/restic-backup.sh

Step 7: systemd Service and Timer

Create a systemd unit to run the script, and a timer to schedule it daily.

sudo tee /etc/systemd/system/restic-backup.service > /dev/null <<'EOF'
[Unit]
Description=Restic backup to Backblaze B2 (via rclone)
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
EnvironmentFile=/etc/restic/restic.env
ExecStart=/usr/local/bin/restic-backup.sh
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=7
PrivateTmp=yes
NoNewPrivileges=yes
ProtectSystem=full
ProtectHome=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes

[Install]
WantedBy=multi-user.target
EOF

sudo tee /etc/systemd/system/restic-backup.timer > /dev/null <<'EOF'
[Unit]
Description=Daily Restic backup timer

[Timer]
OnCalendar=03:15
RandomizedDelaySec=20m
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer

Step 8: First Run and Verification

Trigger a manual run and watch the output:

sudo systemctl start restic-backup.service
sudo journalctl -u restic-backup.service -n 200 -f

List snapshots to confirm:

sudo env $(grep -v '^\s*#' /etc/restic/restic.env | xargs) restic snapshots

Step 9: Tune Retention and Costs

Adjust the restic forget policy to meet recovery objectives and budget. More aggressive pruning reduces storage but limits historical versions. Backblaze B2 costs depend on stored GB, transaction counts, and egress; deduplication in Restic helps keep usage low.

Step 10: Test a Restore

Never trust backups you have not restored. Create a temporary restore folder and recover a small file.

sudo mkdir -p /tmp/restore-test
sudo env $(grep -v '^\s*#' /etc/restic/restic.env | xargs) restic restore latest --target /tmp/restore-test --include /etc/hostname
ls -l /tmp/restore-test/etc/hostname

Security Best Practices

- Use a long, unique Restic password stored in a root-only file.
- Restrict the Backblaze Application Key to one bucket with minimal permissions.
- Enable MFA on your Backblaze account.
- Keep /etc/rclone/rclone.conf and /etc/restic/password mode 600 and owned by root.
- Consider server-side encryption on B2 as a secondary layer if required by policy, although Restic already encrypts data client-side.

Performance Tips

- Parallel uploads: Restic auto-tunes, but you can increase concurrency on bigger servers via RESTIC_OPTIONS like --jobs 4 for backups or use Rclone env vars (RCLONE_B2_UPLOAD_CONCURRENCY).
- Bandwidth limits: Add --limit-upload 4MiB to Restic, or --bwlimit via Rclone if needed.
- Exclude large/ephemeral paths to reduce churn.

Troubleshooting

Fatal: wrong password or no key found: The password in /etc/restic/password does not match the repository. Fix the password file or re-init a new repo.

Repository locked: A previous run crashed. Remove stale locks only when you are certain no job is running:
sudo env $(grep -v '^\s*#' /etc/restic/restic.env | xargs) restic unlock

Slow uploads or timeouts: Check outbound bandwidth, raise concurrency, and ensure your firewall allows long-lived HTTPS connections. Try adding a randomized delay (already in the timer) to avoid contention on shared links.

What You Achieved

You now have an automated, encrypted, off-site backup pipeline for Linux using Restic, Rclone, and Backblaze B2. Snapshots are deduplicated, retention is enforced, and restores are provable. Regularly verify snapshots, monitor storage usage, and adjust policies as your data grows.

Comments