Pourquoi les snapshots hébergeur ne suffisent pas : trois limites concrètes
Un snapshot hébergeur est pratique, mais il partage le même plan de défaillance que votre VM. Première limite : si la VM est supprimée — par erreur, par votre fournisseur, ou suite à un impayé — les snapshots associés disparaissent avec elle. Deuxième limite : si un attaquant compromet votre compte hébergeur, il peut supprimer snapshots et VM en quelques secondes via l'API ou le tableau de bord. Troisième limite : les snapshots de datacenter ne testent jamais la restauration. Un snapshot « cohérent » peut contenir un système de fichiers corrompu ou une base de données dans un état incohérent ; vous ne le saurez qu'au moment où vous en aurez besoin.
Ce qu'une stratégie 3-2-1 garantit, et ce qu'un snapshot ne garantit pas
- Trois copies : l'originale sur disque local, une sur les snapshots hébergeur, une hors du fournisseur sur S3 — aucun point de défaillance unique ne peut tout effacer.
- Deux supports distincts : le disque NVMe de votre VPS et le stockage objet d'un autre fournisseur sont physiquement et logiquement séparés.
- Chiffrement avant le transfert : Restic chiffre côté client avec AES-256 ; le fournisseur de stockage S3 ne voit que des blobs opaques, illisibles sans votre clé.
- Test de restauration : une sauvegarde non testée est une promesse, pas une garantie. Un timer systemd peut vérifier automatiquement qu'un fichier sentinelle est restaurable.
- Indépendance du fournisseur : votre bucket B2 ou R2 n'est pas effaçable depuis le tableau de bord de votre hébergeur VPS.
- Un snapshot hébergeur ne chiffre pas avant le transfert : les données sont lisibles par le fournisseur.
- Un snapshot hébergeur ne vérifie jamais la cohérence applicative de vos bases de données.
Les trois copies expliquées : locale, hébergeur, off-site
La règle 3-2-1 n'est pas une recette rigide — c'est un principe de diversification des risques.
Copie 1 — disque local de votre VPS. C'est votre première ligne : l'originale, sur le disque NVMe. Elle sert les restaurations rapides d'un fichier effacé par erreur sans aucune latence réseau.
Copie 2 — snapshots hébergeur. La sauvegarde automatique gérée par votre fournisseur VPS couvre les accidents de configuration et les suppressions accidentelles au niveau du système. C'est votre filet de sécurité sur site.
Copie 3 — stockage objet off-site, chiffré avec Restic. C'est le maillon que la plupart des équipes oublient, et le seul qui résiste à la perte complète du compte hébergeur. Restic chiffre les données avant tout transfert, les déduplique pour minimiser les coûts et les envoie sur un bucket S3-compatible chez un fournisseur tiers. C'est cette troisième copie que ce guide construit.
Backblaze B2 vs Cloudflare R2 : choisir votre backend S3
| Critère | Backblaze B2 | Cloudflare R2 |
|---|---|---|
| Stockage | tarif public par Go, sans quota gratuit | Gratuit jusqu'à 10 Go/mois, puis tarif public par Go |
| Egress (sortie réseau) | Gratuit vers Cloudflare et certains partenaires CDN ; facturable hors partenaires | Gratuit sans limite — aucun coût de sortie |
| Compatibilité S3 | API S3-compatible native ; endpoint `s3.us-west-004.backblazeb2.com` | API S3-compatible native ; endpoint `<account>.r2.cloudflarestorage.com` |
| Variable `RESTIC_REPOSITORY` | `s3:https://s3.us-west-004.backblazeb2.com/nom-du-bucket` | `s3:https://<account>.r2.cloudflarestorage.com/nom-du-bucket` |
| Clés d'accès | Application Key B2 (Key ID + Application Key) | API Token R2 avec permissions Object Read & Write |
| Cas d'usage recommandé | Volume élevé avec egress limité ou depuis infrastructure Cloudflare | Egress fréquent ou tests de restauration réguliers depuis n'importe où |
Mise en œuvre complète : Restic + S3 sur votre VPS
Exporter les variables d'environnement dans un fichier sécurisé
Créez /root/.restic-env avec les variables nécessaires. Pour Backblaze B2 :
export RESTIC_REPOSITORY="s3:https://s3.us-west-004.backblazeb2.com/votre-bucket"
export RESTIC_PASSWORD="votre-mot-de-passe-depot"
export AWS_ACCESS_KEY_ID="votre-b2-key-id"
export AWS_SECRET_ACCESS_KEY="votre-b2-application-key"Pour Cloudflare R2, remplacez l'URL du dépôt et les clés :
export RESTIC_REPOSITORY="s3:https://<account-id>.r2.cloudflarestorage.com/votre-bucket"
export RESTIC_PASSWORD="votre-mot-de-passe-depot"
export AWS_ACCESS_KEY_ID="votre-r2-access-key-id"
export AWS_SECRET_ACCESS_KEY="votre-r2-secret-access-key"Restreignez immédiatement les droits sur ce fichier : chmod 600 /root/.restic-env. Ce fichier ne doit jamais être commité dans un dépôt Git ni inclus dans une sauvegarde accessible sans authentification.
Initialiser le dépôt Restic sur S3
Chargez l'environnement, puis initialisez le dépôt chiffré sur votre bucket :
source /root/.restic-env
restic initRestic crée la structure du dépôt et scelle le chiffrement avec votre mot de passe. L'opération produit un identifiant de dépôt — notez-le. Conservez le mot de passe du dépôt en dehors du VPS : dans un gestionnaire de mots de passe, un coffre chiffré sur une machine distincte, ou un secret manager. Sans lui, aucune restauration n'est possible, même si vous disposez du bucket complet.
Lancer une première sauvegarde vers S3
Testez le chemin complet avec une sauvegarde manuelle :
source /root/.restic-env
restic backup /etc /var/www /opt/docker-dataPour les bases de données, générez un dump avant la sauvegarde ou utilisez le mode stdin. Exemple pour PostgreSQL :
pg_dump -U postgres mabase | restic backup --stdin --stdin-filename mabase.sqlVérifiez que le snapshot est bien créé : restic snapshots.
Définir la politique de rétention
La commande forget supprime les références aux anciens snapshots ; --prune libère physiquement les blocs orphelins dans le backend :
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 3 --pruneJustification des valeurs. Sept quotidiens couvrent une semaine entière — suffisant pour détecter une corruption silencieuse qui n'apparaît que quelques jours après l'incident. Quatre hebdomadaires offrent une fenêtre d'un mois pour détecter un problème applicatif lent (données manquantes progressivement). Trois mensuels permettent une restauration à un état antérieur au trimestre — utile après une migration de base de données ratée. --prune est indispensable : sans lui, forget marque les snapshots pour suppression mais ne libère pas l'espace dans le bucket, et la facture de stockage continue de croître.
Distinguer restic check et restic check --read-data
Ces deux commandes ne vérifient pas la même chose.
restic check valide les métadonnées du dépôt — structure des packs, cohérence des index, intégrité des pointeurs. Rapide (quelques secondes à quelques minutes selon la taille du dépôt). À lancer après chaque forget --prune.
restic checkrestic check --read-data télécharge et vérifie chaque blob de données en les comparant à leur hash cryptographique. Lent (proportionnel au volume du dépôt) et coûteux en egress si votre fournisseur facture les sorties. À réserver à une vérification mensuelle ou après un doute sur l'intégrité du bucket.
restic check --read-dataUne vérification hebdomadaire des métadonnées suffit pour détecter les corruptions courantes sans surcoût de transfert.
Créer l'unité systemd de sauvegarde (.service)
Créez /etc/systemd/system/restic-backup.service :
[Unit]
Description=Restic backup vers S3
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/root/.restic-env
ExecStartPre=/bin/sh -c 'curl -sf --max-time 10 https://one.one.one.one > /dev/null || exit 1'
ExecStart=/usr/bin/restic backup /etc /var/www /opt/docker-data
ExecStartPost=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 3 --prune
ExecStartPost=/usr/bin/restic check
StandardOutput=journal
StandardError=journalExecStartPre vérifie la connectivité réseau avant de tenter le backup — si le VPS est isolé ou si le bucket est inaccessible, le service échoue proprement avec un statut exploitable plutôt que de pendre ou d'écrire dans les logs une erreur silencieuse. EnvironmentFile charge /root/.restic-env sans exposer les clés dans la définition de l'unité.
Créer l'unité systemd de planification (.timer)
Créez /etc/systemd/system/restic-backup.timer :
[Unit]
Description=Timer quotidien pour restic-backup.service
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=900
[Install]
WantedBy=timers.targetPersistent=true garantit que si le VPS est éteint à 03h00, le backup s'exécutera au prochain démarrage. RandomizedDelaySec=900 étale le déclenchement sur une fenêtre de quinze minutes — évite les pics de charge si vous avez plusieurs serveurs avec le même timer. Activez et démarrez :
systemctl daemon-reload
systemctl enable --now restic-backup.timerVérifiez l'état du timer : systemctl status restic-backup.timer et les logs du dernier run : journalctl -u restic-backup.service.
Créer un test de restauration automatisé avec fichier sentinelle
Un backup dont la restauration n'a jamais été testée ne prouve rien. Créez un fichier sentinelle dans votre sauvegarde, puis un service systemd qui restaure et vérifie ce fichier.
Premièrement, créez le fichier sentinelle et incluez-le dans votre sauvegarde :
echo "sentinel-$(date +%s)" > /opt/restic-sentinel.txtAssurez-vous que /opt est inclus dans votre commande restic backup.
Ensuite, créez /etc/systemd/system/restic-restore-test.service :
[Unit]
Description=Test de restauration Restic
After=network-online.target
[Service]
Type=oneshot
EnvironmentFile=/root/.restic-env
ExecStart=/bin/sh -c '
rm -rf /tmp/restic-test-restore && \
restic restore latest --target /tmp/restic-test-restore && \
test -f /tmp/restic-test-restore/opt/restic-sentinel.txt && \
echo "Restauration OK : $(cat /tmp/restic-test-restore/opt/restic-sentinel.txt)" || \
(echo "ECHEC restauration sentinelle" && exit 1)
'
StandardOutput=journal
StandardError=journalCréez le timer hebdomadaire /etc/systemd/system/restic-restore-test.timer :
[Unit]
Description=Test hebdomadaire de restauration Restic
[Timer]
OnCalendar=Sun 04:00:00
Persistent=true
[Install]
WantedBy=timers.targetActivez : systemctl enable --now restic-restore-test.timer. Le dimanche à 04h00, le service restaure le dernier snapshot et échoue avec exit 1 si le fichier sentinelle est absent — ce qui produit un log exploitable et un statut failed visible dans systemctl status.
Secrets Restic : fichier .env isolé, jamais en dur dans le service
Ne placez jamais RESTIC_PASSWORD, AWS_ACCESS_KEY_ID ou AWS_SECRET_ACCESS_KEY directement dans la définition d'une unité systemd, dans un script versionné ou dans un Dockerfile. Le fichier /root/.restic-env avec chmod 600 est la bonne pratique : il est chargé par EnvironmentFile= sans jamais apparaître dans systemctl show ni dans les logs. Ajoutez /root/.restic-env à votre .gitignore ou .dockerignore si votre répertoire /root est versionné. Pour un environnement multi-utilisateurs, préférez un secret manager ou les secrets systemd (LoadCredential=) plutôt qu'un fichier plat.
Dépannage : quatre erreurs courantes
Fatal: unable to open config file au restic init ou au premier restic backup. Cette erreur indique que Restic ne peut pas accéder au bucket. Vérifiez d'abord que les variables sont bien chargées (echo $RESTIC_REPOSITORY) et que les identifiants sont corrects. Ensuite, vérifiez les permissions IAM de votre clé B2 ou R2 : elle doit disposer au minimum des droits de lecture, écriture et liste sur le bucket. Sur B2, une Application Key restreinte à un bucket spécifique doit explicitement inclure listBuckets pour que Restic puisse vérifier son existence. Sur R2, le token doit avoir les permissions Object Read et Object Write sur le bucket cible.
Bucket S3 : permissions insuffisantes. Si restic init réussit mais que restic backup échoue avec une erreur d'autorisation, c'est souvent une politique de bucket qui surcharge les permissions de la clé. Sur B2, vérifiez qu'aucune règle de bucket denyUpload n'est active. Sur R2, vérifiez que le bucket n'est pas en mode public avec restrictions en écriture.
Timer systemd qui ne se déclenche pas. Diagnostiquez en trois commandes : systemctl status restic-backup.timer (état actif ou inactif), systemctl list-timers --all | grep restic (prochaine exécution planifiée), journalctl -u restic-backup.service --since today (logs du dernier run). Si le timer est actif mais le service n'a pas tourné, vérifiez que OnCalendar est syntaxiquement valide : systemd-analyze calendar '*-*-* 03:00:00' doit renvover une date de prochain déclenchement.
restic check --read-data trop lent. Sur un dépôt de plusieurs dizaines de Go, --read-data peut prendre plusieurs heures et générer des coûts d'egress significatifs sur B2. Utilisez --read-data-subset=10% pour vérifier un échantillon aléatoire à chaque run hebdomadaire, et réservez la vérification complète à une maintenance mensuelle planifiée hors des heures de pointe.
Plan de reprise : combien de temps pour restaurer depuis B2 ou R2 ?
La durée de restauration dépend de trois facteurs : le volume de données, la bande passante disponible entre votre VPS et le bucket, et les éventuels coûts d'egress.
Pour estimer : un dépôt Restic de 20 Go sur B2 (données déjà dédupliquées et compressées) se restaure en environ 15 à 30 minutes avec une connexion de datacenter standard à 1 Gbps. Sur R2, l'egress est gratuit — vous n'avez pas de pression financière à étaler la restauration. Sur B2, si votre VPS est hors du réseau partenaire Backblaze, les premiers Go sont gratuits puis facturés ; une restauration complète d'un gros dépôt peut engendrer des coûts non nuls.
Deux pratiques réduisent le temps de reprise : d'abord, maintenir une liste de vos répertoires critiques séparée de vos répertoires de cache ou de logs (ne sauvegardez pas /tmp, /proc, les volumes Docker inutilisés) — un dépôt plus petit se restaure plus vite. Ensuite, tester régulièrement la restauration partielle d'un seul répertoire (restic restore latest --target /tmp/test --include /etc) pour calibrer le temps réel sur votre infrastructure, plutôt que de découvrir la durée le jour d'un incident. La commande restic stats donne la taille du dépôt et permet de planifier.