From d159a4ef23e3eee03785a71e105c3349fe2335b7 Mon Sep 17 00:00:00 2001 From: Nathan FONTEYNE Date: Wed, 8 Jul 2026 13:51:11 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20parsing=20url=20cass=C3=A9=20par=20le=20?= =?UTF-8?q?mdp=20postgres?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 10 ++++++++-- README.md | 11 ++++++----- src/config.js | 12 +++++++++++- src/db/pool.js | 2 +- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index 4f5e88a..20331f4 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,15 @@ NODE_ENV=production PORT=3000 -# Postgres -DATABASE_URL=postgres://octane:changeme@postgres:5432/octane +# Postgres — the app connects with these discrete fields (not a DATABASE_URL), +# so POSTGRES_PASSWORD can safely contain any character without needing +# URL-encoding. Only POSTGRES_PASSWORD needs to be set; the rest already +# match the "postgres" service in docker-compose.yml. POSTGRES_PASSWORD=changeme +# PGHOST=postgres +# PGPORT=5432 +# PGDATABASE=octane +# PGUSER=octane # Sessions SESSION_SECRET=change-me-to-a-long-random-string diff --git a/README.md b/README.md index 45ea2a4..8a668a0 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,6 @@ cp .env.example .env Éditer `.env` (au minimum) : ``` -DATABASE_URL=postgres://octane:changeme@postgres:5432/octane POSTGRES_PASSWORD=changeme SESSION_SECRET=une-longue-chaine-aleatoire @@ -31,6 +30,8 @@ TRAEFIK_NETWORK_NAME=traefik-proxy APP_DOMAIN=octane.dandrove.com ``` +`POSTGRES_PASSWORD` est la seule variable Postgres à renseigner : l'app se connecte avec des champs séparés (host/port/base/utilisateur déjà pré-remplis avec les valeurs par défaut du service `postgres`), pas une URL unique — donc n'importe quel caractère spécial dans le mot de passe (généré par `openssl rand -base64` par exemple) fonctionne sans encodage particulier. + `AUTHENTIK_ISSUER_URL` utilise ici le nom du conteneur Authentik sur le réseau `traefik-proxy` (remplacez `authentik-server` par le vrai nom de service de votre stack Authentik — `docker ps` sur cette stack vous le donnera) plutôt que l'URL publique, pour éviter un aller-retour inutile par Traefik. L'URL publique fonctionne aussi si vous préférez. Pour générer `POSTGRES_PASSWORD` et `SESSION_SECRET` (valeurs aléatoires, à ne jamais commiter) : @@ -270,8 +271,8 @@ Le [Démarrage rapide](#démarrage-rapide-serveur-avec-traefik) ci-dessus couvre | Variable | Description | |---|---| -| `DATABASE_URL` | Chaîne de connexion Postgres (déjà cohérente avec le service `postgres` du compose) | -| `POSTGRES_PASSWORD` | Mot de passe du service Postgres | +| `POSTGRES_PASSWORD` | Mot de passe Postgres, utilisé à la fois par le service `postgres` et par l'app (connexion par champs séparés, pas d'URL — aucun caractère à encoder) | +| `PGHOST` / `PGPORT` / `PGDATABASE` / `PGUSER` | Optionnels, déjà cohérents par défaut avec le service `postgres` du compose (`postgres`/`5432`/`octane`/`octane`) | | `SESSION_SECRET` | Chaîne aléatoire longue pour signer les cookies de session | | `AUTHENTIK_ISSUER_URL` | URL d'issuer OIDC de l'application Authentik (interne, ex: `http://authentik-server:9000/application/o/octane-website/`, ou publique) | | `OIDC_CLIENT_ID` / `OIDC_CLIENT_SECRET` | Identifiants du provider Authentik | @@ -295,7 +296,6 @@ Dans `.env`, mettre : ``` DEV_BYPASS_AUTH=true -DATABASE_URL=postgres://octane:changeme@postgres:5432/octane POSTGRES_PASSWORD=changeme SESSION_SECRET=une-longue-chaine-aleatoire ``` @@ -312,7 +312,8 @@ Ou sans Docker du tout, avec un Postgres local : ```bash npm install -# démarrer un Postgres local, renseigner DATABASE_URL dans .env +# démarrer un Postgres local, puis dans .env : PGHOST=localhost (au lieu du +# nom de service Docker "postgres" par défaut) + POSTGRES_PASSWORD assorti npm run migrate npm start ``` diff --git a/src/config.js b/src/config.js index a2ee3cc..55b4b58 100644 --- a/src/config.js +++ b/src/config.js @@ -13,7 +13,17 @@ function required(name) { module.exports = { nodeEnv: process.env.NODE_ENV || 'development', port: parseInt(process.env.PORT, 10) || 3000, - databaseUrl: required('DATABASE_URL'), + // Discrete connection fields rather than a single DATABASE_URL: a + // password containing "/", "+", "=", "@" etc. (as produced by e.g. + // `openssl rand -base64`) would otherwise need manual URL-encoding + // to avoid breaking the connection string parser. + pg: { + host: process.env.PGHOST || 'postgres', + port: parseInt(process.env.PGPORT, 10) || 5432, + database: process.env.PGDATABASE || 'octane', + user: process.env.PGUSER || 'octane', + password: required('POSTGRES_PASSWORD'), + }, sessionSecret: required('SESSION_SECRET'), // DEV_BYPASS_AUTH lets you run the app locally without a real Authentik // instance: /auth/login prompts for a name instead of redirecting to OIDC. diff --git a/src/db/pool.js b/src/db/pool.js index 3dea200..d6e80b1 100644 --- a/src/db/pool.js +++ b/src/db/pool.js @@ -1,6 +1,6 @@ const { Pool } = require('pg'); const config = require('../config'); -const pool = new Pool({ connectionString: config.databaseUrl }); +const pool = new Pool(config.pg); module.exports = pool;