From b03ed9a2f29cb6f88881ef48ab8a9edd6ac6cff7 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sat, 3 Oct 2026 21:35:15 -0400 Subject: [PATCH] =?UTF-8?q?fix(compose):=20publish=20db=20on=20loopback=20?= =?UTF-8?q?only=20=E2=80=94=20was=20reachable=20from=20any=20LAN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unqualified 0.0.0.0 publish put Postgres on every interface, and Docker delivers published ports through PREROUTING DNAT into the FORWARD path — ufw's default deny incoming never sees those packets. Result: the database was reachable from whatever network the laptop joined (home, guest Wi-Fi, hotel), not just from the host. Bind to 127.0.0.1/[::1] instead: with no DNAT matching LAN-destined packets, they fall back to INPUT where the firewall actually applies. Host-side tools keep working over the loopback publish (both families bound because localhost may resolve to ::1 first); app↔db and tests↔db are untouched — they use the db service name on the compose network, which never traverses iptables on this host (br_netfilter not loaded). If LAN access to the DB is ever wanted again, revert to an unqualified publish and rely on DOCKER-USER home-subnet scoping instead of an open binding. --- docker-compose.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 9a7d1bf..ec12944 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,8 @@ services: # Make other volumes as needed - ./uploads:/app/uploads ports: - - "${DB_PORT:-5432}:${DB_PORT:-5432}" + - "127.0.0.1:${DB_PORT:-5432}:${DB_PORT:-5432}" + - "[::1]:${DB_PORT:-5432}:${DB_PORT:-5432}" healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 30s