Guides

Backup Strategies: The 3-2-1 Rule and What Actually Matters

Most backup strategies fail because they were never tested. Here's how to actually implement reliable backups that you'll thank yourself for when things break.

The Backup Reality Check

Backups are like insurance. Everyone knows they need them. Most people don't test them until it's too late. The number of "we had backups" stories that end with "but the last good backup was from three months ago" is embarrassingly high.

This guide isn't about backup tools. It's about backup strategy โ€” what to back up, how to structure retention, where to store it, and most importantly, how to verify it actually works.

The 3-2-1 Rule

The standard advice, explained properly:

3 copies of your data
2 different storage media
1 offsite

"3 copies" means: your live data + 2 backups. Not one backup. One backup is a single point of failure.

"2 different media" means: if your backup is on the same server as your data and the server dies, you lose both. Better: server disk + external disk, or server disk + cloud storage.

"1 offsite" means: if your office burns down, your backup in the office doesn't help. The offsite copy is your protection against site-level disasters.

3-2-1 in Practice

LayerWhatWhere
LiveYour dataOn the server
Backup 1Full snapshotExternal disk (same location)
Backup 2Incremental snapshotsCloud storage (different location)

This is the minimum viable setup. You can add more layers (snapshot replication, multi-cloud), but start here.

What to Back Up

