PostgreSQL: understanding and resolving the "peer authentication failed" error#
1) Understanding the error and when it occurs#
During the configuration of PostgreSQL on Linux systems, this specific error frequently appears in both production and staging environments:
psql -U domain_user -d app_database -W -c "\dt"
Resulting Output:
FATAL: Peer authentication failed for user "domain_user"
In the vast majority of cases, the password is correct and the user exists, yet the connection is decisively rejected. The problem is almost always an authentication policy applied to the wrong connection type, rather than an invalid credential.
2) The source of truth: pg_hba.conf#
On Linux systems, the host-based authentication (HBA) file path varies by distribution:
# Debian / Ubuntu (postgresql-common package)
/etc/postgresql/{VERSION}/main/pg_hba.conf
# RHEL / CentOS / AlmaLinux / Rocky Linux
/var/lib/pgsql/{VERSION}/data/pg_hba.conf
To definitively identify the active configuration file without guessing:
sudo -u postgres psql -tAc 'SHOW hba_file;'
A common line responsible for this behavior looks like this:
# TYPE DATABASE USER METHOD
local all all peer
Operational Breakdown:
local: Refers to connections made via the Unix-domain socket (connections without-h).all: Applies to all databases and all users.peer: Validates based on OS identity (the Linux user running the command must match the database role), bypassing traditional password checks.
3) Confirming diagnosis in the server log#
To inspect rejected connections and verify which rule was triggered:
# View recent PostgreSQL logs
sudo journalctl -u postgresql --no-pager -n 20
If the log displays FATAL: Peer authentication failed for user "domain_user", the connection hit a local rule configured with the peer method where the caller's system UID did not match the requested role.
4) Remediation strategies (pros and cons)#
Option 1: Execute as matching OS user#
If the environment relies on controlled local execution, the most direct fix is to align the OS user with the database role:
sudo -u domain_user psql -d app_database
- Best For: Internal cron jobs, local automation, or root-to-service-account transitions.
Option 2: Force TCP connection (troubleshooting bypass)#
To quickly bypass local socket rules and validate whether your password is valid:
psql -h 127.0.0.1 -U domain_user -d app_database -W
This forces evaluation of host rules in pg_hba.conf, which typically accept password authentication.
Option 3: Migrate to scram-sha-256 (recommended for production)#
For full-stack applications and services that require strong local password authentication over Unix sockets, the definitive fix is to update the authentication method in pg_hba.conf.
- Update the password hash in the database to ensure SCRAM compatibility:
-- Run connected as superuser postgres
SET password_encryption = 'scram-sha-256';
ALTER ROLE domain_user PASSWORD 'your_strong_password';
- Edit the
pg_hba.confconfiguration file:
sudo nano $(sudo -u postgres psql -tAc 'SHOW hba_file;')
Rule Ordering Is Critical: PostgreSQL evaluatespg_hba.confrules from top to bottom and applies the first match. If you append your new rule to the end of the file, the genericlocal all all peerrule will match first and override it. Always place user-specific rules ABOVE the generic catch-all:
# Specific rule for application user (ABOVE generic catch-all)
local all domain_user scram-sha-256
# Standard generic rule (below)
local all all peer
- Reload PostgreSQL without dropping existing connections:
# Graceful reload (zero downtime)
sudo systemctl reload postgresql
# Or directly via SQL:
# sudo -u postgres psql -c 'SELECT pg_reload_conf();'
- Validate the connection:
psql -U domain_user -d app_database -W -c "SELECT current_user;"
5) What to avoid in production#
- Never use
trustin production: Whiletrustimmediately removes the authentication hurdle, it allows any local user or rogue process to connect without verification. - Avoid legacy
md5in new setups: MD5 is vulnerable to hash collisions and offline cracking. PostgreSQL 14+ defaults toscram-sha-256.
6) Technical method comparison#
| Method | Requires Password? | OS-Identity Based? | Recommended Usage |
|---|---|---|---|
peer | No | Yes | Local admin via SSH and strictly controlled scripts |
trust | No | No | Temporary lab environments only (NEVER in production) |
scram-sha-256 | Yes | No | Web apps, modern production, compliance-heavy sites |
Practical takeaways#
Peer authentication failed is not a bug; it is an active security mechanism working as designed.
The definitive solution requires understanding how pg_hba.conf parses rules sequentially, choosing the correct connection type (socket vs TCP), and deploying modern scram-sha-256 authentication when applications rely on password credentials.
Was this article helpful?
Leave a quick reaction to help prioritize future technical guides:
This post is licensed under CC BY-NC.



Comments
Join the discussion below.
0 comments