Skip to content

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 :

  1. La base PostgreSQL — via pg_dump, l'outil standard fourni avec PostgreSQL.
  2. Le volume /app/server/uploads — via une archive tar du 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 :

FormatOptionCaractéristiques
Personnalisé (custom)-F cCompressé, restauration sélective possible avec pg_restore, format recommandé par défaut
Texte SQL brut (plain)-F pFichier .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) :

bash
pg_dump -h <HOTE_DB> -p 5432 -U postgres -d timepick -F c -f timepick_$(date +%Y-%m-%d).dump

Le 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)

bash
pg_dump -h <HOTE_DB> -p 5432 -U postgres -d timepick -F p -f timepick_$(date +%Y-%m-%d).sql

Où 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 :

bash
pg_dump -U postgres -d timepick -F c -f /tmp/timepick_backup.dump

Le 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 :

bash
docker ps --filter name=timepick-db

Puis 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 :

bash
docker exec <NOM_CONTENEUR_PG> pg_dump -U postgres -d timepick -F c > timepick_$(date +%Y-%m-%d).dump

C'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 :

bash
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) :

bash
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

  1. Arrêter le conteneur applicatif (voir l'admonition ci-dessus) — la base reste accessible, seule l'application qui la sollicite est stoppée.
  2. Vider le schéma cible si vous restaurez par-dessus une base existante (voir ci-dessous) — la restauration se fait sur une base vide.
  3. Restaurer le dump avec pg_restore (format personnalisé) ou psql (format SQL brut).
  4. Redémarrer le conteneur applicatif.
  5. 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 :

sql
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é

bash
pg_restore -h <HOTE_DB> -p 5432 -U postgres -d timepick timepick_<DATE>.dump

En Coolify, via docker exec avec redirection de l'entrée standard depuis l'hôte :

bash
docker exec -i <NOM_CONTENEUR_PG> pg_restore -U postgres -d timepick < timepick_<DATE>.dump

Restaurer un dump au format SQL brut

bash
psql -h <HOTE_DB> -p 5432 -U postgres -d timepick -f timepick_<DATE>.sql

Restaurer le volume des uploads

Sens inverse de la sauvegarde : extraire l'archive dans le volume cible (conteneur applicatif arrêté) :

bash
docker run --rm -v <NOM_VOLUME_UPLOADS>:/data -v "$(pwd)":/backup alpine tar xzf /backup/timepick-uploads_<DATE>.tar.gz -C /data

Vérifier après une restauration

Trois vérifications, dans cet ordre, une fois le conteneur applicatif redémarré :

  1. Le healthcheck répond :
bash
curl https://votre-domaine.tld/health

Doit 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).

  1. 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.

  2. Un comptage de cohérence — comparer un nombre de lignes attendu avec ce qui a été restauré, par exemple :

sql
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.

Publié sous licence FSL-1.1-MIT.