Application Data (Always)

  • Databases (MySQL, PostgreSQL, MongoDB, etc.)
  • User-uploaded files (images, documents, media)
  • Configuration files (if modified from defaults)
  • Application secrets (but encrypt them โ€” don't store plaintext keys in S3)
  • System Data (Depends)

  • Web server configs: probably, yes
  • System packages: no (you can reinstall)
  • OS: no (reinstall is faster and cleaner)
  • Logs: optional (compress and rotate if disk allows)
  • What Not to Back Up

  • Temporary files โ€” /tmp, cache directories
  • Build artifacts โ€” node_modules, .git, build outputs (can be rebuilt)
  • Large media files that can be re-downloaded โ€” if your server downloads public datasets, consider if you need to back up the download or just the download script

Backup Methods

Database dumps

# MySQL/MariaDB
mysqldump --single-transaction --routines --triggers --all-databases | gzip > /backups/mysql_all_$(date +%Y%m%d).sql.gz

# PostgreSQL pg_dumpall | gzip > /backups/postgres_all_$(date%Y%m%d).sql.gz

# MongoDB mongodump --archive=/backups/mongo_$(date +%Y%m%d).archive --gzip

Dumps should happen with --single-transaction (MySQL) or equivalent to ensure consistency without locking the database.

Filesystem snapshots

# rsync with hardlinks (for incremental efficient copies)
rsync -avz --delete /var/www/ /backup-disk/www/

# With hardlinks for space efficiency (each daily backup only stores changes) rsync -avz --delete --link-dest=/backup-disk/www-day-1 /var/www/ /backup-disk/www-day-2/

LVM snapshots

If your server uses LVM, you can take instant snapshots:

# Create snapshot (instant, not copy)
lvcreate --size 10G --snapshot --name backup-snap /dev/vg0/lv-root

# Mount and backup mount /dev/vg0/backup-snap /mnt/snapshot

# After backup umount /mnt/snapshot lvdelete /dev/vg0/backup-snap

LVM snapshots are space-efficient (copy-on-write) and fast to create. They're ideal for consistent database backups without downtime.

Retention Policies

Retention is the hard part. Keep backups too short, and you might not have a clean version to restore from. Keep them too long, and storage costs spiral.

Recommended Retention

TypeFrequencyRetention
Full backupDaily7 days (daily)
Weekly backupWeekly4 weeks
Monthly backupMonthly12 months
Annual backupYearly7 years

For most projects, this covers:

  • "I need last night's backup" (daily)
  • "Something broke last week, what did it look like?" (weekly)
  • "We need to see data from 3 months ago" (monthly)
  • "Audit requires records from 7 years ago" (annual)
  • Simplify: The GFS Approach

    Grandfather-Father-Son is a rotation scheme that simplifies retention:

  • Daily backups (Son): Keep 6 daily
  • Weekly backups (Father): Keep 4 weekly
  • Monthly backups (Grandfather): Keep 12 monthly

This gives you 6 recent days, 4 weeks, and 12 months. For most projects, this is sufficient.

#!/bin/bash
# /usr/local/bin/backup-rotate.sh

BACKUP_DIR="/backup-disk" DATE=$(date +%Y%m%d) DAY=$(date +%a) WEEK=$(date +%G-%V) MONTH=$(date +%Y-%m)

# Daily backup tar -czf $BACKUP_DIR/daily/$DATE.tar.gz /var/www /etc/nginx /var/lib/mysql

# Weekly if Sunday if [ "$DAY" = "Sun" ]; then cp $BACKUP_DIR/daily/$DATE.tar.gz $BACKUP_DIR/weekly/week-$WEEK.tar.gz fi

# Monthly if first of month if [ "$(date +%d)" = "01" ]; then cp $BACKUP_DIR/daily/$DATE.tar.gz $BACKUP_DIR/monthly/month-$MONTH.tar.gz fi

# Cleanup old daily backups (keep 7 days) find $BACKUP_DIR/daily -name "*.tar.gz" -mtime +7 -delete

Offsite Storage

Cloud Options

ProviderServiceCost (approx)Notes
AWSS3$0.023/GB/mo (Standard)Most mature, egress costs
B2Backblaze$0.006/GB/moNo egress fees, S3-compatible
WasabiWasabi$0.007/GB/moNo egress fees, S3-compatible
R2Cloudflare$0.015/GB/moNo egress fees, S3-compatible

For most use cases, Backblaze B2 or Wasabi offer the best value. S3 is the standard but has egress fees that can surprise you.

Upload Tools

# rclone (supports B2, S3, Wasabi, R2, and more)
rclone copy /backup-disk/daily/$DATE.tar.gz b2:my-bucket/daily/

# With bandwidth limiting to avoid saturating connection rclone copy --bwlimit 10M /backup-disk/daily/$DATE.tar.gz b2:my-bucket/daily/

# AWS CLI (if using S3) aws s3 cp /backup-disk/daily/$DATE.tar.gz s3://my-bucket/daily/

Encryption Before Upload

Never upload unencrypted backups to the cloud. Use gpg or rclone's built-in encryption:

# Encrypt with a password (use a passphrase, not a key file)
gpg --encrypt --recipient "Backup Key" /backup-disk/daily/$DATE.tar.gz

# Or use rclone's encryption (simpler for rclone-native operations) rclone --crypt-password "mypassword123" copy /backup-disk/daily/ b2:encrypted-backups/

The Part Everyone Skips: Testing Restores

Backups are worthless if you can't restore from them. Schedule regular restore tests.

What to Test

1. File restore โ€” Can I extract a specific file from a backup? 2. Database restore โ€” Can I restore a database dump to a test server? 3. Full restore โ€” Can I rebuild a server from scratch using only backups?

Restore Test Schedule

  • Weekly: Verify one file restore works
  • Monthly: Restore a database to a test environment
  • Quarterly: Full disaster recovery drill

Restore Test Script

#!/bin/bash
# /usr/local/bin/test-restore.sh

BACKUP=/backup-disk/daily/$(date -d "yesterday" +%Y%m%d).tar.gz TEST_DIR=/tmp/restore-test

# Extract to test directory mkdir -p $TEST_DIR tar -xzf $BACKUP -C $TEST_DIR

# Verify key files exist if [ -f $TEST_DIR/var/www/wp-config.php ]; then echo "โœ“ WordPress config found" else echo "โœ— WordPress config MISSING" exit 1 fi

# Verify database dump if [ -f $TEST_DIR/var/lib/mysql/latest.sql.gz ]; then echo "โœ“ Database dump found" else echo "โœ— Database dump MISSING" exit 1 fi

# Cleanup rm -rf $TEST_DIR echo "โœ“ Restore test passed"

Automation

Cron Schedule Example

# Daily backup at 3am
0 3   * /usr/local/bin/backup.sh

# Upload to cloud at 4am 0 4 * /usr/local/bin/backup-upload.sh

# Test restore at 9am Monday 0 9 1 /usr/local/bin/test-restore.sh

# Cleanup old local backups (keep 7 days) 0 5 find /backup-disk -name ".tar.gz" -mtime +7 -delete

What to Do When Restoring

When disaster strikes:

1. Assess the scope. Full server loss vs single file vs database corruption? Different scenarios, different restore procedures.

2. Identify the restore point. When was the last known good backup? Factor in how much data you're willing to lose.

3. Restore to a test environment first. Don't overwrite production until you've verified the backup is good.

4. Communicate. If users are affected, tell them. "We had a failure and we're restoring from backup, ETA X hours" is better than silence.

5. Post-mortem. What failed? Was it the backup system, the monitoring, or the underlying cause? Fix the root cause, not just the symptom.

The Checklist

Before you call your backup strategy done:

  • [ ] All databases being dumped daily
  • [ ] Dump files compressed and stored safely
  • [ ] File backups using rsync or similar
  • [ ] Retention policy defined and implemented
  • [ ] Offsite copy exists (cloud or remote server)
  • [ ] Backup encryption enabled
  • [ ] Monitoring: backup job success/failure alerts
  • [ ] Restore tested (file level)
  • [ ] Restore tested (database level)
  • [ ] Full restore drill done within last quarter
  • [ ] Documented restore procedure exists

Backups are not a "set and forget" system. They require maintenance, testing, and occasional intervention. Treat them accordingly.

Rather than DIY? Let OpsHelp handle everything.

Managed hosting with support, security, backups, and monitoring โ€” from ยฃ50/mo.

Get Managed Hosting โ†’

Need help with your server setup?

OpsHelp provides professional server management, setup, and hardening services.

Get Help from OpsHelp โ†’