From 79e1dc4144db3c072dc64912f1fcbf2d24e3c22e Mon Sep 17 00:00:00 2001 From: emil Date: Sat, 16 May 2026 02:56:53 +0300 Subject: [PATCH] =?UTF-8?q?fix(deploy):=20lock=20down=20postgres=20?= =?UTF-8?q?=E2=80=94=20no=20public=20port=20+=20password=20via=20.env?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yesterday's prod incident exposed postgres on 0.0.0.0:5432 with the default 'postgres:postgres' credentials. A scanner ransomware bot brute-forced it and dropped the database (left a readme_to_recover note). We restored from a pre-incident dump and the user data is back, but the underlying weakness was in this docker-compose.yml. Changes: - Remove `ports: "5432:5432"` from the postgres service entirely. Postgres is reachable only via the internal docker network. For ad-hoc admin access, use an SSH tunnel: `ssh -L 5432:localhost:5432 deploy@` - POSTGRES_PASSWORD now reads from `${POSTGRES_PASSWORD:-postgres}` via env interpolation. Prod `.env` (not in repo) provides the real value; local dev gets the `postgres` fallback so `docker compose up` still works without setup. - Remove the no-longer-needed DATABASE_URL override in the app service `environment:` — `env_file: .env` already supplies it. After this lands, the deploy pipeline will rsync the new compose.yml, recreate containers with no exposed pg port, and substitute the strong password from .env at container start. Volumes persist, data intact. Co-Authored-By: Claude Opus 4.7 --- docker-compose.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3fcf464..c2c07df 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,6 @@ services: - NODE_ENV=production - HOST=0.0.0.0 - PORT=4321 - - DATABASE_URL=postgresql://postgres:postgres@postgres:5432/randify depends_on: postgres: condition: service_healthy @@ -23,11 +22,11 @@ services: postgres: image: postgres:16-alpine - ports: - - "5432:5432" + # No public port mapping: Postgres is reachable only via the internal + # docker network. Use an SSH tunnel for ad-hoc admin access. environment: - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres} - POSTGRES_DB=randify volumes: - postgres_data:/var/lib/postgresql/data