Databases

Fix PostgreSQL Password Authentication Failed for User

Diagnose and fix the PostgreSQL "password authentication failed for user" error by checking pg_hba.conf rules, resetting the role password and reloading the server.

BeginnerLinux server6 min read

FATAL: password authentication failed for user "deploy" means PostgreSQL accepted your connection, compared the password you sent with the stored hash, and rejected it. The fix is almost always one of three things: the role password is wrong, the hash was created with a different encryption method than the pg_hba.conf line expects, or your client is sending an old cached password. This guide walks through each one in order.

Before you start

You need:

  • SSH access to your Linux VPS with a user that can run sudo.
  • The full error message, including the user name PostgreSQL printed.
  • Access to the postgres superuser, which you reach with sudo -u postgres psql on a default install.
  • Your PostgreSQL version, so you edit the right config file: psql --version.

Config paths differ by distribution. On Ubuntu and Debian the file lives under /etc/postgresql/<version>/main/pg_hba.conf. On AlmaLinux and Rocky Linux it is usually /var/lib/pgsql/data/pg_hba.conf. Ask the server rather than guessing:

Bash
sudo -u postgres psql -c "SHOW hba_file;"

Tip: Run the administrative psql commands below as the postgres system user. That account authenticates over the local socket with peer auth and does not need a password.

Read the error and identify the failing user

PostgreSQL prints a different message for each failure, and they point at different fixes:

  • password authentication failed for user — the role exists, the rule matched, the password did not.
  • no pg_hba.conf entry for host — no rule matches your client address at all.
  • role "deploy" does not exist — the login name is wrong or the role was never created.

Confirm the role exists and can log in:

SQL
SELECT rolname, rolcanlogin, rolpassword IS NOT NULL AS has_password
FROM pg_authid
WHERE rolname = 'deploy';

If has_password is false, the role has no password set and any password-based rule will fail. If rolcanlogin is false, the role cannot open a session even with the right password.

Check the pg_hba.conf rule that handles your login

PostgreSQL picks the first matching line in pg_hba.conf, reading top to bottom. A broad peer or trust line above your password line changes everything.

List the active rules without the comments:

Bash
sudo grep -vE '^\s*#|^\s*$' /etc/postgresql/16/main/pg_hba.conf

Each line has five fields: connection type, database, user, address, and method. A typical working pair looks like this:

local   all             postgres                                peer
local   all             all                                     peer
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             ::1/128                 scram-sha-256

The important detail: local lines cover Unix socket connections and host lines cover TCP. If your app connects to localhost over the socket, it hits the local line, and peer ignores passwords completely — it matches the OS user name instead. Connect over TCP to test password auth:

Bash
psql -h 127.0.0.1 -U deploy -d deploydb

Warning: Back up pg_hba.conf before editing it (sudo cp /etc/postgresql/16/main/pg_hba.conf /etc/postgresql/16/main/pg_hba.conf.bak). A syntax error or a wrong method can lock every application out of the database until you fix the file by hand.

If you need to add or change a rule, keep the most specific lines first and put scram-sha-256 in the method column for password logins.

Set the role password correctly

Check which hash format the server is writing:

SQL
SHOW password_encryption;

If it returns md5, new passwords are stored as MD5 hashes. A scram-sha-256 line in pg_hba.conf will reject an MD5-stored password, and vice versa. Set the password with the method you actually want:

SQL
SET password_encryption = 'scram-sha-256';
ALTER ROLE deploy WITH LOGIN PASSWORD 'a-long-unique-passphrase';

Warning: ALTER ROLE... PASSWORD takes effect immediately. Every application, cron job and script still using the old password starts failing the moment you run it. Update the connection strings first, or plan a short window.

SET password_encryption only applies to the current session. To make it the default for future password changes, edit postgresql.conf:

INI
password_encryption = 'scram-sha-256'

Then reload the server. You can verify the stored hash format directly:

SQL
SELECT rolname, left(rolpassword, 14) AS hash_prefix
FROM pg_authid
WHERE rolname = 'deploy';

A SCRAM-SHA-256$ prefix means the role is ready for a scram-sha-256 rule. An md5 prefix means it is not.

Reload PostgreSQL

pg_hba.conf is read on reload, not on every connection, so your edit does nothing until you reload:

Bash
sudo systemctl reload postgresql

On version-specific units the name may be postgresql-16. Check with systemctl list-units 'postgresql*'. A reload keeps existing sessions open; a restart drops them, so prefer reload here.

If you also changed postgresql.conf, reload is usually enough, but if the new value does not appear in SHOW, restart instead:

Bash
sudo systemctl restart postgresql

Check it works

Ask PostgreSQL which rule it will use before you test the login:

SQL
SELECT line_number, type, database, user_name, address, auth_method, error
FROM pg_hba_file_rules
ORDER BY line_number;

A non-null error column means that line has a syntax problem and is being skipped. Next, connect over TCP with the new password:

Bash
psql -h 127.0.0.1 -U deploy -d deploydb -c "SELECT current_user, current_database();"

You should see deploy and deploydb in the output. Finally, test from the application itself, since that is the client that was failing.

Troubleshooting

  • Still "password authentication failed" after ALTER ROLE → your client is sending a cached password. Check ~/.pgpass, the PGPASSWORD environment variable, and any .pgpass file owned by the service user. Remove the stale entry and retry.
  • Works over the socket but not over TCP → the local line uses peer and the host line is missing or comes after a broader rule. Add a host all all 127.0.0.1/32 scram-sha-256 line above the catch-all.
  • "no pg_hba.conf entry for host" → the client address is not covered. If the app connects from another machine, add its address or subnet, and see Configure PostgreSQL Remote Access with pg_hba.conf.
  • "role does not exist" → create it with CREATE ROLE deploy LOGIN PASSWORD '...'; or follow Create PostgreSQL users, roles and databases.
  • pg_hba_file_rules shows an error on your line → a typo in the method or address column. Compare against the working example above and reload again.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.