Backup & Snapshot Strategy: Losing No Data at the Lowest Cost
With the 3-2-1 rule, a few lines of script, and a single `cron` job, your server's data can survive disk failures, fat-finger deletes, and ransomware.
The most expensive thing on a server was never the hardware spec — it's the data inside. Disks fail, commands get mistyped, and even data centers have bad days. The goal of backups is simple: after something goes wrong, you can still get your data back. This article gives you a low-cost setup you can follow step by step.
Start with the 3-2-1 rule
In one line: keep at least 3 copies of your data, on 2 different types of media, with 1 copy off-site.
- 3 copies: the live data counts as one; add two backups on top.
- 2 media: for example local disk plus object storage — never put every copy on the same drive.
- 1 off-site: if the data center burns down or your account gets locked, that off-site copy is your last lifeline.
It isn't dogma — it's just eliminating single points of failure one by one.
File backups: tar and rsync
Use tar for archives — great for a daily full snapshot:
tar -czf /backup/www-$(date +%F).tar.gz /var/www
Use rsync for incremental syncs: it copies only what changed, so it's fast and space-efficient. --delete keeps the destination identical to the source:
rsync -avz --delete /var/www/ /backup/www/
Database backups: mysqldump
Never copy database files directly — you'll capture an inconsistent state. Instead, export logically. mysqldump produces replayable SQL:
mysqldump --single-transaction -u root -p yourdb | gzip > /backup/db-$(date +%F).sql.gz
--single-transaction gives you a consistent snapshot without locking the tables. To restore: gunzip < db.sql.gz | mysql -u root -p yourdb.
Automate it with cron
Manual backups get forgotten sooner or later. Put the command in a script and let cron run it every night. Run crontab -e and add a line:
# Back up the database at 3:30 daily, keep 7 days
30 3 * * * mysqldump --single-transaction -u root -pYOURPASS yourdb | gzip > /backup/db-$(date +\%F).sql.gz && find /backup -name 'db-*.sql.gz' -mtime +7 -delete
Note that % must be escaped as \% inside cron. The find -mtime +7 -delete prunes old backups so the disk never fills up.
Off-site: push to object storage
Local backups won't save you if the whole box dies. Sync your backups to object storage (S3-compatible) with rclone or your provider's CLI:
rclone copy /backup remote:my-bucket/backup
Wire that into the same cron job and you automatically own that off-site "1 copy." Enable bucket versioning and you can even roll back accidental deletes or ransomware encryption.
A snapshot is not a backup — but it pairs well
A snapshot is a point-in-time image of a whole volume, taken by your cloud platform or filesystem (LVM, ZFS, Btrfs). It's near-instant and restores fast — the perfect "undo button" before an upgrade or config change.
But a snapshot usually lives on the same storage as the original volume, so an underlying failure takes both down, and it's whole-volume granularity — you can't pull out a single file. So: snapshots are for fast rollback, backups are for long-term, off-site, pick-and-choose survival. They complement each other; neither replaces the other.
Run recovery drills regularly
An untested backup is no backup. Once a month, pull a backup onto a clean machine and actually restore it: extract the archive, import the database, start the service, and verify the data. Note how long it took (your RTO). On the day things really break, you want muscle memory — not to be reading the docs for the first time.
Summary
Backups don't need an expensive solution: tar/rsync for files, mysqldump for databases, cron for scheduling, object storage for the off-site copy, and snapshots for fast rollback — plus one recovery drill a month. Hold the line on 3-2-1, and your data will survive almost anything.