Skip to Content

Chapitre 15.3 — Tester la restauration

⏱️ TL;DR — La phrase à graver au-dessus de ton bureau : une sauvegarde non testée n’existe pas. Un dépôt restic qui grossit chaque nuit ne prouve rien tant que tu n’as pas restauré pour de vrai et vérifié que les données reviennent, intactes, dans le temps imparti. Ce chapitre te montre comment tester (restaurer sur une machine jetable, vérifier l’intégrité, chronométrer le RTO réel), comment restaurer une base (pg_restore, restic restore) et des fichiers, et surtout comment écrire un runbook de reprise : la procédure pas-à-pas pour reconstruire le serveur de zéro — provisionner, durcir, réinstaller les services, restaurer les données, repointer le DNS. Le tout entraîné régulièrement, pas le jour du sinistre.

🎯 Objectifs

  • Comprendre pourquoi une sauvegarde non testée est une fausse sécurité.
  • Tester une restauration : machine jetable, vérification d’intégrité, chronométrage du RTO réel.
  • Restaurer une base de données (pg_restore, restic restore) et des fichiers.
  • Écrire un runbook de reprise exploitable sous stress par n’importe qui de l’équipe.
  • Garder une infra reproductible (scripts d’install, notes, un peu d’Ansible en survol).
  • Instaurer des exercices de restauration réguliers.

Une sauvegarde non testée n’existe pas

C’est le principe le plus important de toute cette partie. Une sauvegarde a deux moitiés : l’écrire, et pouvoir la relire. La plupart des équipes soignent la première et ignorent la seconde — jusqu’au jour du sinistre, où elles découvrent que :

  • le dépôt était corrompu ou incomplet ;
  • la phrase de passe de chiffrement a été perdue (dépôt illisible) ;
  • le dump de base était vide (le pg_dump échouait en silence depuis des semaines) ;
  • il manquait un dossier essentiel dans la liste des chemins sauvegardés ;
  • la restauration prend 9 heures alors que le RTO promis était de 2 h.

Aucun de ces problèmes n’est visible tant qu’on n’a pas essayé de restaurer. Le seul test qui compte est empirique : reconstituer les données à partir de la sauvegarde, ailleurs, et constater qu’elles sont là et exploitables.

⚠️ PiègeLe piège numéro un de toute cette partie : faire confiance à une sauvegarde jamais restaurée. Un backup vert dans les logs n’est pas une garantie — c’est une promesse non vérifiée. Des entreprises entières ont coulé en découvrant, le jour du crash, que leurs sauvegardes étaient inexploitables depuis des mois. Tant que tu n’as pas restauré au moins une fois avec succès, considère que tu n’as pas de sauvegarde.

💡 Réflexe — Inverse la logique : ne dis pas « j’ai configuré des sauvegardes », dis « j’ai restauré mes données le __/__, en __ minutes, tout était là ». Tant que tu ne peux pas remplir cette phrase avec une date récente, le travail n’est pas fini.

Comment tester une restauration

Tester ne veut pas dire « écraser la prod pour voir ». On restaure à côté, sans risque, et on vérifie.

  1. Sur une cible jetable. Une VM locale, un conteneur, ou un VPS temporaire que tu détruis après. On y restaure comme si c’était le vrai serveur, sans toucher à la production.
  2. Vérifier l’intégrité. Le dépôt est-il sain ? restic check valide la cohérence du dépôt. Les données restaurées sont-elles complètes et lisibles ? On ouvre, on compte, on compare.
  3. Chronométrer le RTO réel. Lance un chrono au début, arrête-le quand le service serait de nouveau opérationnel. Ce temps mesuré est ton vrai RTO — souvent très différent de l’estimation optimiste. S’il dépasse ton objectif, il faut optimiser (sauvegardes plus fines, procédure plus scriptée) avant le sinistre.

🐚 Au terminal — Vérifier le dépôt puis restaurer un snapshot sur une cible jetable :

export RESTIC_REPOSITORY="s3:s3.eu-central-003.backblazeb2.com/formacampus-backups" export RESTIC_PASSWORD_FILE="/etc/restic/password" restic check # 1. le dépôt est-il sain et cohérent ? restic snapshots # 2. repère l'ID ou "latest" du snapshot voulu restic restore latest --target /srv/restore-test # 3. restaure tout dans un dossier de test ls -R /srv/restore-test # 4. vérifie que les fichiers attendus sont bien là

Ici, restic check inspecte l’intégrité du dépôt (structures et, en option approfondie, les données). restic restore latest --target <dossier> reconstitue le contenu du dernier snapshot dans un dossier neuf — on choisit un chemin jetable pour ne rien écraser. Le ls -R final confirme que la base, les uploads et les configs attendus sont présents.

