diff --git a/.env.example b/.env.example index c7fc989..fdc7c5c 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,18 @@ # Copy to .env next to docker-compose.yml and fill in. -# Full connection string to your shared Postgres on the `backend` network. -# Use the Postgres container/service name as the host (e.g. `postgres`). -# Create the database first: CREATE DATABASE albion; -DATABASE_URL=postgres://albion:CHANGE_ME@postgres:5432/albion - +# Shared Postgres on the `backend` network. The host is the Postgres +# CONTAINER/SERVICE name (see `docker network inspect backend`), not localhost. +# +# Option A — one URL. URL-encode special chars in the password (@ -> %40, : -> %3A): +# DATABASE_URL=postgres://albion_user:CHANGE_ME@postgres:5432/albion +# +# Option B — discrete vars (no encoding needed). Leave DATABASE_URL unset if you use these: +PGHOST=postgres +PGPORT=5432 +PGUSER=albion_user +PGPASSWORD=CHANGE_ME +PGDATABASE=albion +705a4391e055a633ce001ece39abd888619ce5a3bfb4cfe329d72d4d7fb83ba4 # Bearer token the web UI and the Windows agent must send. Generate one, e.g.: # openssl rand -hex 32 ALBION_API_KEY=change-me-to-a-long-random-string diff --git a/docker-compose.yml b/docker-compose.yml index 15d3b41..7dbc3a3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,10 +7,16 @@ services: container_name: albion-economy restart: unless-stopped environment: - # Shared Postgres reachable on the internal `backend` network. Set the full - # URL in a .env file next to this compose, e.g. - # DATABASE_URL=postgres://albion:pw@postgres:5432/albion - DATABASE_URL: ${DATABASE_URL:?set DATABASE_URL in .env} + # Shared Postgres on the internal `backend` network. EITHER set the full URL: + # DATABASE_URL=postgres://albion_user:pw@:5432/albion + # (URL-encode special chars in the password: @ -> %40, : -> %3A, etc.) + # OR use the discrete vars below (no encoding needed) and leave DATABASE_URL empty. + DATABASE_URL: ${DATABASE_URL:-} + PGHOST: ${PGHOST:-} + PGPORT: ${PGPORT:-5432} + PGUSER: ${PGUSER:-} + PGPASSWORD: ${PGPASSWORD:-} + PGDATABASE: ${PGDATABASE:-} # REQUIRED for public deployment — the agent and web UI send this as a # Bearer token. Set it in .env too. ALBION_API_KEY: ${ALBION_API_KEY:?set ALBION_API_KEY in .env} diff --git a/server/src/db/index.ts b/server/src/db/index.ts index 25e7777..5d03608 100644 --- a/server/src/db/index.ts +++ b/server/src/db/index.ts @@ -127,10 +127,25 @@ let pool: pg.Pool | null = null; export function getPool(): pg.Pool { if (!pool) { const connectionString = process.env.DATABASE_URL; - if (!connectionString) { - throw new Error('DATABASE_URL is not set (e.g. postgres://user:pass@postgres:5432/albion)'); + if (connectionString) { + pool = new pg.Pool({ connectionString, max: 10 }); + } else if (process.env.PGHOST || process.env.PGUSER || process.env.PGDATABASE) { + // Fall back to discrete PG* env vars. This avoids URL-encoding the password + // (a special char like `@` in DATABASE_URL otherwise mangles the host). + pool = new pg.Pool({ + host: process.env.PGHOST, + port: process.env.PGPORT ? Number(process.env.PGPORT) : 5432, + user: process.env.PGUSER, + password: process.env.PGPASSWORD, + database: process.env.PGDATABASE, + max: 10, + }); + } else { + throw new Error( + 'No database configured. Set DATABASE_URL (postgres://user:pass@host:5432/albion) ' + + 'or the discrete PGHOST/PGPORT/PGUSER/PGPASSWORD/PGDATABASE env vars.', + ); } - pool = new pg.Pool({ connectionString, max: 10 }); } return pool; }