VPS Backup Strategy: Restic + Backblaze B2
This document outlines the implementation of an encrypted, off-site backup solution for Virtual Private Servers (VPS) using Restic for backup orchestration and Backblaze B2 as the S3-compatible object storage backend.
1. Architecture Overview
The backup workflow follows a standard Push model:
- Source: Local filesystem (Volumes, Databases, Configs).
- Transport: Encrypted TLS stream.
- Destination: Backblaze B2 (Immutable snapshots).
Backup Scope
| Category | Paths |
|---|---|
| Docker Data | /var/lib/docker/volumes |
| Application Data | /home/azureuser/forgejo, /home/azureuser/files, /home/azureuser/r-kcet_discord_bot/data |
| System Config | /etc, /home/azureuser/.ssh |
2. Infrastructure Setup
2.1 Backblaze B2 Configuration
- Bucket: Create a private bucket (e.g.,
shorty-backups). - App Key: Generate an Application Key with
Read/Writeaccess restricted to the backup bucket. - Credentials: Note the
keyIDandapplicationKey.
2.2 Environment Configuration
On the VPS, manage secrets via a restricted environment file.
File: /root/.restic-env
# Backblaze B2 Credentials
export B2_ACCOUNT_ID="<YOUR_KEY_ID>"
export B2_ACCOUNT_KEY="<YOUR_APPLICATION_KEY>"
# Restic Repository Password (Encryption Key)
export RESTIC_PASSWORD="<STRONG_GENERATED_PASSPHRASE>"
# Repository Path
export RESTIC_REPOSITORY="b2:shorty-backups:/shorty"Note: Ensure chmod 600 /root/.restic-env to restrict access.
3. Implementation
3.1 Installation & Initialization
# Install Restic
sudo apt update && sudo apt install -y restic
# Initialize the repository
source /root/.restic-env
restic init3.2 Automation Script
The following script handles the backup, retention policy (Pruning), and health checks.
File: /usr/local/bin/server-backup.sh
#!/bin/bash
set -e
# Load Environment
source /root/.restic-env
# Define Backup Sources
BACKUP_PATHS=(
"/var/lib/docker/volumes"
"/home/azureuser/forgejo"
"/home/azureuser/files"
"/home/azureuser/r-kcet_discord_bot/data"
"/etc"
"/home/azureuser/.ssh"
)
echo "[$(date)] Starting Backup..."
# Execute Backup
restic backup "${BACKUP_PATHS[@]}"
# Apply Retention Policy (Keep 7 daily, 4 weekly)
restic forget --keep-last 7 --keep-weekly 4 --prune
# Verify Repository Integrity (Optional/Periodic)
# restic check
echo "[$(date)] Backup Completed Successfully."Apply permissions: chmod +x /usr/local/bin/server-backup.sh
3.3 Scheduling (Cron)
Run the backup daily at 03:00 UTC.
# sudo crontab -e
0 3 * * * /usr/local/bin/server-backup.sh >> /var/log/restic-backup.log 2>&14. Disaster Recovery (DR) Procedure
In the event of a total instance loss, follow these steps to restore service.
Step 1: Provision & Auth
Install Restic on the new instance and recreate the /root/.restic-env file with the original credentials and RESTIC_PASSWORD.
Step 2: Full System Restore
source /root/.restic-env
# Restore the latest snapshot to the root directory
restic restore latest --target /Step 3: Post-Restore Validation
- Permissions: Fix ownership if UID/GIDs differ on the new OS.
chown -R azureuser:azureuser /home/azureuser - Services: Reinstall the Docker engine and start the stack.
docker-compose up -d
5. Maintenance & Monitoring
- Snapshots: View all available recovery points:
restic snapshots. - Storage Stats: Monitor B2 usage:
restic stats. - Integrity: Run
restic checkmonthly to ensure no data corruption has occurred in the remote bucket. - Testing: Perform a non-destructive restore test quarterly:
restic restore latest --target /tmp/restore-test
6. Cross-Provider Migration & Restore
When migrating between different cloud providers (e.g., Azure to DigitalOcean or AWS), system environments and default usernames often change (e.g., azureuser vs ubuntu). To handle this safely, use a Temporary Restore workflow.
The Correct Cross-Provider Restore Method
Instead of restoring directly to /, restore to a temporary directory first to avoid overwriting system-specific files on the new VPS.
# Restore to a temporary location
restic -r b2:shorty-backups:/shorty restore latest --target /restoreYour backup will now be accessible at /restore/, allowing you to inspect and move data manually.
Step-by-Step Restore on a New VPS
-
Prepare New VPS
- Provision your new instance (DigitalOcean, AWS, etc.).
- Install required tools:
sudo apt update sudo apt install docker.io restic
-
Restore to Temporary Location
restic -r b2:shorty-backups:/shorty restore latest --target /restore -
Restore Docker Volumes Copy the volume data and restart the Docker engine:
sudo rsync -a /restore/var/lib/docker/volumes/ /var/lib/docker/volumes/ sudo systemctl restart docker -
Restore Application Data (User Migration) If your new server has a different user (e.g.,
ubuntuinstead ofazureuser), move the data and fix permissions:# Copy data from the old user's home to the new system sudo rsync -a /restore/home/azureuser/forgejo /home/ sudo rsync -a /restore/home/azureuser/files /home/ # If renaming the home directory: sudo mv /restore/home/azureuser /home/ubuntu sudo chown -R ubuntu:ubuntu /home/ubuntu -
Restore SSH Keys
sudo mkdir -p /home/ubuntu/.ssh sudo cp /restore/home/azureuser/.ssh/* /home/ubuntu/.ssh/ sudo chown -R ubuntu:ubuntu /home/ubuntu/.ssh chmod 600 /home/ubuntu/.ssh/* -
Restore Config Files (Selective) Only copy specific configurations you need; do not blindly overwrite
/etc.sudo rsync -a /restore/etc/nginx /etc/ -
Start Services Navigate to your project directories and run:
docker compose up -d
Why This Method Is Better
This Restore → Inspect → Copy workflow is the professional DevOps standard. It ensures that you don’t lose data when moving between providers with different system layouts, allowing your infrastructure to remain provider-agnostic.