🔒 Sécurité — Traite la cible de test comme de la vraie donnée : elle contient les données personnelles de tes utilisateurs le temps du test. Restaure sur une machine maîtrisée, détruis-la (et son disque) après, et ne laisse jamais traîner une restauration de prod sur un serveur de test ouvert ou partagé. Une fuite depuis l’environnement de test est une fuite tout court.

Restaurer une base de données

La base est presque toujours l’élément le plus critique et le plus délicat à restaurer. Deux étapes : récupérer le dump depuis restic, puis le rejouer dans PostgreSQL. (On s’appuie sur la Partie 11.5, qui détaille pg_dump / pg_restore.)

🐚 Au terminal — Récupérer le dump depuis restic, puis restaurer la base :

# 1. Extraire uniquement le dump de base depuis le snapshot restic restore latest --target /tmp/restore --include /var/backups/db # 2a. Cas d'un dump SQL compressé (pg_dump | gzip) : recréer la base et rejouer sudo -u postgres createdb formacampus gunzip -c /tmp/restore/var/backups/db/formacampus-2026-07-14.sql.gz \ | sudo -u postgres psql formacampus # 2b. Cas d'un dump au format custom (pg_dump -Fc) : utiliser pg_restore sudo -u postgres pg_restore -d formacampus /tmp/restore/.../formacampus.dump

On procède en deux temps. D’abord restic restore ... --include extrait seulement le dossier des dumps (inutile de tout restaurer pour ne récupérer que la base). Ensuite, la façon de rejouer dépend du format du dump : un dump SQL compressé se décompresse (gunzip -c) et se rejoue via psql dans une base fraîchement créée ; un dump custom (pg_dump -Fc) se restaure avec pg_restore, plus souple (restauration partielle, parallèle, réordonnancement). Après restauration, on vérifie : nombre de tables, quelques SELECT count(*) sur les tables clés, cohérence des données récentes.

💡 Réflexe — Après toute restauration de base, exécute une poignée de requêtes témoins : « combien d’utilisateurs ? », « la dernière commande date de quand ? », « telle table critique est-elle peuplée ? ». Un dump peut se restaurer sans erreur tout en étant incomplet (tronqué, ancien). Les requêtes témoins attrapent ce que le code de retour ne dit pas.

Restaurer des fichiers

Pour les fichiers (uploads, configs), c’est plus direct : restic restore reconstitue l’arborescence. On peut restaurer tout un snapshot, ou cibler un sous-chemin avec --include, voire remonter un seul fichier en montant le dépôt.

🐚 Au terminal — Restaurer des uploads, ou parcourir un snapshot fichier par fichier :

# Restaurer un dossier précis à son emplacement d'origine restic restore latest --target / --include /var/www/shared/uploads # Ou monter le dépôt comme un système de fichiers pour naviguer dedans mkdir -p /mnt/restic restic mount /mnt/restic # parcours les snapshots comme des dossiers, puis Ctrl-C

restic restore --target / --include <chemin> réécrit le dossier ciblé à sa place d’origine — pratique pour ne remettre que ce qui manque. restic mount est l’option la plus souple pour un besoin ponctuel : il monte le dépôt comme un dossier normal, tu navigues dans l’historique des snapshots et copies manuellement le ou les fichiers voulus, sans tout restaurer.

Le runbook de reprise

Le jour où le serveur est perdu, tu ne veux pas réfléchir : tu veux dérouler une procédure écrite, testée, que même un collègue peut suivre. C’est le runbook de reprise (disaster recovery runbook). Il reconstruit le serveur de zéro, dans l’ordre :

RUNBOOK DE REPRISE — formacampus.fr ──────────────────────────────────── 1. PROVISIONNER : créer un VPS Ubuntu LTS (même région), noter la nouvelle IP. 2. DURCIR : utilisateur deploy, SSH par clés, UFW, fail2ban (Partie 5). 3. SERVICES : installer Nginx, Node/Next, PHP-FPM/Symfony, PostgreSQL (Parties 7,9,10,11). 4. RESTAURER : restic restore -> dump DB (pg_restore) + uploads + configs + .env. 5. VÉRIFIER : requêtes témoins, l'app répond en local (curl 127.0.0.1). 6. HTTPS : Certbot -> certificats Let's Encrypt (Partie 8). 7. DNS : repointer l'enregistrement A vers la nouvelle IP, attendre le TTL. 8. CONTRÔLER : le site répond en HTTPS de l'extérieur, monitoring au vert (Partie 14). ──────────────────────────────────── Contacts : hébergeur, registrar DNS. RTO cible : 4 h.

