Tight pg_hba.conf rules decide who gets a seat at the PostgreSQL table and who gets shown the door, making them a primary control for preventing accidental exposure of port 5432.
The file contains host-based authentication (HBA) records that match on connection type (local for Unix sockets, host for TCP), target database, role name, and client address. PostgreSQL evaluates the file from top to bottom and applies the first matching record to every new connection attempt, so specificity and ordering determine the effective access policy.
A single permissive line near the top can override intended restrictions, and an overly strict change can lock out remote administration. Always locate the live file using SHOW hba_file;, prefer scram-sha-256 over legacy md5 where possible, and reload the server so only new connections see the updated policy.
Related: How to restrict remote access in PostgreSQL \\
Related: How to enable SSL for PostgreSQL connections
$ sudo -u postgres psql -Atc 'SHOW hba_file;' /etc/postgresql/16/main/pg_hba.conf
$ sudo cp -a /etc/postgresql/16/main/pg_hba.conf /etc/postgresql/16/main/pg_hba.conf.bak
$ sudoedit /etc/postgresql/16/main/pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD host appdb appuser 192.0.2.0/24 scram-sha-256
Records are whitespace-separated fields in the order TYPE, DATABASE, USER, ADDRESS, and METHOD.
# A single host should appear above a broader subnet match. host appdb appuser 192.0.2.40/32 scram-sha-256 host appdb appuser 192.0.2.0/24 scram-sha-256
Use hostssl instead of host to require TLS at the server side for that rule.
# Allow the trusted subnet first. host appdb appuser 192.0.2.0/24 scram-sha-256 # Reject everything else over TCP. host all all 0.0.0.0/0 reject host all all ::/0 reject
A broad allow rule above specific entries can silently punch a hole through the policy, and a catch-all reject blocks loopback TCP unless explicit 127.0.0.1/32 and ::1/128 rules appear above it.
$ sudo -u postgres psql -c "SELECT pg_reload_conf();" pg_reload_conf ---------------- t (1 row)
Existing sessions remain connected, and only new connections are checked against the updated rules.
$ sudo -u postgres psql -c 'SELECT line_number, error FROM pg_hba_file_rules WHERE error IS NOT NULL;' line_number | error -------------+------- (0 rows)
Switching to scram-sha-256 requires role passwords stored in SCRAM format and clients new enough to support SCRAM.
$ psql "host=host.example.net dbname=appdb user=appuser sslmode=require" -c 'SELECT current_user, inet_client_addr();' current_user | inet_client_addr --------------+----------------- appuser | 192.0.2.40 (1 row)
$ psql "host=203.0.113.50 dbname=appdb user=appuser sslmode=disable" -c 'SELECT 1;' psql: error: connection to server at "203.0.113.50", port 5432 failed: FATAL: pg_hba.conf rejects connection for host "203.0.113.55", user "appuser", database "appdb", no encryption