Skip to content
Back to Blog
Linux & Server10 min read

Automated VPS Backup with Restic: Encrypted, Deduplicated, Offsite

Provider snapshots are not a backup strategy. This guide walks through setting up automated, encrypted, deduplicated offsite VPS backups using Restic and Backblaze B2 — including MySQL dumps, cron automation, a retention policy, and how to test a real restore.

Written by Abdul AbrorTechnical Hosting Support Engineer
On this page

Most VPS users rely on their hosting provider's snapshot feature and assume they are covered. Snapshots are useful, but they are not a backup strategy: they live on the same provider, they do not protect against account-level events, and they rarely automate the way you need. This guide shows you how to set up automated, encrypted, deduplicated offsite backups for a VPS using Restic — an open-source backup tool that runs on every major Linux distribution and costs nothing except your storage destination.

Why Restic Instead of rsync or tar?

Traditional backup approaches work, but they have practical problems in a VPS context:

  • rsync copies files as-is — no built-in encryption, no deduplication, and restoring a specific point in time requires either multiple full copies or manual snapshot management.
  • tar + cron produces unencrypted archives unless you layer in GPG, grows linearly with full backups, and has no built-in retention policy.

Restic addresses all of these out of the box. According to the official Restic documentation:

  • Encrypted by default: every snapshot is AES-256 encrypted before leaving your server
  • Content-addressed deduplication: only changed data is stored, keeping storage costs low
  • Point-in-time snapshots: every backup run creates a browsable snapshot; restore any file from any point
  • Multiple backends: supports local storage, SFTP, S3-compatible storage (Backblaze B2, Wasabi, Cloudflare R2), and more
  • Cross-platform: single binary, no dependencies, works on any Linux distribution

Architecture of This Setup

We will configure Restic to back up selected directories from a VPS to an offsite S3-compatible destination (Backblaze B2 is used as the example because of its low cost and first-class Restic support). A daily cron job runs the backup and enforces a retention policy automatically.

  • Source: your VPS (any Debian/Ubuntu/AlmaLinux/CentOS setup)
  • Destination: Backblaze B2 bucket (or any S3-compatible provider)
  • Schedule: daily at 02:00 server time
  • Retention: keep last 7 daily, 4 weekly, 12 monthly snapshots
  • Encryption: AES-256, passphrase stored in a protected file

Step 1: Install Restic

# Debian / Ubuntu
sudo apt update && sudo apt install restic -y

# AlmaLinux / CentOS
sudo dnf install restic -y

# Or download the latest binary directly
wget https://github.com/restic/restic/releases/latest/download/restic_linux_amd64.bz2
bunzip2 restic_linux_amd64.bz2
chmod +x restic_linux_amd64
sudo mv restic_linux_amd64 /usr/local/bin/restic

# Verify
restic version

Step 2: Create a Storage Bucket

On Backblaze B2 (or your preferred S3-compatible provider):

  1. Create a private bucket named vps-backups-yourname
  2. Create an application key with read and write access limited to that bucket
  3. Note the keyID and applicationKey — you will need them below
  4. Note the endpoint URL (e.g. s3.us-west-004.backblazeb2.com)

Cloudflare R2 also works well here — it has zero egress fees, which matters if you restore frequently. The setup is identical; just substitute the R2 endpoint and credentials.

Step 3: Create a Credential File

Store all secrets in a single file that only root can read. This avoids putting credentials in cron or environment variables visible to other processes.

sudo mkdir -p /etc/restic
sudo nano /etc/restic/b2.env

Paste the following, substituting your values:

export RESTIC_REPOSITORY="s3:https://s3.us-west-004.backblazeb2.com/vps-backups-yourname"
export RESTIC_PASSWORD="your-strong-passphrase-here"
export AWS_ACCESS_KEY_ID="your-b2-keyid"
export AWS_SECRET_ACCESS_KEY="your-b2-applicationkey"
sudo chmod 600 /etc/restic/b2.env

Step 4: Initialise the Repository

source /etc/restic/b2.env
restic init

Restic will connect to your bucket and initialise the repository structure. Save the passphrase somewhere offline — losing it means losing access to all backups.

Step 5: Run Your First Backup

