Storage Backup Strategies - 3-2-1, RPO/RTO, and Backup Tiering

Status: Active
Last Updated: 2026-08-26
Category: Cloud - Storage & Backup Fundamentals
Prerequisites: cloud-storage-concepts, restic-backups
Time: 2 hours (reading + planning)
Tags: backup, 3-2-1, rpo, rto, storage, disaster-recovery

Summary

This article defines the strategy layer underneath every backup job on fogserv.cloud: the 3-2-1 rule, recovery point/recovery time objectives (RPO/RTO), and the three fundamental backup models (snapshot, sync, versioned). It then maps those concepts onto a practical tiering scheme β€” local disk β†’ MinIO object storage β†’ offsite copy β€” so that each service's backup can be designed deliberately instead of ad hoc.

🎯 What You'll Learn

By the end of this article, you'll be able to:


Table of Contents

  1. Context / Why This Matters
  2. The 3-2-1 Rule
  3. RPO and RTO
  4. Snapshot vs Sync vs Versioned
  5. Tiering: Local β†’ Object β†’ Offsite
  6. Practical Examples
  7. Troubleshooting & Common Pitfalls

Context / Why This Matters

fogserv.cloud already runs the mechanics of backups: restic-backups covers the tool, minio-setup covers S3-compatible object storage, and nextcloud-setup covers the largest user-facing data set. What those articles deliberately do not answer is the strategic question: how much data are you allowed to lose, and how fast must you be back?

Without explicit RPO/RTO numbers, backup systems drift into a false comfort state: jobs run green every night, but a single house fire, ransomware event, or dead RAID controller still takes everything, because all copies shared a failure domain. Strategy first, tooling second.

The 3-2-1 Rule

The baseline for any data you would be sad to lose:

