Aller au contenu

Restaurer une instance

cenaclo-restore.sh remet en place une archive produite par cenaclo-backup.sh. Il s’exécute dans le conteneur backend, sur une instance déjà déployée et démarrée, et il remplace le contenu de la base.

Voir Sauvegardes self-hosting pour produire ces archives.

  • postgres/postgres.dump — le dump complet de la base applicative.
  • config/backup-manifest.txt — la date de création, la version Cenaclo, la version majeure, le nom d’hôte et la présence ou non du stockage objet.
  • config/environment.env — un instantané des variables d’environnement de l’instance au moment du backup.
  • secrets/generated/ — les secrets générés au premier démarrage, sauf si l’archive a été produite avec --no-secrets.
  • storage/seaweedfs/ — les objets SeaweedFS, sauf si l’archive a été produite avec --no-storage.

Les secrets générés au premier démarrage — CENACLO_MASTER_KEY_SECRET, JWT_PRIVATE_KEY, JWT_PUBLIC_KEY, AUTH_IP_SALT, EMAIL_HASH_PEPPER, STORAGE_LOCAL_SIGNING_SECRET, VAPID_PUBLIC_KEY et VAPID_PRIVATE_KEY — vivent dans le volume monté sur /var/lib/cenaclo/generated. Ils sont inclus dans l’archive, elle-même chiffrée avec la passphrase de sauvegarde.

C’est nécessaire, et pas seulement pratique. CENACLO_MASTER_KEY_SECRET dérive la clé AES-256-GCM qui chiffre les secrets TOTP en base. Sur un hôte neuf, le premier démarrage génère un nouveau jeu de secrets : sans celui d’origine, la base restaurée contient des colonnes chiffrées que plus aucune clé ne déchiffre, et les comptes protégés par 2FA deviennent inaccessibles. La restauration réussirait, sans rien récupérer.

La restauration réinstalle ces secrets dans le volume cible avant de redémarrer l’application, puis le démarrage suivant les reprend au lieu d’en générer de nouveaux.

config/environment.env reste expurgé : toute variable dont le nom contient PASSWORD, PASSPHRASE, SECRET, TOKEN, PRIVATE_KEY ou ACCESS_KEY y est remplacée par <redacted>. Cet instantané sert à comparer une configuration, pas à la rejouer — les valeurs qui comptent pour la récupération sont dans secrets/generated/.

config/backup-manifest.txt contient une ligne master_key_fingerprint. C’est un HMAC-SHA256 tronqué, calculé avec la master key comme clé : il identifie l’installation d’origine sans permettre de remonter au secret.

La restauration compare cette empreinte à celle de l’hôte cible avant d’écraser la base, et refuse d’aller plus loin quand une archive sans secrets atterrit sur un hôte qui ne peut pas lire ses données :

cenaclo-restore: this host runs a different master key than the one that
encrypted the backup; restoring would leave the encrypted data unreadable.

--force passe outre. Ne l’utilisez qu’après avoir vérifié que l’hôte détient bien la master key d’origine.

  • Une instance déjà déployée et démarrée, sur laquelle les variables minimales sont renseignées. La restauration ne provisionne pas une machine vide.
  • La passphrase de l’archive, fournie par CENACLO_BACKUP_PASSPHRASE_FILE (recommandé) ou CENACLO_BACKUP_PASSPHRASE. C’est la passphrase de sauvegarde, pas celle de la master key saisie dans le wizard.
  • DATABASE_URL, déjà présente dans le conteneur backend.
  • Si l’archive contient du stockage objet et que vous ne l’excluez pas : S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY et S3_SECRET_KEY, plus éventuellement S3_REGION et S3_FORCE_PATH_STYLE.

Restaurez avant de rouvrir le trafic utilisateur : la base est écrasée, les écritures faites entre-temps seraient perdues.

Ouvrez un terminal Coolify sur le service backend, vérifiez que la passphrase disponible correspond bien à celle de l’archive, puis lancez :