source /etc/restic/b2.env
restic backup   /etc   /home   /var/www   /var/lib/mysql   --exclude=/var/www/*/cache   --exclude=/var/www/*/tmp   --verbose

The first run uploads everything. Subsequent runs only upload changed chunks — a 5 GB site with a few updated files might add only 10-50 MB per daily backup after the initial run.

Step 6: Automate with Cron

Create a backup script:

sudo nano /etc/restic/backup.sh
#!/bin/bash
set -euo pipefail
source /etc/restic/b2.env

restic backup   /etc   /home   /var/www   /var/lib/mysql   --exclude=/var/www/*/cache   --exclude=/var/www/*/tmp   --tag "daily"

# Retention policy: keep 7 daily, 4 weekly, 12 monthly
restic forget   --keep-daily 7   --keep-weekly 4   --keep-monthly 12   --prune

restic check
sudo chmod +x /etc/restic/backup.sh

Add a cron job:

sudo crontab -e
# Run backup every day at 02:00
0 2 * * * /etc/restic/backup.sh >> /var/log/restic-backup.log 2>&1

Step 7: Verify Backups and Test Restore

A backup you have never restored is a backup you cannot trust. Test at least once a month:

source /etc/restic/b2.env

# List snapshots
restic snapshots

# Browse a snapshot (substitute <snapshot-id> from the list above)
restic ls <snapshot-id> /var/www/html

# Restore a single file to /tmp
restic restore <snapshot-id>   --include /var/www/html/wp-config.php   --target /tmp/restore-test

# Full integrity check
restic check

MySQL / MariaDB: Back Up the Database

Backing up raw MySQL data files while the server is running can produce corrupt backups. Use mysqldump to create a consistent dump and include it in the Restic backup:

# Add to /etc/restic/backup.sh, before the restic backup line:
mkdir -p /var/backups/mysql
mysqldump --all-databases   --single-transaction   --quick   --lock-tables=false   -u root -p"$MYSQL_ROOT_PASSWORD"   > /var/backups/mysql/all-databases.sql

Then add /var/backups/mysql to the Restic backup paths. The SQL dump will be included, encrypted, and deduplicated along with everything else.

How Much Storage Will This Use?

With deduplication, ongoing storage cost depends almost entirely on how much data changes each day — not on total site size. A rough estimate:

  • A 10 GB VPS (mostly static files) with 200 MB changed per day: ~12 GB total after 30 days with the 7/4/12 retention policy
  • A WordPress site with an active database: initial backup ~3-5 GB; daily increments ~50-200 MB
  • Backblaze B2 costs approximately $0.006/GB/month (prices vary; check their current pricing)

Checklist

  1. Restic installed and binary verified
  2. Offsite bucket created with a dedicated API key (not your root account key)
  3. Credential file at /etc/restic/b2.env with chmod 600
  4. Repository initialised with restic init
  5. First manual backup completed and listed with restic snapshots
  6. Cron job installed and log file created
  7. MySQL dump included if the server runs a database
  8. Test restore performed — at least one file restored and verified
  9. Passphrase stored securely offline (password manager or printed, separate location)
  10. Retention policy pruning confirmed with restic forget --dry-run

Conclusion

Automated, encrypted, offsite backups are not optional for a production VPS. Restic gives you all three in a single binary with a straightforward cron setup. The steps above take under an hour to complete, cost a few dollars a month in storage, and mean that the next time a server goes down — hardware failure, accidental deletion, or a compromised account — you have a clean, tested restore point ready to use.

FAQ

What happens if I forget the passphrase?

You permanently lose access to all backups in that repository. Restic's encryption has no backdoor. Store the passphrase in at least two separate locations — a password manager and an offline note are the common combination.

Can I use this on shared hosting?

Restic requires a shell and the ability to run a persistent binary, which most shared hosting accounts support via SSH. The limitation is the destination: you need an S3 bucket or SFTP target that your cPanel account can reach. Some hosts block outbound S3 connections; SFTP to a separate VPS is a reliable alternative in that case.

Is Backblaze B2 a good choice?

B2 is widely used for Restic backups because of low storage cost and native S3-compatible API support. Cloudflare R2 is a strong alternative if you want zero egress fees and already use Cloudflare. Both work identically with Restic via the S3 backend.