# Requirement fogserv.cloud implementation
3 Three copies of the data Primary (service volume) + local backup target + offsite copy
2 Two different media/types Local filesystem (ZFS/ext4 on the NAS) + S3 object store (MinIO)
1 One copy offsite Encrypted restic repo pushed to a remote location (friend's box, cheap VPS, or cloud S3)

Notes on applying it honestly:

RPO and RTO

Two numbers define every backup decision. Write them down per service before choosing tooling.

RPO β€” Recovery Point Objective

How much data loss is tolerable, measured in time.

RTO β€” Recovery Time Objective

How long until the service is usable again after an incident.

Mapping table for homelab services

Service RPO RTO Consequence
Nextcloud DB 15 min 2 h Frequent small pg_dump snapshots + nightly full
Nextcloud data dir 24 h 4 h Nightly restic snapshot
Immich (DB + uploads) 24 h 6 h Nightly combined dump+snapshot
MinIO buckets 24 h 8 h mc mirror + lifecycle-managed versions
Docker host config 7 days 30 min Git repo (see ../cicd/cicd-concepts.md)

Snapshot vs Sync vs Versioned

Three fundamentally different models. Most bad backup designs come from using one where another was needed.

Snapshot

A point-in-time, read-only view of the data (ZFS/btrfs snapshots, LVM snapshots, database dumps).

Sync (mirroring)

A live copy kept identical to the source (rsync, mc mirror). Deleting a file on the source deletes it in the mirror.

Versioned backup

Each run stores a new immutable generation; old generations expire on a retention policy (restic snapshots, Borg archives).

Rule of thumb: snapshot for consistency points, sync for moving data between tiers, versioned backup as the actual safety net.

Tiering: Local β†’ Object β†’ Offsite

A practical three-tier pipeline used across fogserv.cloud services:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   snapshot    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  restic push  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Service      β”‚ ───────────▢ β”‚ Tier 1: Local     β”‚ ───────────▢ β”‚ Tier 2: MinIO    β”‚
β”‚ volumes      β”‚              β”‚ NAS disk          β”‚  (versioned) β”‚ S3 bucket        β”‚
β”‚ (Docker)     β”‚              β”‚ + ZFS snaps       β”‚              β”‚ (versioned)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                                       β”‚ mc mirror /
                                                                       β”‚ restic copy
                                                                       β–Ό
                                                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                                              β”‚ Tier 3: Offsite  β”‚
                                                              β”‚ encrypted repo   β”‚
                                                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tier 1 β€” Local fast target

Same-site disk (NAS or second machine). Purpose: absorb hourly/daily versioned snapshots with fast restore times (good RTO). Retention: keep 7 daily + 4 weekly. Cheap to keep dense because Tier 2 holds the long tail.

Tier 2 β€” Object storage (MinIO)

S3 API target running on different hardware than the primary (see minio-setup). Restic speaks S3 natively, so the local repo is replicated with restic copy or the repo is initialized directly on MinIO. Enable bucket versioning and a lifecycle rule to age out noncurrent versions β€” this gives you the "one copy on different infrastructure" property without a cloud bill.

Tier 3 β€” Offsite

An encrypted repository at a physically separate location. Because restic encrypts client-side, the offsite host never needs to be trusted. Sync Tier 2 β†’ Tier 3 with rclone sync or a second restic remote, ideally from a different network path (e.g., over WireGuard VPN).

Encryption everywhere

Every tier beyond the service host must hold only ciphertext: restic repos are AES-256 encrypted with the repo password; database dumps should be piped through age or restic's stdin backup if stored raw. Keys/passwords belong in a secrets manager, not next to the backups (see sysadmin/secrets).

Practical Examples

Example 1: Classify a new service in 5 minutes

When adding any new Docker service, fill in this mini-template before writing a single backup command:

Service: jellyfin
Data:      /srv/jellyfin/config (small), /media/library (large, re-creatable)
RPO:       config 24h; library N/A (re-downloadable)
RTO:       4h
Model:     versioned backup of config only; library excluded
Tiers:     T1 restic local, T2 restic→MinIO, T3 inherited via repo replication

The key discipline: exclude re-creatable bulk data (media, caches) from all tiers. Backing up 4 TB of re-downloadable movies wastes every tier and stretches RTO.

Example 2: Consistent database snapshot feeding a versioned backup

#!/usr/bin/env bash
set -euo pipefail
# Tier 1: consistent dump, then restic picks it up
docker exec nextcloud-db pg_dump -U nextcloud nextcloud \
  | gzip > /backup/staging/nextcloud-db-$(date +%F).sql.gz

restic backup /backup/staging /srv/nextcloud/data \
  --tag nextcloud --tag auto

# Retention on Tier 1
restic forget --keep-daily 7 --keep-weekly 4 --prune
rm -f /backup/staging/nextcloud-db-*.sql.gz.tmp

Example 3: Replicating the repo to Tier 2

export RESTIC_REPOSITORY=s3:http://minio.internal:9000/backups
export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=...
restic copy --from-repository /mnt/nas/restic --tag auto

Troubleshooting & Common Pitfalls

Problem Cause Fix
Backups pass but restore fails Never tested; repo corrupt or password lost Schedule quarterly restore drills (see backup-to-object-storage)
Ransomware took out all copies Sync-only "backups"; shares writable from desktops Use versioned backups with append-only credentials; restrict SMB/NFS access to backup host
Offsite copy months stale Manual offsite process Automate Tier 3 sync inside the same timer chain (backup-automation)
Backup storage fills up No retention policy; keeping forever restic forget schedules per tier; monitor repo size (../observability/simple-alerts.md)
Database restore is inconsistent Files backed up while DB running without snapshot Dump first, or snapshot volume before file-level backup
Single disk = single copy illusion Two "copies" on same RAID array Verify tiers are on separate physical hosts/chassis

Next Steps / Ops Actions

Sources & Related Articles

External references consulted:

Related knowledge-base articles:

Change Log

2026-08-26

Choose Theme

Your selection is saved locally.

Neural Cacophony
Aperture v2
Flux v1
Mosaic Chaos
Nexus v1
Nexus Zest
Prism v2
Synapse