Fenêtre de terminal
/usr/local/bin/cenaclo-restore.sh /var/backups/cenaclo/cenaclo-backup-YYYYMMDDTHHMMSSZ.tar.gz.age
Fenêtre de terminal
docker compose --env-file infra/compose/.env -f infra/compose/docker-compose.yml exec -T backend \
/usr/local/bin/cenaclo-restore.sh /var/backups/cenaclo/cenaclo-backup-YYYYMMDDTHHMMSSZ.tar.gz.age

Le script déchiffre l’archive, vérifie la compatibilité de version, restaure Postgres, dépose l’instantané de configuration dans un répertoire protégé, restaure les objets SeaweedFS si l’archive en contient, puis demande le redémarrage de l’application.

Option Effet
--force Accepte une archive dont la version majeure diffère de la version courante, ou dont la master key ne correspond pas à celle de cet hôte
--skip-storage Ne restaure pas les objets SeaweedFS, même s’ils sont présents
--skip-secrets Ne réinstalle pas les secrets générés. La restauration exige alors que l’hôte détienne déjà la master key d’origine
--secrets-dir RÉPERTOIRE Destination des secrets générés (défaut : /var/lib/cenaclo/generated)
--config-dir RÉPERTOIRE Destination de l’instantané de configuration (défaut : /var/backups/cenaclo/restored-config)
--work-dir RÉPERTOIRE Répertoire de travail pour les fichiers déchiffrés (défaut : le répertoire de l’archive)
--restart-command COMMANDE Commande de redémarrage à exécuter à la place du redémarrage du conteneur
--no-restart Ne redémarre pas l’application après la restauration

Utilisez --skip-storage quand les objets sont restaurés par un autre outil, par exemple une synchronisation rclone depuis un stockage externe :

Fenêtre de terminal
docker compose --env-file infra/compose/.env -f infra/compose/docker-compose.yml exec -T backend \
/usr/local/bin/cenaclo-restore.sh --skip-storage /var/backups/cenaclo/cenaclo-backup-YYYYMMDDTHHMMSSZ.tar.gz.age

Le script compare la version inscrite dans le manifeste de l’archive à la version de l’instance courante, et refuse de restaurer quand les versions majeures diffèrent. Il refuse aussi quand le manifeste ne porte pas de version, ou quand l’une des deux versions n’est pas exploitable.

--force lève ce garde-fou. Ne l’utilisez qu’après avoir vérifié que le schéma de l’archive est compatible avec le code déployé. Le chemin le plus sûr reste l’inverse : redéployer l’instance sur la version d’origine de l’archive, puis restaurer sans --force. Voir Mettre à jour.

Par défaut, le script demande le redémarrage en terminant le processus principal du conteneur : l’orchestrateur — Coolify ou Docker Compose — relance le service. C’est le comportement attendu dans les deux parcours.

Hors conteneur, ce mécanisme n’existe pas et le script s’arrête avec une erreur explicite. Fournissez alors --restart-command avec votre commande de redémarrage, ou --no-restart si vous redémarrez vous-même ensuite.

  1. Réappliquez la configuration à la main si nécessaire. L’instantané déposé dans /var/backups/cenaclo/restored-config/<nom-de-l-archive> est là pour comparaison ; le script ne modifie aucune variable de Coolify ni de Compose.
  2. Vérifiez les sondes de santé des services backend et web.
  3. Connectez-vous avec un compte existant : c’est le contrôle qui prouve que la base et les secrets sont cohérents entre eux.
  4. Ouvrez un contenu média (pièce jointe, replay) pour confirmer que le stockage objet a bien suivi.
  5. Relancez une sauvegarde immédiatement, pour disposer d’un point de reprise sur l’état restauré.

Une archive .tar.gz.age sans sa passphrase est définitivement illisible. Aucune procédure, aucun script et aucun support ne peut la déchiffrer : c’est la contrepartie du chiffrement de bout en bout des sauvegardes.

Vérifiez donc dès aujourd’hui que la passphrase de sauvegarde et la passphrase de master key du wizard sont conservées hors du serveur, dans un gestionnaire de mots de passe. Ce sont deux valeurs distinctes.

En cas de doute sur une archive, faites l’essai de restauration sur une instance jetable avant d’en avoir besoin. Les pannes rencontrées pendant une restauration sont recensées dans Dépannage.