From cc699799a63ea7aed77c94aa3b6361b19e48e640 Mon Sep 17 00:00:00 2001 From: Josh France <12610835+16francej@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:02:18 -0400 Subject: [PATCH 1/2] Read local Postgres settings from the assembled env, not process.env MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The supervisor is spawned with only the caller's env; dev.env is merged into assembled.env later by assembleEnv(). ensureLocalPostgres() read DEV_INSTANCE_POSTGRES_* from process.env, so a port/container/password configured in dev.env never reached it — it defaulted to 55432 and, on a machine where that port belongs to a different Postgres container, up failed with 'password authentication failed for user postgres'. Thread the assembled env through instead. --- scripts/dev/lib/postgres.ts | 16 ++++++++++------ scripts/dev/supervisor/main.ts | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/scripts/dev/lib/postgres.ts b/scripts/dev/lib/postgres.ts index 9a7b1f3e..6d641bc8 100644 --- a/scripts/dev/lib/postgres.ts +++ b/scripts/dev/lib/postgres.ts @@ -67,12 +67,16 @@ export interface LocalPostgres { url: string; } -export async function ensureLocalPostgres(worktree: string, log: (msg: string) => void): Promise { - const container = process.env.DEV_INSTANCE_POSTGRES_CONTAINER || "qm-dev-postgres"; - const port = process.env.DEV_INSTANCE_POSTGRES_PORT || "55432"; - const image = process.env.DEV_INSTANCE_POSTGRES_IMAGE || POSTGRES_IMAGE; - const password = process.env.DEV_INSTANCE_POSTGRES_PASSWORD || "qm-dev"; - const volume = process.env.DEV_INSTANCE_POSTGRES_VOLUME || "qm-dev-postgres-data"; +export async function ensureLocalPostgres( + worktree: string, + env: Record, + log: (msg: string) => void, +): Promise { + const container = env.DEV_INSTANCE_POSTGRES_CONTAINER || "qm-dev-postgres"; + const port = env.DEV_INSTANCE_POSTGRES_PORT || "55432"; + const image = env.DEV_INSTANCE_POSTGRES_IMAGE || POSTGRES_IMAGE; + const password = env.DEV_INSTANCE_POSTGRES_PASSWORD || "qm-dev"; + const volume = env.DEV_INSTANCE_POSTGRES_VOLUME || "qm-dev-postgres-data"; const dbName = worktreeDbName(worktree); if (!(await ensureDockerDaemon(log))) throw new Error("docker daemon unavailable"); diff --git a/scripts/dev/supervisor/main.ts b/scripts/dev/supervisor/main.ts index 5eedb307..9bd2437f 100644 --- a/scripts/dev/supervisor/main.ts +++ b/scripts/dev/supervisor/main.ts @@ -343,7 +343,7 @@ async function assembleAndPrepare(spec: BootSpec): Promise { let durableAdminPrincipal = ""; if (!databaseUrl) { try { - const pg = await ensureLocalPostgres(worktree, log); + const pg = await ensureLocalPostgres(worktree, assembled.env, log); databaseUrl = pg.url; localPg = true; } catch (err) { From dcb2266d14f7e543b29e93d065003a1be7f11573 Mon Sep 17 00:00:00 2001 From: Josh France <12610835+16francej@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:12:39 -0400 Subject: [PATCH 2/2] URL-encode the local Postgres password in the connection string --- scripts/dev/lib/postgres.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dev/lib/postgres.ts b/scripts/dev/lib/postgres.ts index 6d641bc8..a6681ec2 100644 --- a/scripts/dev/lib/postgres.ts +++ b/scripts/dev/lib/postgres.ts @@ -134,5 +134,5 @@ export async function ensureLocalPostgres( throw new Error(`createdb ${dbName} failed`); } log(`durability: using local Postgres container ${container} database ${dbName}`); - return { url: `postgres://postgres:${password}@127.0.0.1:${port}/${dbName}` }; + return { url: `postgres://postgres:${encodeURIComponent(password)}@127.0.0.1:${port}/${dbName}` }; }