A backup that has never been restored is not a backup: it is a hypothesis. Many production sites rely on a single nightly dump sitting on the very server it is meant to protect, which survives neither a disk failure, nor a ransomware encryption, nor a slip of the hand. This article lays out a proven method for building a reliable backup strategy and, above all, for proving that it works.
The 3-2-1 rule, and why it still holds
The 3-2-1 rule fits in one sentence: three copies of the data, on two different media, one of them off site. It is more than twenty years old and remains the reference because it does not guard against a single risk, but against a whole family of them.
| Principle | What it covers | Concrete example |
|---|---|---|
| 3 copies | Silent corruption and human error | Production + local backup + remote backup |
| 2 media | Hardware failure of one media type | Server disk + object storage |
| 1 off site | Physical disaster and ransomware | S3 bucket in another region, write-once |
The off-site copy is the one most often neglected, and it is precisely the one that saves you during a server-room fire or a malicious encryption that reaches everything mounted locally. A more recent variant, known as 3-2-1-1-0, adds an immutable copy and a target of zero errors on the tested restore.
Choosing a tool: rsync, restic or borg
The choice of tool follows the real need, not fashion. Three families cover most of what a website requires.
| Tool | Deduplication | Encryption | Best fit |
|---|---|---|---|
| rsync | No | No (via the SSH transport) | Simple file mirror |
| restic | Yes, block-level | Yes, native (AES-256) | Remote object storage (S3, Backblaze) |
| borg | Yes, block-level | Yes, native | Dedicated backup server over SSH |
For a self-hosted site that must ship its data to remote object storage, restic offers the best compromise: an end-to-end encrypted repository, deduplication that keeps volume in check, and direct support for S3 backends. The example below initialises a repository, then backs up the files and a database.
# Variables d'environnement (a stocker hors du depot versionne)
export RESTIC_REPOSITORY="s3:s3.eu-west-3.amazonaws.com/mon-bucket-sauvegardes"
export RESTIC_PASSWORD_FILE="/root/.restic-pass"
# Initialisation, une seule fois
restic init
# Sauvegarde des fichiers du site
restic backup /var/www/monsite --tag fichiers
# Sauvegarde de la base : on evite le fichier intermediaire en clair
mysqldump --single-transaction monsite \
| restic backup --stdin --stdin-filename monsite.sql --tag baseAutomating without feeling safe
A manual backup is never taken on the day it matters. Automation goes through a scheduled task, whether a cron entry or a systemd timer, the latter having the advantage of logging cleanly and replaying a missed run.
# /etc/systemd/system/backup.timer
[Unit]
Description=Sauvegarde quotidienne du site
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
RandomizedDelaySec=600
[Install]
WantedBy=timers.targetThe retention policy is driven on the restic side, which can keep only a chosen number of points per day, week and month, then prune the rest. This step is essential: without it, the repository swells indefinitely and the storage bill follows.
# Rotation : 7 quotidiennes, 4 hebdomadaires, 6 mensuelles
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --pruneThe repository’s encryption key must never live only on the backed-up server. If that server burns down with its only copy of the key, the remote repository becomes a permanently unreadable block of data. Keep the key in a secrets manager and on an offline physical medium.
The restore test: the only proof that counts
This is the step almost nobody performs, and the only one that turns intent into a guarantee. A repository that has never been restored may be corrupt, incomplete, or encrypted with a key that has been lost, without any dashboard flagging it.
The day of the incident is not the day to discover that the restore does not work.
The test is run on an isolated environment, never by overwriting production. The goal is twofold: to verify that the data comes back, and to measure how long it takes, because that delay is your real recovery point.
# Restauration d'un instantane precis vers un repertoire de controle
restic snapshots
restic restore 4a8f2c1b --target /tmp/restore-test
# Verification d'integrite du depot (a planifier aussi)
restic check --read-data-subset=5%A monthly restore, logged with its date and duration, is worth a thousand “all green” backup reports. It is also the moment to check that the procedure is documented clearly enough to be carried out by someone other than its author, on the evening of an outage.
What to take away
A solid backup strategy comes down to three decisions: apply the 3-2-1 rule to cover every family of risk, automate with an explicit retention policy so as not to depend on human discipline, and test the restore regularly to turn the hypothesis into certainty. These reflexes fit naturally into the wider practice of running a self-hosted server and complement a security baseline on the hardening side.
I keep a simple rule for all my projects and my clients’: a backup whose restore I have not tested in the past month does not exist in my mental dashboard. Years ago I lost half a day of data because the nightly dump had been writing to a disk that had been full for a week, with nothing raising the alarm. Ever since, I treat the restore test as the only indicator that does not lie, and I schedule it just like the backups themselves. — Simon Janvier
Further reading: restic.