Chaque étape renvoie à une partie du cours qui la détaille. Le runbook n’est pas un pavé théorique : c’est une checklist actionnable, avec les commandes clés, les chemins, les identifiants (les noms, pas les secrets), et les contacts (hébergeur, registrar). Il vit hors du serveur (un dépôt git privé, un gestionnaire de notes) — parce qu’un runbook stocké uniquement sur le serveur mort ne sert à rien.

⚠️ Piège — Le runbook (ou les identifiants du registrar DNS, ou la phrase de passe restic) stocké uniquement sur le serveur qu’on cherche à reconstruire. Le jour du sinistre, il est inaccessible. Garde le runbook et les accès de reprise ailleurs : gestionnaire de secrets, dépôt privé, coffre partagé de l’équipe. Teste que tu peux y accéder sans le serveur de prod.

📚 La doc — Un runbook s’appuie sur les commandes stables de chaque brique : man certbot, la doc Nginx, man pg_restore, la doc restic. Renvoie-y depuis ton runbook plutôt que de recopier des options qui vieilliront. Le runbook dit quoi faire dans quel ordre ; la doc dit la syntaxe exacte du jour.

Infra reproductible (survol)

Plus ton serveur est reproductible, plus ton RTO baisse. À la main, tu réinstalles étape par étape (lent, faillible). Mieux : scripter l’installation. Deux niveaux :

  • Scripts shell + notes : un setup.sh qui installe les paquets, pose les configs, crée l’utilisateur deploy. Simple, versionné dans git, suffisant pour un VPS unique.
  • Ansible (en survol) : un outil d’automatisation qui décrit l’état voulu du serveur dans des fichiers YAML (playbooks) et l’applique de façon idempotente (rejouable sans casse). Dès que tu gères plusieurs serveurs ou que tu recrées souvent, Ansible transforme des heures de configuration manuelle en une commande. On ne le détaille pas ici — retiens qu’il existe et qu’il industrialise la reconstruction.

Combinée aux sauvegardes de données, une infra scriptée rend la reprise rapide et fiable : le script rebâtit la machine, restic réinjecte les données. C’est la vraie récompense du travail de ce chapitre.

💡 Réflexe — Chaque fois que tu configures manuellement quelque chose sur ton serveur, demande-toi « si je devais tout refaire demain, est-ce écrit quelque part ? ». Si non, ajoute-le à ton script d’install ou à ton runbook tout de suite. Un serveur dont chaque réglage est reproductible n’a plus de secret perdu dans la tête d’une seule personne.

Des exercices de restauration réguliers

Un runbook testé une fois vieillit : les versions changent, un service s’ajoute, un chemin bouge. La restauration doit devenir un rituel, pas un événement. Instaure un exercice périodique (trimestriel, par exemple) : on prend un VPS jetable, on déroule le runbook chronomètre en main, on note ce qui a coincé, on corrige le runbook. C’est ainsi que le RTO promis reste réel et que l’équipe garde le geste.

🧭 Sur FormaCampus — Le premier vendredi de chaque mois, l’équipe fait son exercice de restauration : elle provisionne un petit VPS jetable, déroule le runbook formacampus.fr, restaure la base PostgreSQL (pg_restore depuis le dump restic) et les vidéos de cours, lance les requêtes témoins (« 12 480 apprenants, dernière inscription hier »), et chronomètre. Le premier test avait révélé un RTO réel de plus de 6 h (le restic check et le téléchargement des vidéos étaient lents) — au-dessus de l’objectif de 4 h. L’équipe a corrigé : dépôt de sauvegarde plus proche, vidéos volumineuses restaurées en parallèle. Depuis, le RTO mesuré tient sous les 4 h, et le runbook — stocké dans un dépôt git privé, hors du serveur — est à jour. Leur sauvegarde existe, parce qu’ils la restaurent pour de vrai.

✏️ Exercices

Exercice 1 — Démonte la fausse sécurité. Un responsable affirme : « nos sauvegardes sont parfaites, le job restic backup est vert tous les matins depuis un an. » Quelle est la question qui fâche, et quelles trois choses cette affirmation ne garantit pas ?

✅ Solution

