Bulletproof Self-Hosted Backups: Restic, Kopia & Automated Offsite Snapshots
The number one fear stopping engineering teams from self-hosting is disaster recovery: "What happens if the VPS SSD dies at 3 AM or an accidental DROP DATABASE occurs?"
Relying solely on cloud provider disk snapshots is not enough — they don't guarantee database consistency, they are often vendor-locked, and restoring a single corrupted table requires spinning up an entire duplicate server.
Here is an automated, battle-tested backup and disaster recovery architecture using open-source tools: PostgreSQL consistent dumps + Restic encrypted deduplication + Hetzner Storage Box / S3 + Healthchecks.io dead-man switches.
The 3-2-1-1-0 Backup Rule for Self-Hosters
- 3 Copies of Data: Live production database, local daily snapshot, offsite encrypted repository.
- 2 Different Media: Local NVMe disk and Remote Object Storage.
- 1 Offsite Copy: Geographically separated datacenter (e.g., VPS in Frankfurt, backups in Helsinki or S3).
- 1 Immutable / Append-Only Copy: Protected against ransomware or compromised server credentials.
- 0 Errors: Verified through automated daily restore drills.
Recommended Self-Hosted Backup Tools Comparison
| Tool | Deduplication | Encryption | GUI Web UI | Storage Targets | Best For |
|---|---|---|---|---|---|
| Restic | Chunk-based | AES-256 / ChaCha20 | CLI / Resticker | S3, SFTP, B2, Local | Automated headless servers & cron jobs |
| Kopia | Fast dynamic chunking | End-to-end | Yes (KopiaUI / Web) | S3, Azure, GCP, SFTP, WebDAV | Teams needing both CLI and Web GUI |
| BorgBackup | Extremely mature | High-grade | Vorta (Desktop) | SSH / BorgBase | Linux-to-Linux SSH repositories |
| pgBackRest | Postgres Block-level | Optional | CLI | S3, Azure, GCS, POSIX | Large-scale PostgreSQL PITR (>500GB) |
Full Category Guide: SelfHostStack Backup & Disaster Recovery Alternatives
Production Automation: The 15-Minute Restic Backup Script
Save this script as /opt/scripts/backup.sh on your server:
#!/usr/bin/env bash
set -euo pipefail
# Configuration
export RESTIC_REPOSITORY="s3:https://<endpoint>/<bucket-name>/restic-repo"
export AWS_ACCESS_KEY_ID="<your-s3-key>"
export AWS_SECRET_ACCESS_KEY="<your-s3-secret>"
export RESTIC_PASSWORD="<strong-repo-encryption-password>"
HC_PING_URL="https://hc-ping.com/<your-uuid-token>"
# Signal Start to Healthchecks.io
curl -fsS -m 10 --retry 3 "${HC_PING_URL}/start" || true
TEMP_DIR="/tmp/db-backups"
mkdir -p "$TEMP_DIR"
echo "[1/4] Dumping PostgreSQL databases consistently..."
docker exec -t postgres_container pg_dumpall -U postgres | gzip > "$TEMP_DIR/all_databases.sql.gz"
echo "[2/4] Initializing Restic repo if needed..."
restic snapshots > /dev/null 2>&1 || restic init
echo "[3/4] Running encrypted deduplicated backup..."
restic backup \
--tag "production" \
--tag "daily-cron" \
--exclude="/var/lib/docker/overlay2" \
"$TEMP_DIR" \
/opt/docker-stacks \
/etc/caddy
echo "[4/4] Pruning old snapshots according to retention policy..."
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--prune
# Cleanup temporary dump
rm -rf "$TEMP_DIR"
# Signal Success to Healthchecks.io
curl -fsS -m 10 --retry 3 "${HC_PING_URL}"
echo "Backup and maintenance completed successfully!"
How to Test and Restore (The 5-Minute Drill)
Never trust a backup you haven't restored. Run this quarterly:
# List all snapshots
restic snapshots
# Restore the latest snapshot to /tmp/restore-test
restic restore latest --target /tmp/restore-test
# Verify integrity of the database dump
gunzip -t /tmp/restore-test/tmp/db-backups/all_databases.sql.gz && echo "Database dump is 100% valid!"
Cost Analysis: Cloud Backup Costs
| Strategy | Storage | Monthly Cost |
|---|---|---|
| AWS RDS Automated Backups (Retention 30d) | 200 GB | ~$38.00/mo |
| Hetzner Storage Box BX11 (RAID, ZFS, Snapshots) | 1,000 GB (1 TB) | €3.81/mo |
| Cloudflare R2 (Zero Egress Fees) | 200 GB | ~$2.70/mo |
| Backblaze B2 | 200 GB | ~$1.20/mo |
Using Restic with Hetzner Storage Box or Cloudflare R2 reduces your backup budget by over 85% while giving you instant multi-region disaster recovery.
Hardware & Storage Recommendations
- Storage: Hetzner Storage Box (BX11/BX21) via SFTP / WebDAV or S3-compatible R2.
- Compute VPS: Hetzner Cloud CX22 / CPX21 (€3.79 - €7.05/mo).
- Review all cloud server benchmarks on our VPS Hosting Guide.
Explore verified Docker Compose templates, self-hosted alternatives, and full cost comparisons on SelfHostStack.
Top comments (0)