Sauvegarde et restauration
Cette fiche décrit comment sauvegarder et restaurer les données d'une instance TimePick : la base PostgreSQL (utilisateurs, événements, créneaux, réservations, modèles d'email) et le volume des fichiers uploadés (images insérées dans l'éditeur d'emails).
Hors périmètre
Cette fiche ne couvre pas les migrations de schéma ni le déroulé d'une mise à jour de version — voir Mettre à jour une instance.
Vue d'ensemble
Deux éléments à sauvegarder séparément :
- La base PostgreSQL — via
pg_dump, l'outil standard fourni avec PostgreSQL. - Le volume
/app/server/uploads— via une archivetardu volume Docker.
Les deux commandes (pg_dump, pg_restore, psql) doivent être disponibles sur la machine depuis laquelle vous les exécutez. Elles sont déjà présentes dans tout conteneur PostgreSQL officiel ; sur un poste local, elles s'installent avec le paquet client PostgreSQL de votre distribution.
Version du client
Utiliser un client pg_dump / pg_restore de version égale ou supérieure à celle du serveur PostgreSQL cible (PostgreSQL 17 par défaut sur une installation Coolify récente). Un client plus ancien que le serveur peut échouer ou produire une sauvegarde incomplète.
Sauvegarder la base de données
Formats disponibles
pg_dump propose plusieurs formats de sortie ; deux sont pertinents ici :
| Format | Option | Caractéristiques |
|---|---|---|
| Personnalisé (custom) | -F c | Compressé, restauration sélective possible avec pg_restore, format recommandé par défaut |
| Texte SQL brut (plain) | -F p | Fichier .sql lisible, portable avec n'importe quel client psql, pratique pour une inspection manuelle ou une archive de secours |
Commande de sauvegarde (format personnalisé)
Depuis une machine qui peut atteindre la base (voir Variables d'environnement pour l'URL de connexion, ou la section Coolify plus bas pour un accès sans exposition réseau) :
pg_dump -h <HOTE_DB> -p 5432 -U postgres -d timepick -F c -f timepick_$(date +%Y-%m-%d).dumpLe mot de passe est demandé de façon interactive, sauf s'il est fourni via la variable d'environnement PGPASSWORD ou un fichier ~/.pgpass.
Commande de sauvegarde (format SQL brut)
pg_dump -h <HOTE_DB> -p 5432 -U postgres -d timepick -F p -f timepick_$(date +%Y-%m-%d).sqlOù stocker les sauvegardes
- Ne jamais laisser la seule copie sur le même disque que le serveur : une panne matérielle du VPS emporterait à la fois la base et sa sauvegarde. Copier chaque sauvegarde vers un stockage distinct (poste local, stockage objet, autre machine).
- Nommer les fichiers avec une date explicite (comme dans les commandes ci-dessus) pour pouvoir identifier rapidement la sauvegarde la plus récente et purger les anciennes.
Fréquence recommandée
- Systématiquement avant toute mise à jour de version (voir le rappel en fin de fiche) — c'est le filet de sécurité principal en cas de migration problématique.
- À intervalle régulier au-delà de ce déclencheur ponctuel, selon le volume de réservations et la tolérance à la perte de données de votre organisation (par exemple quotidienne ou hebdomadaire) — TimePick ne fournit pas de mécanisme de sauvegarde automatique intégré ; la planification (cron, tâche planifiée) est à la charge de l'opérateur.
Cas Coolify — exécuter dans le conteneur PostgreSQL
Sur une instance Coolify (voir Déploiement sur un VPS avec Coolify), la base PostgreSQL tourne dans son propre conteneur, sans port exposé publiquement par défaut. Deux façons d'y exécuter pg_dump :
Option A — Terminal intégré Coolify
Coolify → projet TimePick → ressource timepick-db → onglet Terminal ouvre un shell directement dans le conteneur PostgreSQL. Depuis ce terminal :
pg_dump -U postgres -d timepick -F c -f /tmp/timepick_backup.dumpLe fichier reste dans le conteneur (/tmp) : il faut ensuite le récupérer sur l'hôte avec docker cp (option B) pour l'archiver ailleurs — le terminal intégré Coolify ne propose pas de téléchargement direct.
Option B — docker exec depuis l'hôte (SSH sur le VPS)
Identifier d'abord le nom exact du conteneur PostgreSQL :
docker ps --filter name=timepick-dbPuis exécuter pg_dump dans le conteneur en redirigeant la sortie directement vers un fichier sur l'hôte, sans étape docker cp intermédiaire :
docker exec <NOM_CONTENEUR_PG> pg_dump -U postgres -d timepick -F c > timepick_$(date +%Y-%m-%d).dumpC'est la méthode recommandée en Coolify : une seule commande, exécutable depuis une session SSH sur le VPS, qui produit directement un fichier sur l'hôte prêt à être copié ailleurs.
Sauvegarder le volume des uploads
Les images insérées dans l'éditeur d'emails sont stockées dans le volume monté sur /app/server/uploads (voir Installation en production (Docker) et Déploiement sur un VPS avec Coolify). Ce volume se sauvegarde indépendamment de la base.
Identifier le nom exact du volume attaché au conteneur applicatif :
docker inspect timepick --format '{{ range .Mounts }}{{ .Name }} -> {{ .Destination }}{{ "\n" }}{{ end }}'Archiver le contenu du volume dans un fichier tar.gz sur l'hôte, sans arrêter le conteneur applicatif (lecture seule pendant l'archivage) :
docker run --rm -v <NOM_VOLUME_UPLOADS>:/data -v "$(pwd)":/backup alpine tar czf /backup/timepick-uploads_$(date +%Y-%m-%d).tar.gz -C /data .Cette commande lance un conteneur alpine jetable qui monte le volume à sauvegarder en lecture et le dossier courant en écriture, puis archive le contenu.
Restaurer une sauvegarde
Arrêter l'application avant de restaurer
Une restauration ne doit jamais se faire pendant que l'application est en cours d'exécution : des écritures concurrentes pendant la restauration peuvent corrompre l'état de la base ou entrer en conflit avec les données restaurées. Arrêter le conteneur applicatif (Coolify → application → Stop, ou docker stop timepick) avant de commencer, et ne le redémarrer qu'une fois la restauration vérifiée.
Ordre des opérations
- Arrêter le conteneur applicatif (voir l'admonition ci-dessus) — la base reste accessible, seule l'application qui la sollicite est stoppée.
- Vider le schéma cible si vous restaurez par-dessus une base existante (voir ci-dessous) — la restauration se fait sur une base vide.
- Restaurer le dump avec
pg_restore(format personnalisé) oupsql(format SQL brut). - Redémarrer le conteneur applicatif.
- Vérifier (voir la section suivante).
Vider le schéma cible (base non vide)
Si la base cible contient déjà des données (restauration en place, par exemple après un incident), il faut d'abord repartir d'un schéma vide :
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;Irréversible
Cette commande supprime toutes les tables et toutes les données actuelles de la base (utilisateurs, événements, créneaux, réservations, modèles d'email). Elle n'est pertinente que juste avant une restauration immédiate depuis une sauvegarde. À exécuter via psql (terminal Coolify, docker exec, ou client GUI — voir les options d'accès dans le guide de déploiement).
Si la base cible est nativement vide (nouvelle instance, nouvelle base PostgreSQL fraîchement créée), cette étape est inutile.
Restaurer un dump au format personnalisé
pg_restore -h <HOTE_DB> -p 5432 -U postgres -d timepick timepick_<DATE>.dumpEn Coolify, via docker exec avec redirection de l'entrée standard depuis l'hôte :
docker exec -i <NOM_CONTENEUR_PG> pg_restore -U postgres -d timepick < timepick_<DATE>.dumpRestaurer un dump au format SQL brut
psql -h <HOTE_DB> -p 5432 -U postgres -d timepick -f timepick_<DATE>.sqlRestaurer le volume des uploads
Sens inverse de la sauvegarde : extraire l'archive dans le volume cible (conteneur applicatif arrêté) :
docker run --rm -v <NOM_VOLUME_UPLOADS>:/data -v "$(pwd)":/backup alpine tar xzf /backup/timepick-uploads_<DATE>.tar.gz -C /dataVérifier après une restauration
Trois vérifications, dans cet ordre, une fois le conteneur applicatif redémarré :
- Le healthcheck répond :
curl https://votre-domaine.tld/healthDoit renvoyer un code 200 avec un statut ok (ou degraded si le SMTP n'est pas encore configuré, ce qui n'indique pas un problème de restauration).
La connexion fonctionne — se connecter avec un compte existant dans la sauvegarde restaurée (magic link ou code de secours) et confirmer l'accès au tableau de bord.
Un comptage de cohérence — comparer un nombre de lignes attendu avec ce qui a été restauré, par exemple :
SELECT COUNT(*) FROM users;Un résultat à 0 ou manifestement incohérent avec ce qui était attendu signale une restauration incomplète — vérifier les messages d'erreur affichés par pg_restore ou psql pendant l'opération avant de considérer la restauration terminée.
Rappel : sauvegarder avant toute mise à jour
Une mise à jour de version applique de nouvelles migrations de base de données, qui sont forward-only (pas de rollback automatique). Effectuer une sauvegarde de la base avant de lancer une mise à jour n'est pas optionnel — voir Mettre à jour une instance.