Percio Castelo.
PT Resume
PostgreSQL: understanding and resolving the "peer authentication failed" error
← Back to blog

PostgreSQL: understanding and resolving the "peer authentication failed" error

6/7/2026 · 3 min · Development · 834 views

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.

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.

  1. 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';
  1. Edit the pg_hba.conf configuration file:
sudo nano $(sudo -u postgres psql -tAc 'SHOW hba_file;')
Rule Ordering Is Critical: PostgreSQL evaluates pg_hba.conf rules from top to bottom and applies the first match. If you append your new rule to the end of the file, the generic local all all peer rule 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
  1. 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();'
  1. Validate the connection:
psql -U domain_user -d app_database -W -c "SELECT current_user;"

5) What to avoid in production#

  1. Never use trust in production: While trust immediately removes the authentication hurdle, it allows any local user or rogue process to connect without verification.
  2. Avoid legacy md5 in new setups: MD5 is vulnerable to hash collisions and offline cracking. PostgreSQL 14+ defaults to scram-sha-256.

6) Technical method comparison#

MethodRequires Password?OS-Identity Based?Recommended Usage
peerNoYesLocal admin via SSH and strictly controlled scripts
trustNoNoTemporary lab environments only (NEVER in production)
scram-sha-256YesNoWeb 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:

834 reads
Creative Commons Attribution-NonCommercial

This post is licensed under CC BY-NC.

Comments

Join the discussion below.

0 comments