できない.dev

PostgreSQL で「Peer authentication failed for user」が出て接続できない

peer 認証は OS のユーザー名をそのままデータベースのユーザー名として突き合わせる。
両者が違えばパスワードの正誤に関係なく弾かれる。
OS ユーザーを合わせるか、TCP 接続かパスワード認証へ切り替える。

公開:

要約

peer 認証は、Peer Authentication(新しいタブで開く) が説明するとおり クライアントの OS ユーザー名をカーネルから取得し、それをそのまま許可するデータベースユーザー名として扱う
パスワードは一切見ない。
だから OS 側で alice としてログインしている限り、myuser としては入れない。

psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed:
FATAL:  Peer authentication failed for user "myuser"

エラーに socket と出ているのが手掛かりで、これは Unix ドメインソケット経由の接続を意味する。
peer はローカル接続でのみ使える方式なので、TCP に切り替えるだけでも別の行が適用される。

よくある原因

  1. OS ユーザーと DB ユーザーの不一致: Debian / Ubuntu のパッケージは local all all peer を既定にしている。
    自分の OS アカウントのまま -U myuser を指定すれば必ず落ちる。
  2. パスワードを設定したのに使われない: ALTER ROLE myuser PASSWORD ... を実行しても、pg_hba.confpeer のままならパスワードは参照されない。
    「パスワードが違う」と誤解しやすい。
  3. 接続経路の取り違え: -h を付けない psql はソケット接続になる。-h 127.0.0.1 を付けると host 行が使われ、認証方式が変わる。
  4. ユーザー名マップ未定義: OS ユーザー名と DB ユーザー名を意図的に分けたい場合は pg_ident.conf にマップが要る。
    書かないまま peer を使えば一致しない。
  5. 再読み込み漏れ: pg_hba.conf は起動時と再読み込み時にしか反映されない。
    編集しただけでは変わらない。

解決策

1. OS ユーザーを合わせる

sudo -u postgres psql

管理作業なら、これが最も手数が少ない。postgres ロールで入ったあと、必要なロールやデータベースを作る。

2. TCP 接続に切り替える

psql -h 127.0.0.1 -p 5432 -U myuser -d mydb

-h を付けると pg_hba.confhost 行が使われる。
アプリケーションからの接続は元々こちらなので、症状が psql でだけ出る場合はこの違いが原因である。

3. パスワード認証に変える

# TYPE  DATABASE  USER  ADDRESS  METHOD
local   all       all            scram-sha-256

The pg_hba.conf File(新しいタブで開く) が定めるとおり、上から順に最初に一致した行だけが使われる。peer の行が上に残っていると書き換えたつもりでも効かないので、順序も確認する。

4. ユーザー名マップを使う

pg_ident.conf:

# MAPNAME  SYSTEM-USERNAME  PG-USERNAME
app        deploy           myuser

pg_hba.conf:

local   all   all   peer map=app

OS の deploymyuser として入れるようになる。
パスワードを持たせずに済むので、サーバー上のデプロイ用アカウントに向く。

5. 設定を再読み込みする

sudo systemctl reload postgresql

または接続済みのセッションから次を実行する。

SELECT pg_reload_conf();

実際に適用された内容は SELECT * FROM pg_hba_file_rules; で確認できる。
構文エラーがあれば error 列に出るので、再読み込みが黙って失敗している場合の切り分けに使える。

この記事は役立ちましたか?