La question qui fâche : « quand avez-vous restauré pour la dernière fois, et combien de temps ça a pris ? ». Un restic backup vert ne garantit pas : (1) que le dépôt est restaurable (il peut être corrompu, ou la phrase de passe perdue → illisible) ; (2) que les données sont complètes et exploitables (un pg_dump peut réussir tout en produisant un dump vide/tronqué, ou un dossier essentiel peut manquer de la liste) ; (3) que la restauration tient dans le RTO (elle peut prendre 9 h alors que l’objectif est 2 h). Seul un test de restauration réel lève ces trois inconnues.

Exercice 2 — Ordonne le runbook. Remets dans le bon ordre ces étapes de reprise et explique pourquoi le DNS vient à la fin : (A) restaurer la base et les uploads ; (B) repointer le DNS vers la nouvelle IP ; (C) provisionner et durcir un nouveau VPS ; (D) installer et configurer les services (Nginx, app, Postgres) ; (E) obtenir les certificats HTTPS.

✅ Solution

Ordre : C → D → A → E → B. On provisionne et durcit (C), on installe les services (D), on restaure les données (A), on obtient HTTPS (E), et enfin on repointe le DNS (B). Le DNS vient en dernier parce qu’il redirige les vrais utilisateurs vers la nouvelle machine : tant que le serveur n’est pas complet, vérifié et en HTTPS, on ne veut pas y envoyer le trafic (sinon les visiteurs tombent sur un serveur à moitié reconstruit). On bascule le DNS seulement quand tout répond correctement en local.

Exercice 3 — Restaure une base. Tu as un dump extrait via restic dans /tmp/restore/db/app.sql.gz (dump SQL compressé). Donne la séquence de commandes pour recréer et repeupler la base app, puis une vérification.

✅ Solution

# 1. Créer une base vide sudo -u postgres createdb app # 2. Décompresser et rejouer le dump dedans gunzip -c /tmp/restore/db/app.sql.gz | sudo -u postgres psql app # 3. Vérifier (requêtes témoins) sudo -u postgres psql app -c "\dt" # les tables sont-elles là ? sudo -u postgres psql app -c "SELECT count(*) FROM users;" # données présentes ?

Le gunzip -c décompresse vers la sortie standard, redirigée dans psql qui rejoue le SQL dans la base app. On vérifie ensuite avec \dt (liste des tables) et un count(*) sur une table clé — un dump peut se restaurer sans erreur tout en étant incomplet. (Pour un dump au format custom -Fc, on utiliserait pg_restore -d app à la place de psql.)

🧠 Quiz de révision

1. Que signifie « une sauvegarde non testée n’existe pas » ?

Qu’une sauvegarde n’a de valeur que si on peut la relire et restaurer. Tant qu’on n’a pas restauré pour de vrai (dépôt sain, données complètes et exploitables, dans le RTO), on n’a qu’une promesse non vérifiée : le dépôt peut être corrompu, la clé perdue, le dump vide, un dossier manquant. Le seul test valable est empirique.

2. Où et comment teste-t-on une restauration sans risque ?

Sur une cible jetable (VM, conteneur, VPS temporaire), jamais sur la prod. On restaure le snapshot dans un dossier/serveur de test, on vérifie l’intégrité (restic check, requêtes témoins, comptage des fichiers), on chronomètre le RTO réel, puis on détruit la cible de test (qui contient de vraies données personnelles).

3. Quelle vérification faire après avoir restauré une base, au-delà du code de retour ?

Des requêtes témoins sur les données : lister les tables (\dt), compter les enregistrements clés (SELECT count(*) FROM ...), vérifier la fraîcheur (date du dernier enregistrement). Un dump peut se restaurer sans erreur tout en étant incomplet ou ancien ; seules les requêtes témoins révèlent ce que le succès apparent cache.

4. Pourquoi repointe-t-on le DNS en dernier dans un runbook de reprise ?

Parce que basculer le DNS redirige les vrais utilisateurs vers la nouvelle machine. Tant que le serveur n’est pas entièrement reconstruit, restauré, vérifié et en HTTPS, on ne veut pas y envoyer de trafic — sinon les visiteurs tombent sur un serveur incomplet. On bascule le DNS seulement quand tout répond correctement en local.

5. Pourquoi le runbook et les accès de reprise ne doivent-ils pas vivre uniquement sur le serveur de prod ?

Parce que le sinistre qu’on prépare, c’est justement la perte de ce serveur. Un runbook, une phrase de passe restic ou les identifiants du registrar stockés uniquement là seraient inaccessibles au pire moment. Ils doivent vivre ailleurs (dépôt git privé, gestionnaire de secrets, coffre d’équipe), avec un accès vérifié sans le serveur de prod.


Chapitre suivant : Scaling — le trafic monte : mesurer, optimiser, puis grossir intelligemment (vertical, horizontal, CDN).

Last updated on