From 90e069f66a376e8473bf3252aa27a63bd0027306 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 10 Aug 2026 06:25:45 +0000 Subject: [PATCH] =?UTF-8?q?Nommer=20le=20vrai=20obstacle=20:=20le=20mot=20?= =?UTF-8?q?de=20passe=20grav=C3=A9=20dans=20le=20volume?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le diagnostic disait « mot de passe d'amorçage erroné » sans dire pourquoi cela arrive, et on cherchait du côté du rôle applicatif — qui n'y est pour rien. `POSTGRES_PASSWORD` n'est lu qu'à l'initialisation du volume de la base. Un volume créé lors d'un déploiement antérieur, fût-il un déploiement qui avait échoué pour une autre raison, garde le mot de passe d'alors ; le changer dans la pile n'y touche pas, le volume ne se réinitialise jamais. Le compte d'amorçage est alors refusé, l'application ne peut plus réparer le rôle applicatif, et le seul symptôme visible est un P1000 qui désigne le mauvais coupable. Le message nomme désormais ce cas et donne les deux issues : repartir d'un volume neuf quand la base est vide, ou réaligner le mot de passe par la socket locale — que l'image PostgreSQL accepte sans l'ancien. Éprouvé sur la panne réelle, sous authentification par mot de passe. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Cr9dkEHwbDgkWPnyGj1Rjv --- README.md | 28 +++++++++++++++++++++++ docker/bootstrap-role.mjs | 48 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e91d15c..d7e170d 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,34 @@ Les autres ont une valeur par défaut utilisable : `POSTGRES_PASSWORD`, `POSTGRE **Après le premier déploiement, relevez la clé dans les journaux du conteneur `app` et conservez-la hors du serveur.** +### Si l’application ne démarre pas : `P1000` + +Le journal du conteneur `app` dit toujours quoi faire. Trois cas, dans l’ordre de fréquence. + +**`[bootstrap] Le compte d’amorçage « planflow » est lui-même refusé.`** + +C’est le piège classique de PostgreSQL en conteneur, et il n’a rien à voir avec le rôle applicatif. **`POSTGRES_PASSWORD` n’est lu qu’à l’initialisation du volume.** Un volume créé lors d’un déploiement antérieur — y compris un déploiement qui avait échoué pour une autre raison — garde le mot de passe d’alors. Le changer dans la pile n’y touche pas : le volume ne se réinitialise jamais. + +La base est encore vide ? Repartez d’un volume neuf, c’est le plus sûr : + +```bash +docker compose down +docker volume rm planflow_db-data +docker compose up -d +``` + +La base contient déjà quelque chose ? Réalignez le mot de passe. L’image PostgreSQL fait confiance aux connexions par socket locale, donc l’ancien mot de passe n’est pas nécessaire : + +```bash +docker compose exec db psql -U planflow \ + -c "ALTER USER planflow PASSWORD 'planflow-interne';" +docker compose restart app +``` + +**`[bootstrap] Aucun identifiant d’amorçage fourni`** — le service `app` n’a pas `POSTGRES_PASSWORD`. Il l’a par défaut dans le compose fourni ; son absence signale une variable vidée à la main. + +**Aucune ligne `[bootstrap]` du tout** — l’image tourne sur une version antérieure à ce mécanisme. Reconstruisez-la (`docker compose up -d --build`, ou dans Portainer *Update the stack* avec *Re-pull image and redeploy*). Un simple redémarrage réutilise l’image existante. + ### Première installation Les migrations posent le schéma, rien de plus : une instance neuve n'a **aucun compte et aucun utilisateur**. Le jeu de données de démonstration (`pnpm db:seed`) n'y remédie pas et refuse de tourner en production, à raison — personne ne veut de « Maison Rivage » et de salariés fictifs dans son registre du personnel. diff --git a/docker/bootstrap-role.mjs b/docker/bootstrap-role.mjs index 810f6cb..8ba4294 100644 --- a/docker/bootstrap-role.mjs +++ b/docker/bootstrap-role.mjs @@ -106,9 +106,51 @@ try { } catch (error) { // Non bloquant : le rôle est peut-être déjà correct et posé par `db-init`. // Faire échouer le démarrage ici priverait d'une installation qui marche. - console.error( - `[bootstrap] Provisionnement impossible (${error instanceof Error ? error.message : String(error)}).`, - ); + const message = error instanceof Error ? error.message : String(error); + console.error(`[bootstrap] Provisionnement impossible (${message}).`); + + // Le cas de très loin le plus fréquent, et le moins évident : le compte + // d'amorçage lui-même est refusé. + // + // `POSTGRES_PASSWORD` n'est lu qu'à **l'initialisation du volume**. Un volume + // créé lors d'un déploiement antérieur garde le mot de passe d'alors, et le + // changer dans la pile n'y touche pas — le volume ne se réinitialise jamais. + // Sans cette explication, on cherche indéfiniment du côté du rôle applicatif, + // qui n'y est pour rien. + if (/password authentication failed/i.test(message)) { + console.error(''); + console.error( + `[bootstrap] Le compte d’amorçage « ${superUser} » est lui-même refusé.`, + ); + console.error( + '[bootstrap] POSTGRES_PASSWORD n’est lu qu’à la création du volume de la', + ); + console.error( + '[bootstrap] base. Si ce volume vient d’un déploiement antérieur, il porte', + ); + console.error( + '[bootstrap] encore l’ancien mot de passe, et le changer dans la pile n’y', + ); + console.error('[bootstrap] change rien.'); + console.error(''); + console.error('[bootstrap] • Base encore vide — repartir d’un volume neuf :'); + console.error('[bootstrap] docker compose down'); + console.error('[bootstrap] docker volume rm planflow_db-data'); + console.error('[bootstrap] docker compose up -d'); + console.error(''); + console.error('[bootstrap] • Base à conserver — réaligner le mot de passe.'); + console.error( + '[bootstrap] Par la socket locale, qui ne demande pas l’ancien :', + ); + console.error( + `[bootstrap] docker compose exec db psql -U ${superUser} \\`, + ); + console.error( + `[bootstrap] -c "ALTER USER ${superUser} PASSWORD '';"`, + ); + console.error(''); + } + console.error( '[bootstrap] La suite dira si le rôle applicatif est utilisable en l’état.', );