If you've just installed PostgreSQL on a fresh VPS and tried to log in the way you'd expect, you've probably already hit this wall: psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "postgres". It's one of the most common first-hour PostgreSQL problems on a bare Linux server, and the fix is quick once you understand what "peer" actually means.

Symptom

You install PostgreSQL with something like apt install postgresql or dnf install postgresql-server, start the service, and then try to connect:

$ psql -U postgres
psql: error: FATAL:  Peer authentication failed for user "postgres"

Or you try connecting as your own Linux user with a password:

$ psql -U myappuser -d mydb -W
psql: error: FATAL:  Peer authentication failed for user "myappuser"

Sometimes it shows up differently depending on the client — a Node.js or Django app throws a generic "password authentication failed" or "no pg_hba.conf entry" error instead, especially once you start connecting over TCP (-h 127.0.0.1) rather than the local Unix socket.

Cause

PostgreSQL ships with a few different authentication methods, and Debian/Ubuntu and RHEL-family distros both default the local Unix-socket connections to peer authentication. Peer auth doesn't ask for a password at all — it checks that the Linux OS user you're logged in as matches (or is mapped to) the PostgreSQL role you're trying to connect as. So:

  • If you're logged in as root or your own sudo user and run psql -U postgres, peer auth fails because your OS username isn't postgres.
  • If you switch to the postgres Linux user first, plain psql works fine, because now the OS user and DB role match.
  • Once you try connecting from a remote app or over TCP with a password, you're hitting a different rule in the same file, and if that rule is also set to peer or ident, no password will ever be accepted.

All of this is controlled by one file: pg_hba.conf (host-based authentication). It's a simple top-to-bottom rule list — the first matching line for your connection type, database, user, and address wins.

Fix

First, find the file. Its location varies by distro and version:

DistroTypical path
Ubuntu/Debian/etc/postgresql/<version>/main/pg_hba.conf
AlmaLinux/Rocky/RHEL/var/lib/pgsql/<version>/data/pg_hba.conf

If you're not sure, ask Postgres itself once you're connected any way you can:

SHOW hba_file;

1. Fix local socket access (the postgres superuser)

The safest fix is not to weaken security for everyone — it's to just switch to the postgres Linux user for admin tasks, which peer auth is designed to support:

sudo -i -u postgres
psql

That should drop you straight into a postgres=# prompt with no password prompt at all. This is the intended, secure way to administer Postgres locally — most guides that tell you to change peer to trust are giving you worse advice than this one line.

2. Set a password for password-based logins

While you're in that superuser session, give the postgres role (or your app's role) a real password so TCP/password logins work later:

ALTER USER postgres WITH PASSWORD 'a-strong-password-here';

3. Switch the right pg_hba.conf lines to md5/scram

Open the file and look for lines like these near the bottom:

# TYPE  DATABASE  USER  ADDRESS       METHOD
local   all       all                 peer
host    all       all   127.0.0.1/32  ident
host    all       all   ::1/128       ident

Change the METHOD column so password-based clients can actually authenticate. On modern PostgreSQL (13+) use scram-sha-256; on older installs md5 is the safe fallback:

# TYPE  DATABASE  USER  ADDRESS       METHOD
local   all       all                 scram-sha-256
host    all       all   127.0.0.1/32  scram-sha-256
host    all       all   ::1/128       scram-sha-256

Only change the lines your app actually needs. Don't blanket-replace every line with trust — that removes authentication entirely and lets any local process connect as any role, which is a real security hole on a shared or internet-facing VPS.

4. Allow remote connections (only if you actually need them)

If your app connects from a different server, two more things need to line up. First, tell Postgres to listen on more than localhost, in postgresql.conf:

listen_addresses = '*'

Then add a host rule in pg_hba.conf scoped to the specific app server's IP, not the whole internet:

host    mydb    myappuser    203.0.113.10/32    scram-sha-256

And open the port in your firewall for just that IP:

ufw allow from 203.0.113.10 to any port 5432

5. Restart, don't just reload, if you're not sure

sudo systemctl restart postgresql

A reload (or SELECT pg_reload_conf();) is enough for pg_hba.conf changes, but listen_addresses in postgresql.conf needs a full restart to take effect. When in doubt, restart the service.

Prevention

  • Never set an authentication method to trust as a "quick fix" — it's the single most common way self-managed Postgres installs get compromised.
  • Keep remote host rules scoped to specific IPs or subnets in pg_hba.conf, and mirror that with firewall rules (UFW, firewalld, or CSF) so you're not relying on Postgres alone to keep port 5432 closed.
  • Document which lines in pg_hba.conf you changed and why — a comment above the line saves the next person (often future you) from re-diagnosing the same peer-auth error six months later.
  • If your app connects over TCP, test with psql -h 127.0.0.1 -U myappuser -d mydb right after setup, not just the bare local psql command — they hit different rules in the same file.

Frequently Asked Questions

Why does psql work fine as the postgres user but fail for my own Linux account?

Peer authentication maps your OS login name directly to a matching PostgreSQL role. Your own Linux username almost certainly isn't a Postgres role by default, so the match fails. Either connect as the postgres Linux user, or create a Postgres role that matches your OS username with CREATE ROLE.

Is it safe to just set every line in pg_hba.conf to trust?

No. trust means anyone who can reach that connection type gets in with zero credentials. On a VPS, that's a serious risk the moment any other process or user can reach the Postgres port or socket. Use scram-sha-256 or md5 instead.

I changed pg_hba.conf but the error hasn't gone away — why?

Two common reasons: you edited the wrong file (check with SHOW hba_file; once connected any way you can), or you forgot to reload/restart the service so the running instance is still using the old rules.

Do I need to open port 5432 on my firewall too?

Only if you're connecting from a different server. If your app and database run on the same VPS and connect over the Unix socket or localhost, you don't need to open 5432 externally at all — and shouldn't, unless it's required.

What's the difference between peer and ident authentication?

peer is used for local Unix-socket connections and checks the OS user directly. ident is the equivalent for TCP connections and relies on an identd service to confirm the connecting user — it's largely a legacy method now and most modern setups replace it with scram-sha-256 or md5 for TCP rules.