Check listen_addresses before you change it
postgresql.conflisten_addresses = 'localhost' # the default; loopback only# or, to serve a private network explicitly:listen_addresses = 'localhost,10.0.0.5'listen_addresses requires a restart, not a reload.
Read this before you change anything
Section titled “Read this before you change anything”The default is already localhost. PostgreSQL’s own default allows only
local TCP/IP loopback connections. A great deal of hardening advice tells you to
set listen_addresses = 'localhost', which on a stock cluster changes nothing at
all.
That makes this control unusual: the value is rarely wrong by accident. It is wrong because something changed it deliberately, and the useful question is what, not what should it be.
The two common answers:
- The official Docker image sets
listen_addresses = '*'. This is correct for a container — a database that only accepts loopback connections inside its own network namespace is useless to every other container. The exposure comes from the published port, not the setting. - Someone needed a remote connection.
*made it work, and the change stayed long after the specific need went away.
Why ‘*’ is not automatically the bug
Section titled “Why ‘*’ is not automatically the bug”It’s tempting to treat listen_addresses = '*' as the finding and revert it.
Often that’s wrong, and it breaks things while fixing nothing.
listen_addresses decides which interfaces the server binds. It says nothing
about who may connect — that is pg_hba.conf,
and it is the control that actually authorises. A cluster listening on * with
tight host rules and a firewall is fine. A cluster listening on localhost with
host all all 0.0.0.0/0 trust is not saved by the narrow listener; it just needs
one port-forward to become catastrophic.
So the order of operations is: fix the rules first, then decide about the
listener. If pg_hba.conf is scoped and the port is firewalled, narrowing
listen_addresses is defence in depth. If it isn’t, narrowing the listener is
a fig leaf.
In containers, don’t fight the image. Leave * and control exposure at the
publish and network layer — -p 127.0.0.1:5432:5432 rather than -p 5432:5432,
or no published port at all when only sibling containers need it.
Related
Section titled “Related”- Scope pg_hba.conf rules — the control that actually authorises.
- Postgres exposed to the internet — what a wide listener plus a wide rule buys you.