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
rootor your own sudo user and runpsql -U postgres, peer auth fails because your OS username isn'tpostgres. - If you switch to the
postgresLinux user first, plainpsqlworks 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
peerorident, 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:
| Distro | Typical 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
trustas 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.confyou 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 mydbright after setup, not just the bare localpsqlcommand — 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.
