Chapitre 6
Sauvegarde et restauration
La sauvegarde quotidienne, la copie chiffrée hors serveur, la restauration d'essai et la restauration réelle.
Concerne :Équipe techniqueHébergeur
Ce qui est sauvegardé#
Le script deploy/sauvegarde.sh produit, sans arrêter la plateforme, un dossier horodaté (heure UTC) par sauvegarde dans SAUVEGARDE_DOSSIER (/var/backups/read) :
| Fichier | Contenu |
|---|---|
base.dump | Base PostgreSQL complète (pg_dump, format personnalisé), sans propriétaires ni droits : un instantané cohérent même pendant l'utilisation |
app-donnees.tar.gz | Fichiers déposés : logo, pièces jointes, ressources de la bibliothèque |
app-keys.tar.gz | Clés de protection des données ; sans elles, les sessions et les jetons émis deviennent illisibles |
comptes.txt | Nombres de lignes de quelques tables (organisations, activités, rapports, participations, pièces jointes, utilisateurs, journal d'audit) et nombres de fichiers ; comparés lors d'une restauration |
SHA256SUMS | Empreintes des quatre fichiers précédents |
Les fichiers sont lisibles par root seulement (droits 600, dossier 700). Les sauvegardes de plus de SAUVEGARDE_JOURS jours (30) sont supprimées à chaque exécution, localement et à distance.
Remarque
Les journaux de l'application et les certificats HTTPS ne sont pas sauvegardés : les journaux ne sont pas des données métier et Caddy redemande les certificats.
Activer la sauvegarde quotidienne#
Le minuteur systemd fourni lance la sauvegarde chaque jour à 2 h 30 UTC (3 h 30 à Niamey), à quelques minutes près ; une exécution manquée (serveur éteint) est rattrapée au démarrage.
sudo cp /opt/read/code/deploy/systemd/read-sauvegarde.* /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now read-sauvegarde.timer
systemctl list-timers read-sauvegarde.timer # prochaine exécutionLancer une sauvegarde à la main (avant un déploiement, par exemple) :
sudo /opt/read/code/deploy/sauvegarde.shLire le compte rendu de la dernière sauvegarde automatique :
sudo journalctl -u read-sauvegarde.service -n 20Exemple de compte rendu (valeurs indicatives) :
[2026-10-08T02:31:04Z] Sauvegarde dans /var/backups/read/20261008-023104
[2026-10-08T02:31:19Z] Taille : 48M ; organisations 24;activites 300;…;fichiers_app-keys 1;
[2026-10-08T02:31:41Z] Copie hors serveur : chiffre:/20261008-023104
[2026-10-08T02:31:42Z] Sauvegarde terminée.Attention
Le message ATTENTION : aucune copie hors serveur (SAUVEGARDE_DISTANTE vide) signifie que les sauvegardes restent sur le serveur : elles disparaîtraient avec lui. Configurez la copie hors serveur.
Copie hors serveur chiffrée#
La copie est faite par rclone (dans un conteneur : rien à installer), chiffrée avant l'envoi (couche crypt) : l'hébergeur du stockage ne peut lire ni les contacts ni le journal.
- Créez un stockage objet compatible S3 dans une autre région que le serveur, un conteneur et un utilisateur S3 limité à ce conteneur. Notez le point d'accès, la région, la clé d'accès et la clé secrète.
Choisissez une phrase de chiffrement longue et conservez-la hors du serveur (gestionnaire de mots de passe). Convertissez-la au format attendu par rclone :
docker run --rm rclone/rclone:1.75.1 obscure '<phrase>'Ajoutez à
/opt/read/.env(modèle commenté dansdeploy/.env.example) :RCLONE_CONFIG_DISTANT_TYPE=s3 RCLONE_CONFIG_DISTANT_PROVIDER=Other RCLONE_CONFIG_DISTANT_ENDPOINT=https://s3.<region>.example.net RCLONE_CONFIG_DISTANT_REGION=<region> RCLONE_CONFIG_DISTANT_ACCESS_KEY_ID=<clé d'accès> RCLONE_CONFIG_DISTANT_SECRET_ACCESS_KEY=<clé secrète> RCLONE_CONFIG_CHIFFRE_TYPE=crypt RCLONE_CONFIG_CHIFFRE_REMOTE=distant:<conteneur>/read RCLONE_CONFIG_CHIFFRE_PASSWORD=<phrase convertie par « rclone obscure »> SAUVEGARDE_DISTANTE=chiffre:- Lancez une sauvegarde à la main ; le compte rendu doit indiquer
Copie hors serveur. Listez les copies distantes :
docker run --rm --env-file <(grep ^RCLONE_ /opt/read/.env) rclone/rclone:1.75.1 lsd chiffre:
Danger
Sans la phrase de chiffrement, les copies distantes sont illisibles, y compris pour vous. Si le serveur est perdu, c'est la copie conservée hors du serveur qui permet de tout restaurer : vérifiez qu'au moins deux personnes savent où elle se trouve.
Restaurer#
Le script deploy/restaurer.sh vérifie d'abord les empreintes (SHA256SUMS) du dossier fourni, puis travaille selon le mode choisi.
Restauration d'essai#
Elle restaure la sauvegarde dans des conteneurs jetables et compare les nombres de lignes et de fichiers avec ceux relevés à la sauvegarde. Elle n'a aucun effet sur la plateforme.
sudo /opt/read/code/deploy/restaurer.sh /var/backups/read/<horodatage> --essaiElle se termine par Restauration d'essai réussie, identique à la sauvegarde, ou par ÉCHEC et les différences.
Important
Faites une restauration d'essai au moins une fois par mois et après chaque changement du schéma de la base. Une sauvegarde jamais relue n'est pas une sauvegarde.
Restauration réelle#
Elle remplace la base et les fichiers déposés de la plateforme par ceux de la sauvegarde.
- Prévenez les utilisateurs : tout ce qui a été saisi après la sauvegarde sera perdu.
Lancez :
sudo /opt/read/code/deploy/restaurer.sh /var/backups/read/<horodatage> --confirmerLe script arrête
appetcaddy, recrée la base, y restaurebase.dump, remplace le contenu des volumesapp-donneesetapp-keys, puis relance tout pardocker compose up -d. Le servicemigrationsredonne au rôle de l'application ses droits et applique les migrations plus récentes que la sauvegarde.- Connectez-vous et contrôlez quelques fiches récentes.
Serveur perdu : rapatrier une copie distante#
Sur un nouveau serveur installé comme au chapitre Installation, avec le même fichier .env (mêmes variables RCLONE_CONFIG_* et même phrase de chiffrement) :
- Déployez la plateforme (elle démarre sur une base vide).
Listez les copies (
lsd chiffre:) et rapatriez la plus récente :docker run --rm --env-file <(grep ^RCLONE_ /opt/read/.env) -v /var/backups/read:/r rclone/rclone:1.75.1 \ copy chiffre:<horodatage> /r/<horodatage>- Faites une restauration d'essai, puis la restauration réelle.
- Pointez le nom de domaine vers le nouveau serveur.