Backing up a VPS is not optional, but traditional backup solutions can be expensive or complex to set up. Restic is a fast, encrypted, open-source backup tool that deduplicates data across backups. Backblaze B2 provides low-cost object storage at $0.006/GB/month. Together, they form a backup stack that costs pennies per month for a typical single-VPS setup. This guide walks through the full setup: installation, configuration, automation, and restore testing.
Why restic + B2?
Three things make this combination compelling for a budget VPS:
- Deduplication. Restic splits files into chunks and only stores new chunks. Daily backups of a 10 GB VPS typically consume 100-200 MB of new storage per day, keeping B2 costs under $1/month.
- Encryption. All data is encrypted client-side with AES-256-GCM before leaving your VPS. B2 never sees plaintext — your data is safe even if someone gains access to your bucket.
- Snapshots. Restic creates point-in-time snapshots that you can browse, mount, or restore selectively. You can restore a single file, a directory, or the entire backup.
Prerequisites
- A VPS running Linux (Ubuntu/Debian shown, but restic works on any distribution)
- A Backblaze B2 account (free tier: 10 GB storage, 1 GB daily egress)
- A B2 application key with read/write access to a dedicated bucket
Step 1: Install restic
Restic is available in most package managers. The official repository provides the latest version:
# Ubuntu/Debian
sudo apt install restic
# Verify installation
restic version
Step 2: Create a B2 Bucket and Application Key
Log into your Backblaze B2 account and:
- Create a new private bucket (name it something like
vps-backups-$(hostname)). - Generate an application key with read/write access to only that bucket (not your master key). This limits the blast radius if the key is compromised.
- Save the keyID and applicationKey — you will need them for the restic configuration.
Step 3: Initialize the restic Repository
On your VPS, set environment variables for the B2 credentials and initialize the repository:
# Set environment variables (temporary - we will make them permanent later)
export B2_ACCOUNT_ID="your-key-id"
export B2_ACCOUNT_KEY="your-application-key"
# Initialize the repository in your B2 bucket
restic -r b2:your-bucket-name init
# You will be prompted for a repository password
# This password is used to encrypt/decrypt your backups
# Store it in a password manager - if you lose it, your backups are unrecoverable
Step 4: Create Your First Backup
Run a manual backup to verify the setup works. A typical VPS backup includes the entire filesystem, excluding system pseudo-filesystems and temporary directories:
# Create a backup of the entire root filesystem, excluding /proc, /sys, /dev, /tmp, /mnt
restic -r b2:your-bucket-name backup --exclude /proc --exclude /sys --exclude /dev --exclude /tmp --exclude /run --exclude /mnt --exclude /media --exclude /lost+found /
For a database-driven application, add pre-backup scripts to dump your databases. Restic supports --pre-backup-command and --post-backup-command hooks:
# Backup with MySQL dump before the file snapshot
restic -r b2:your-bucket-name backup --pre-backup-command "mysqldump --all-databases --single-transaction > /tmp/mysql-dump.sql" --post-backup-command "rm /tmp/mysql-dump.sql" --exclude /proc --exclude /sys --exclude /dev --exclude /tmp --exclude /run --exclude /mnt --exclude /lost+found /
Step 5: Verify the Backup
After the first backup completes, verify the repository integrity and list your snapshots:
# Check repository integrity
restic -r b2:your-bucket-name check
# List snapshots
restic -r b2:your-bucket-name snapshots
# View the contents of a specific snapshot
restic -r b2:your-bucket-name ls latest
Step 6: Automate Daily Backups
Create a backup script at /usr/local/bin/vps-backup.sh:
#!/bin/bash
# /usr/local/bin/vps-backup.sh - Restic backup to Backblaze B2
set -euo pipefail
# Configuration
export B2_ACCOUNT_ID="your-key-id"
export B2_ACCOUNT_KEY="your-application-key"
export RESTIC_REPOSITORY="b2:your-bucket-name"
export RESTIC_PASSWORD="your-repository-password"
# Database dump (if applicable)
mysqldump --all-databases --single-transaction > /tmp/pre-backup-dump.sql 2>/dev/null || true
# Run the backup
restic backup --exclude /proc --exclude /sys --exclude /dev --exclude /tmp --exclude /run --exclude /mnt --exclude /lost+found --exclude /var/cache/apt --exclude /var/cache/dnf --exclude "*.log" --tag "daily" / 2>&1
# Clean up
rm -f /tmp/pre-backup-dump.sql
# Remove snapshots older than 30 days
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 3 --prune 2>&1
# Check repository integrity (weekly, on Sundays)
if [ "$(date +%u)" -eq 7 ]; then
restic check 2>&1
fi
Make it executable and add a cron job:
sudo chmod +x /usr/local/bin/vps-backup.sh
# Add to crontab (runs daily at 2 AM)
sudo crontab -e
# Add this line:
# 0 2 * * * /usr/local/bin/vps-backup.sh >> /var/log/vps-backup.log 2>&1
Step 7: Test Restore (The Most Important Step)
A backup you have never restored is not a backup. Test restoring a single file and a full snapshot:
# Restore a single file from the latest snapshot
restic -r b2:your-bucket-name restore latest --path /etc/nginx/nginx.conf --target /tmp/restore-test/
# Restore an entire snapshot to a temporary directory
restic -r b2:your-bucket-name restore latest --target /tmp/full-restore-test/
# Mount a snapshot as a filesystem (read-only)
restic -r b2:your-bucket-name mount /mnt/restic-mount
Verify the restored files are complete and the database dumps are importable. Document the restore procedure in a runbook — you do not want to figure it out under pressure.
Cost Analysis
For a typical 20 GB VPS with daily backups and 30-day retention:
| Component | Cost |
|---|---|
| B2 storage (initial ~2 GB, ~200 MB/day new) | ~$0.06/month |
| B2 Class B transactions (write/list) | ~$0.01/month |
| B2 Class C transactions (read) | ~$0.00/month (minimal) |
| Total | ~$0.07/month |
Compare this to managed backup services that charge $5-20/month, or to S3 standard storage at $0.023/GB/month. The restic + B2 combination is the cheapest production-grade backup solution for a single VPS.
Security Considerations
- Never store the repository password in the script file on a production server if you share the server. Use a restricted environment file (
/etc/restic/envwithchmod 600) or a secrets manager. - Use a dedicated B2 application key scoped to one bucket. Do not use your master B2 key.
- Test the backup without the key set to confirm that the backups are indeed encrypted and inaccessible without the password.
- Keep a copy of the repository password offline — in a password manager, not on the VPS. If you lose both the VPS and the password, your backups are gone.
Next Steps
Once your backup automation is running, consider adding monitoring: pipe the backup log to a health check service (like Uptime Kuma or Healthchecks.io) so you know when a backup fails. Set up a monthly calendar reminder to do a full restore test. And when comparing VPS providers for your next server, check the VPS provider comparison table to see which ones offer the storage and bandwidth specs that fit your backup strategy.


Leave a Reply
You must be logged in to post a comment.