TL;DR
FATAL: password authentication failed for user "your_user" が発生しています。詳しく調査する前に、このチェックリストを確認してください:
- パスワードが間違っている →
ALTER USER your_user WITH PASSWORD 'newpassword';でリセット pg_hba.confの認証方式が一致していない →md5とscram-sha-256を合わせる- ユーザーにパスワードが設定されていない → 明示的に設定する
- 接続文字列のタイポ → アプリの設定を再確認する
実際に何が起きているのか
PostgreSQL がクライアントから送信されたパスワードを拒否しました。原因は大きく3つあり、それぞれ異なる対処が必要です。闇雲にパスワードをリセットしても1つのケースしか解決できません。まず自分がどのケースに該当するかを特定しましょう。
原因1: 単純にパスワードが間違っている
最もよくある原因です。接続文字列のパスワードが、PostgreSQL にそのユーザー用として保存されているものと一致していません。サーバー移行後にもこの問題が発生します。たとえば、pg_dumpall でロールをダンプしたあと、新サーバーでパスワードを手動でリセットした一方、アプリの設定には古い値がそのまま残っているケースなどです。
原因2: pg_hba.conf の認証方式の不一致
pg_hba.conf は各接続の認証方式を制御します。ファイルが md5 を指定しているのに、パスワードが scram-sha-256(PostgreSQL 14 以降のデフォルト)として保存されている場合、パスワードが完全に正しくてもログインに失敗します。逆の場合も同様です。方向が違っても同じエラーになります。
原因3: ユーザーにパスワードが設定されていない、またはユーザーが存在しない
CREATE USER myuser;(パスワード句なし)で作成されたユーザーは、パスワードベースの認証方式では認証できません。PostgreSQL は「パスワードが設定されていません」のような説明的なメッセージではなく、この不透明なエラーを返します。不親切ですが、仕様として一貫しています。
対処方法
1. ユーザーのパスワードをリセットする
postgres スーパーユーザーとして接続します。Linux では通常、peer 認証を使って以下のように接続できます:
sudo -u postgres psql
次にパスワードをリセットします:
ALTER USER your_user WITH PASSWORD 'your_new_password';
\q で終了し、接続をテストします:
psql -U your_user -h 127.0.0.1 -d your_database -W
-W フラグはパスワードの入力を強制し、peer 認証にサイレントフォールスルーせず、実際の認証情報をテストしていることを確認します。
2. pg_hba.conf の認証方式を修正する
まず、pg_hba.conf の場所を確認します:
sudo -u postgres psql -c "SHOW hba_file;"
PostgreSQL 15 を使用する Ubuntu/Debian では、通常 /etc/postgresql/15/main/pg_hba.conf にあります。ファイルを開き、接続タイプに一致する行を探します:
# TYPE DATABASE USER ADDRESS METHOD
host all all 127.0.0.1/32 md5
PostgreSQL 14 以降をデフォルト設定で使用している場合、保存されているハッシュは scram-sha-256 です。方式を一致するように変更します:
host all all 127.0.0.1/32 scram-sha-256
md5 しか対応していない古いクライアントをサポートする必要がある場合は、方式を md5 のままにして、パスワードを明示的に md5 形式で再ハッシュします:
-- postgres スーパーユーザーとして実行:
SET password_encryption = md5;
ALTER USER your_user WITH PASSWORD 'your_password';
pg_hba.conf を変更した後は、PostgreSQL をリロードします。完全な再起動は不要です:
sudo systemctl reload postgresql
3. ユーザーの存在とパスワード設定を確認する
ユーザーが存在するかどうかを確認します:
sudo -u postgres psql -c "\du your_user"
出力がなければユーザーが存在しません。作成しましょう:
CREATE USER your_user WITH PASSWORD 'your_password';
ユーザーは存在するがパスワードが設定されているか不明な場合は、pg_shadow(スーパーユーザーのみ)を確認します:
SELECT usename, passwd IS NOT NULL AS has_password
FROM pg_shadow
WHERE usename = 'your_user';
has_password が f を返した場合は、上記の ALTER USER コマンドを実行してパスワードを設定してください。
4. クイックデバッグ: trust 認証を一時的に使用する
問題の原因がパスワードなのか認証方式なのかわからない場合は、localhost 上のユーザーに対してパスワードチェックを一時的にバイパスできます。pg_hba.conf の既存の host 行より上に次の行を追加します:
host all your_user 127.0.0.1/32 trust
リロードして接続します。接続できれば、ユーザーとデータベースの設定は問題ありません。問題は純粋にパスワードまたはハッシュ方式にあります。テスト後は直ちにこの行を削除してください。 本番環境での trust 認証は深刻なセキュリティホールになります。
修正が機能したことを確認する
明示的なパスワードプロンプトでテストします:
psql -U your_user -h 127.0.0.1 -d your_database -W
アプリ接続については、コネクションプールのログを確認してください。PgBouncer、Sequelize、Django のコネクションレイヤーはいずれも次回の接続試行時に最新の認証情報を取得します。通常はアプリ全体の再起動は不要で、プールのサイクルを待つだけで大丈夫です。接続文字列を環境変数に保存している場合は、更新された値がディスクに書き込まれているだけでなく、実行中のプロセスに実際に読み込まれていることを確認してください。
アプリの環境から直接テストすることもできます:
psql "postgresql://your_user:your_password@127.0.0.1:5432/your_database"
再発防止のためのヒント
チーム環境で最もよくある繰り返しの失敗例:誰かがデータベースパスワードを一度設定してドキュメント化せず、後で別の開発者が Slack やウィキから取得する。タイポが発生し、値が古くなっていく。最初から強力なランダムパスワードを設定し、シークレットマネージャーまたは gitignore 済みの .env ファイルに保存しましょう。チャットには保存しないでください。
今すぐランダムなパスワードが必要な場合は、ToolCraft のパスワードジェネレーターがブラウザ上で完全に動作し、サーバーサイド処理は一切ありません。何もインストールせずに本当にランダムなパスワードが欲しい場合に便利です。
メジャーバージョンアップグレード後にも注意が必要です。PostgreSQL 13 から 16 へのアップグレードでは、デフォルトの password_encryption が md5 から scram-sha-256 に変わります。既存のハッシュはそのまま引き継がれますが、アップグレード後にパスワードをリセットすると新しい形式が使われます。結果としてハッシュの種類が混在し、最初にリセットされたユーザーで確実に認証の不一致が発生します。メジャーバージョンアップ後は必ず監査を実施して、早期に問題を発見しましょう。

