環境
Vagrant
Ubuntu20.4
Postgresql12
はじめに
PostgreSQLのpg_hba.confについての解説記事となります。pg_hba.confは、PostgreSQLに接続するときの認証について定義されている設定ファイルです。
初期設定ではつぎのような設定になっています。この設定について解説します。
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all all peer
host all all 127.0.0.1/32 md5
localとhostの違い
TYPEにはlocalとhostと大きく2つの設定があります。この2つの違いの認識は重要です。
localはUNIXドメインソケットで接続する場合の設定で、hostはTCP/IPで接続する場合の設定です。UNIXドメインソケットで接続する場合は、IPアドレスは使わないで接続をします。サーバー側でコマンドを叩いてPostgreSQLに接続する場合、つぎのようにして接続します。このコマンドでは、UNIXドメインソケットで接続しています。
$sudo su - postgres
$psql
postgres=#
サーバー側からの接続であっても、つぎのように、hオプションをつけて、接続先を明示的に指定することができます。ローカル環境で接続する場合は、localhostは省略することもできます。省略すれば、UNIXドメインソケットで接続されることになるのに対し、明示的に指定すれば、TCP/IPを使って接続されることになります。
$sudo su - postgres
$psql -h localhost
postgres=#
ホスト名を指定してもIPアドレスを指定しても、どちらでも接続できます。
$sudo su - postgres
$psql -h 127.0.0.1
postgres=#
pgAdminやSSHなどを使って、クライアントからサーバーに接続する場合は、UNIXドメインソケットを使て接続することはできません。TCP/IPを使って接続することになります。つまり、クライアントから接続する場合のpg_hba.confの設定は、localではなくhostで行います。
自分の開発環境のように、仮想環境を構築していて、PostgreSQLはゲストOSで動いており、ホストOSからpgAdminを使って接続する場合は、当然TCP/IPでしか接続できません。Windows環境の場合、ODBC接続をしたがると思うのですが、当然TCP/IP接続となります。
peerとmd5の違い
デフォルトでは、localの設定は、つぎの設定になっています。
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all all peer
Ubuntuにはvagrantユーザーでログインしており、PostgreSQLにもvagrantロールが存在している場合、つぎのコマンドで接続することができます。
$psql -d hoge
hoge=#
Ubuntuにはvagrantユーザーでログインしています。(Ubuntuにはtanaユーザーは存在していません)PostgreSQLにtanaロールが存在しています。このような環境で、tanaでログインしようとしても接続はできません。なぜかといえば、Peer認証で設定されているためです。peer認証とはUbuntuで登録されているユーザーと同じユーザーをPostgreSQLにも登録しておき、Ubuntuのログインで認証に成功していれば、PostgreSQLの認証はスルーさせてOKにする仕組みです。
$psql-d hoge -U tana
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "tana"
Peer認証をパスワード認証に変更しました。
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all all md5
Ubuntuにはvagrantユーザーでログインしています。(Ubuntuにはtanaユーザーは存在していません)PostgreSQLにtanaロールが存在しているため、これで、tanaでログインができるようになりました。パスワード認証の場合は、Ubuntuに登録されていないユーザーをPostgreSQLで登録して、接続することができます。
$psql-d hoge -U tana
hoge=#
localからの接続の場合は「Peer認証(peer)」で、hostからの接続の場合は「パスワード認証(md5)」にしておいた方が、Ubuntuで登録されているユーザーと、PostgreSQLで登録されているユーザーとの区別がつきやすくなり、管理しやすくなるため、このような設定にしておいた方が分かりやすいかと思います。
自分の場合は、localからの接続の場合は「Peer認証」にし、hostからの接続の場合は「パスワード認証」にしかしないと、始めから決めつけております。その方が管理が便利であるためです。セキュリティ的にもそれほどこだわる部分ではないかと思います。
allとユーザーの違い
接続するユーザーが複数ある場合、各ユーザーごとに接続情報を記述することもできます。
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all vagrant peer
local hoge1 user1 peer
local hoge2 user2 peer
しかし、つぎのように、allでひとまとめにすることもできます。
# TYPE DATABASE USER ADDRESS METHOD
local all all peer
新しいユーザーが追加になった場合、allにしておけば、メンテナンスする必要はありませんが、各ユーザーごとに記述した場合は、都度、メンテナンスを行わなければならないことになります。また、各ユーザーごと、接続するデータベースを制限させることもできます。上記の例では、user1はhoge1にしか接続することができません。user2はhoge2にしか接続することができないようになります。
postgresql.conf
TCP/IP接続をする場合は、postgresql.confのlisten_addressesを設定する必要があります。設定をしないと、TCP/IP接続ができないことになります。
デフォルトでは、次の設定になっています。次の設定では、localhostを指定して接続する場合に限り、TCP/IP接続が有効になります。
listen_addresses = 'localhost'
外部にあるクライアントからサーバーのIPを指定して、接続する場合は、サーバーのIPを指定する必要があります。明示的に指定しなくても、次の設定でも基本的にOKです。
listen_addresses = '*'
設定例
pg_hba.confの設定例を見たい場合は、公式ドキュメントに設定例が掲載されています。
補足
pg_hba.confの設定で、重要なことがあります。pg_hba.confの設定は上から下の順番に参照されるということです。重複した設定があった場合は、上の設定の方が有効になります。また、条件にマッチした設定がなかった場合は、接続ができないことになります。
Railsからデータベースを作成する(おまけ)
RailsでPostgreSQLにデータベースを作成するコマンドがあります。
$rails db:create
このコマンドを実行すると、PostgreSQLに接続してRubyからcreate databeseというpsqlコマンドを実行していると思われます。さて、このコマンドは、UNIXドメインソケット接続をしているのか、TCP/IP接続をしているのだろうか。
断言はできませんが、恐らく、database.ymlのhostの設定で、IPを設定すればTCP/IP接続を行い、hostの設定を省略すればUNIXドメインソケット接続を行うものと想定されます。
TCP/IPで接続をする場合の設定例(その1)
development:
username: hoge
password: hoge
host: 192.168.33.10
TCP/IPで接続をする場合の設定例(その2)
development:
username: hoge
password: hoge
host: localhost
UNIXドメインソケットで接続をする場合の設定例
development:
username: hoge
password: hoge
開発環境で開発用のデータベースを作成するのであれば、どちらで接続をしても、こだわる必要はないのですが、データベースを作成する前に、pg_hba.confの設定がどうなっているか、事前に確認を行ってからdatabase.ymlを触った方がいいと言えるでよう。
例えば、pg_hba.confの設定がデフォルトの状態のままで、PostgreSQLでロールを作成しないで、peer認証でUNIXドメインソケット接続をしにいった場合は、当然コマンドエラーが出ることになります。