The errors and what they mean
| Error text | Meaning |
|---|---|
FATAL: no pg_hba.conf entry for host "10.0.0.5", user "app", database "sales", no encryption | No rule matches this client IP + user + database + SSL state |
Same, ending SSL encryption | A rule exists for non-SSL only, or for a different address |
FATAL: password authentication failed for user "app" | A rule matched, but the password (or method) is wrong |
FATAL: Ident authentication failed / Peer authentication failed | The matching rule uses ident/peer (OS user mapping), not a password |
could not connect to server: Connection refused | Not an auth problem: PostgreSQL isn't listening on that address or port |
SCRAM authentication requires libpq version 10 or above | Client library too old for scram-sha-256 |
How pg_hba.conf is evaluated
Each line is: TYPE DATABASE USER ADDRESS METHOD [options]. PostgreSQL reads rules top to bottom and uses the first one that matches connection type, database, user and address. If that first match is reject or the password fails, it does not try the next line.
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
hostssl sales app 10.0.0.0/24 scram-sha-256
host all all 127.0.0.1/32 scram-sha-256
hostnossl all all 0.0.0.0/0 reject
hostmatches SSL and non-SSL TCP;hostsslonly SSL;hostnosslonly non-SSL.localis Unix sockets only. Connecting with-h localhostuses TCP, sohostlines apply.
Step 1: confirm the server is listening
ss -ltnp | grep 5432
psql -U postgres -c "SHOW listen_addresses;" -c "SHOW port;"
listen_addresses = 'localhost' means remote clients get "connection refused", whatever pg_hba.conf says. Changing it needs a restart.
Step 2: find and read the active rules
SHOW hba_file;
SELECT line_number, type, database, user_name, address, netmask, auth_method, error
FROM pg_hba_file_rules
ORDER BY line_number;
pg_hba_file_rules shows the file as PostgreSQL parses it now, including an error column for lines that won't load. Check it before reloading.
Walk through the rules with the values from the error message (client IP, user, database, SSL or not) and find the first line that matches. That line is what PostgreSQL applied.
Step 3: add or fix the rule
Add a specific rule above any broader reject line:
hostssl sales app 10.0.0.0/24 scram-sha-256
Reload; no restart needed:
SELECT pg_reload_conf();
or pg_ctl reload -D $PGDATA / systemctl reload postgresql. Then check the log for "pg_hba.conf was not reloaded" errors.
Warning
If the edited file has a syntax error, PostgreSQL keeps the old rules on reload, but a restart with a broken file refuses all connections. Always check
pg_hba_file_rulesfor errors before restarting.
Step 4: fix password method mismatches
PostgreSQL 14+ defaults to password_encryption = scram-sha-256. Problems appear when the stored hash and the rule's method don't line up.
SHOW password_encryption;
SELECT rolname, left(rolpassword, 14) AS hash_type
FROM pg_authid
WHERE rolname = 'app'; -- needs superuser
| Stored hash | Rule method | Result |
|---|---|---|
SCRAM-SHA-256$... | scram-sha-256 | Works |
SCRAM-SHA-256$... | md5 | Works (md5 rules accept SCRAM) |
md5... | scram-sha-256 | Fails: re-set the password |
md5... | md5 | Works, but plan the SCRAM move |
Re-hash the password after setting password_encryption = 'scram-sha-256':
SET password_encryption = 'scram-sha-256';
\password app
Old drivers (very old JDBC, libpq < 10, some ODBC builds) can't do SCRAM. Upgrade the driver rather than downgrading the server to md5.
Step 5: SSL mismatches
- Client uses
sslmode=disableand onlyhostsslrules exist: "no pg_hba.conf entry ... no encryption". Setsslmode=require(orverify-full) on the client. - Check whether a session is encrypted:
SELECT pid, usename, client_addr, ssl, version
FROM pg_stat_ssl JOIN pg_stat_activity USING (pid)
WHERE usename = 'app';
Logging that helps
ALTER SYSTEM SET log_connections = on;
SELECT pg_reload_conf();
The server log then records connection attempts, including authentication failures with the user and host.
Managed services
You can't edit pg_hba.conf directly on managed PostgreSQL:
| Service | Equivalent controls |
|---|---|
| Azure Database for PostgreSQL Flexible Server | Firewall rules or private access (VNet), require_secure_transport, Entra ID auth |
| Amazon RDS / Aurora PostgreSQL | Security groups, rds.force_ssl parameter, IAM database authentication |
"no pg_hba.conf entry" on these services usually means an SSL requirement or a firewall rule not covering the client.
Prevent it next time
- Keep
pg_hba.confin configuration management with comments for every rule's owner. - Use specific CIDRs and named databases/users, and end the file with an explicit
reject. - Move all roles to SCRAM and set
password_encryption = scram-sha-256. - Require SSL (
hostssl) for every non-local connection.