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
postgressuperuser, which you reach withsudo -u postgres psqlon 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:
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:
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:
sudo grep -vE '^\s*#|^\s*$' /etc/postgresql/16/main/pg_hba.confEach 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-256The 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:
psql -h 127.0.0.1 -U deploy -d deploydbWarning: 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:
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:
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:
password_encryption = 'scram-sha-256'Then reload the server. You can verify the stored hash format directly:
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:
sudo systemctl reload postgresqlOn 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:
sudo systemctl restart postgresqlCheck it works
Ask PostgreSQL which rule it will use before you test the login:
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:
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, thePGPASSWORDenvironment variable, and any.pgpassfile owned by the service user. Remove the stale entry and retry. - Works over the socket but not over TCP → the
localline usespeerand thehostline is missing or comes after a broader rule. Add ahost all all 127.0.0.1/32 scram-sha-256line 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_rulesshows an error on your line → a typo in the method or address column. Compare against the working example above and reload again.
Next steps
- Reset the PostgreSQL postgres user password if you are locked out of the superuser account itself.
- Install PostgreSQL and create your first database for a clean starting point on a new server.
- Create PostgreSQL users, roles and databases to set up application roles with the right privileges.
