AlmaLinuxでPostgreSQLを構築しアプリ用のユーザーとDBを作る手順|権限と接続を絞る
AlmaLinux 8にPostgreSQL 16を入れ、アプリ専用のユーザーとDBを最小限の権限で作る手順を解説します。127.0.0.1だけで受けるpg_hba.conf、.envの接続文字列、変更前のpg_dump、接続エラーの見方も紹介します。
目次
この記事でわかること
- AlmaLinux 8でPostgreSQLの版を選ぶときの注意(既定のままでは古い版が入る)
- アプリ専用のユーザーとDBを、必要最小限の権限で作る手順
- 127.0.0.1からだけ接続させるpg_hba.confの書き方と、つまずきやすいエラーの意味
- アプリの.envに接続文字列を置き、変更の前にpg_dumpを取る型
アプリのサーバー(GunicornとUvicorn)はFastAPIアプリをGunicornとUvicornで公開する手順で扱いました。この記事は、そのアプリが使うDBの側を扱います。
確かめた環境と、確かめていないこと
ロールやDBの作成、pg_hba.confの動き、アプリからの接続は、2026年10月に作業PCの一時の環境で、PostgreSQL 16.15を127.0.0.1だけで起動して確かめました。アプリ側はSQLAlchemy 2.0.35とpsycopg2 2.9.9です。
一方で、AlmaLinuxでのdnfによるインストールとsystemctlの操作は、RHEL 8の公式ドキュメントの手順に基づいていて、今回の検証では実行していません。また、AlmaLinuxのpostgresql-setup --initdbが作るpg_hba.confの最初の内容も確かめていません。この記事では、その内容に頼らず、必要な行を自分で書く手順にしています。
入れる版を決める(AlmaLinux 8の既定は古い)
PostgreSQLは、各メジャーバージョンを最初のリリースから5年間支援します。2026年10月時点で支援されているのは14〜18で、10は2022年11月に支援が終わっています。
RHEL 8の公式ドキュメントでは、PostgreSQLは9.6・10・12・13・15・16をモジュールのストリームとして選べ、既定のストリームは10です。16はRHEL 8.10から選べます。何も指定せずに入れると、支援の終わった10が入ってしまいます。
【用途】選べる版の確認 /【実行場所】AlmaLinuxのサーバー /【状態変更】なし(読み取り)
dnf module list postgresql
AlmaLinux 8.10のサーバーでは、次のように表示されました(一部)。[d]が既定、[e]が有効になっているストリームです。
postgresql 10 [d][e] client, server [d] PostgreSQL server and client module
postgresql 15 client, server [d] PostgreSQL server and client module
postgresql 16 client, server [d] PostgreSQL server and client module
この記事では、2028年11月まで支援される16を使います。
PostgreSQLをインストールして起動する
この手順は、PostgreSQLがまだ入っていないサーバーで使います。すでにPostgreSQLが動いているサーバーでは使いません。版の切り替えやデータの移行は、別の手順になります。始める前に、サーバー全体のバックアップ(スナップショット)を取っておくと、元に戻せます。
【用途】PostgreSQL 16のサーバーを入れて起動する /【実行場所】サーバー(sudoの使える管理者) /【状態変更】あり(パッケージを入れ、データの領域を作り、サービスを起動する)
sudo dnf module install postgresql:16/server
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql
RHEL 8の公式ドキュメントでは、ストリームを指定してサーバーを入れ、postgresql-setup --initdbでデータの領域を作ってから、systemctlで起動と自動起動を設定しています。
【用途】起動の確認 /【実行場所】AlmaLinuxのサーバー /【状態変更】なし(読み取り)
systemctl status postgresql
【用途】版の確認 /【実行場所】psql(postgresとして接続) /【状態変更】なし(読み取り)
SELECT version();
postgresとしてpsqlに入る方法は、次の節で説明します。
active (running)と、PostgreSQL 16の版が表示されれば準備はできています。うまく動かないまま戻す場合は、取っておいたバックアップから元に戻します。
アプリ専用のユーザーとDBを作る
PostgreSQLでは、ユーザーは「ロール」と呼ばれます。アプリが使うロールを作り、そのロールを所有者にしてDBを作ります。管理用のpostgresのまま、アプリから接続しないようにします。
まだデータの無い新しいDBなのでバックアップは要りませんが、すでに使っているサーバーで行うときは、先にpg_dumpで控えを取っておきます。
【用途】postgresとしてpsqlに入る /【実行場所】サーバー(sudoの使える管理者) /【状態変更】なし(管理用のユーザーに切り替えるだけ)
sudo su - postgres
psql
【用途】ロールとDBを作る /【実行場所】psql(postgres) /【状態変更】あり(ロールとDBを作る)
CREATE ROLE appuser LOGIN PASSWORD '<パスワード>';
CREATE DATABASE appdb OWNER appuser;
<パスワード>には、推測されにくい長い値を使います。PostgreSQL 16では、パスワードの保存方式の既定がscram-sha-256でした。検証で作ったロールも、SCRAM-SHA-256の形で保存されていました。
【用途】ロールの権限の確認 /【実行場所】psql(postgres) /【状態変更】なし(読み取り)
SELECT rolname, rolsuper, rolcreaterole, rolcreatedb, rolcanlogin
FROM pg_roles WHERE rolname = 'appuser';
検証ではrolsuper・rolcreaterole・rolcreatedbがすべてf(付いていない)、rolcanloginだけがtでした。作り直したいときは、DBにデータを入れる前の段階であれば、管理者が確認したうえでロールとDBを削除して元に戻し、最初から作ります。
権限を必要最小限にする
RHEL 8の公式ドキュメントの例では、ユーザーにCREATEROLEとCREATEDBを付けています。アプリがデータを読み書きするだけなら、どちらも要りません。検証では、これらを付けないロールでも、所有者として指定したDBに表を作ってデータを入れられました。逆に、そのロールでロールやDBを作ろうとすると拒否されました。
ERROR: permission denied to create role
ERROR: permission denied to create database
PostgreSQL 15からは、public スキーマに表を作る権限が、すべてのロール(PUBLIC)には付かなくなりました。検証でも、アプリ用のロールは管理用のpostgresのDBには表を作れず、permission denied for schema publicになりました。自分のDBでは、public スキーマの所有者がpg_database_owner(DBの所有者)になっていて、表を作れました。
ただし、接続する権限(CONNECT)は、既定ですべてのロールに付いています。検証でも、アプリ用のロールでpostgresのDBに接続できました。他のDBへの接続も止めたいときは、次のように取り消します。取り消すとpermission denied for database "postgres"で接続が拒否されました。
【用途】他のDBへの接続を止める(任意) /【実行場所】psql(postgres) /【状態変更】あり(権限を取り消す)
REVOKE CONNECT ON DATABASE postgres FROM PUBLIC;
元に戻すときはGRANT CONNECT ON DATABASE postgres TO PUBLIC;を実行します。
127.0.0.1からだけ接続できるようにする
PostgreSQLは、既定ではTCP/IPの接続をlocalhostだけで待ち受けます。アプリが同じサーバーにあるなら、この既定のまま、外から直接は届かないようにします。
誰がどのDBに接続できるかは、pg_hba.confで決めます。hostの行はTCP/IPの接続に当てはまり、上から順に、最初に一致した行が使われます。まず、ファイルの場所を確かめ、変更の前に控えを取ります。
【用途】pg_hba.confの場所の確認 /【実行場所】psql(postgres) /【状態変更】なし(読み取り)
SHOW hba_file;
【用途】変更の前の控え /【実行場所】AlmaLinuxのサーバー /【状態変更】あり(控えのファイルを作る)
sudo cp -p <表示されたパス> <表示されたパス>.bak
次に、アプリ用の行を、他のhostの行より上に足します。
【用途】アプリ用の行を足す /【実行場所】サーバー(エディターでpg_hba.confを開く) /【状態変更】あり(設定ファイルを変更する)
host appdb appuser 127.0.0.1/32 scram-sha-256
変更を読み直させて、接続できるかを確かめます。
【用途】設定の再読み込みと確認 /【実行場所】AlmaLinuxのサーバー /【状態変更】あり(設定を読み直す)
sudo systemctl reload postgresql
psql -h 127.0.0.1 -U appuser -d appdb -c "SELECT current_user;"
パスワードを聞かれ、appuserと表示されれば成功です。うまくいかないときは、控えの.bakをもとのファイルに戻し、もう一度systemctl reload postgresqlで読み直せば元に戻ります。
検証では、行の順番によって結果が変わりました。
| pg_hba.confの状態 | 結果 |
|---|---|
| 接続先に合う行が無い(appuserがpostgresのDBへ接続) | no pg_hba.conf entry for host "127.0.0.1", user "appuser", database "postgres" で拒否 |
rejectの行がアプリ用の行より上にある |
pg_hba.conf rejects connection for host ... で拒否 |
| アプリ用の行が上にある | 接続できる |
アプリの.envに接続文字列を置く
アプリからは、接続文字列で接続します。SQLAlchemyとpsycopg2を使う場合は、次の形です。
【用途】接続文字列 /【実行場所】アプリのディレクトリの.env /【状態変更】あり(ファイルを作る)
DATABASE_URL=postgresql+psycopg2://appuser:<パスワード>@127.0.0.1:5432/appdb
.envはGitに入れず(.gitignoreに書く)、ファイルの権限を所有者だけが読める状態にします。パスワードに記号を含む場合は、URLとして使える形に直す必要があります。
【用途】接続の確認 /【実行場所】アプリの仮想環境 /【状態変更】なし(読み取り)
import os
from sqlalchemy import create_engine, text
engine = create_engine(os.environ["DATABASE_URL"])
with engine.connect() as conn:
print(conn.execute(text("SELECT current_user, current_database()")).one())
検証では、SQLAlchemy 2.0.35とpsycopg2 2.9.9から、scram-sha-256のロールとして接続できました。このサイトのアプリも、接続文字列は.envに置いています。アプリの起動のしかたはFastAPIアプリをGunicornとUvicornで公開する手順を参考にしてください。
変更の前にpg_dumpを取り、前後で件数を比べる
表の変更やデータの入れ替えの前には、そのDBの控え(ダンプ)を取ります。カスタム形式(-Fc)で取ると、中身の一覧を確かめられます。
【用途】変更の前のバックアップ /【実行場所】AlmaLinuxのサーバー /【状態変更】あり(ダンプのファイルを作る)
pg_dump -h 127.0.0.1 -U appuser -Fc -f appdb_before.dump appdb
pg_restore --list appdb_before.dump | grep "TABLE DATA"
pg_restore --listは中身の一覧を表示するだけで、DBは変えません。検証では、一覧にTABLE DATA public itemsが出て、表のデータが入っていることを確かめられました。
あわせて、変更の前と後で件数を比べます。
【用途】前後の件数の確認 /【実行場所】psql(appuser) /【状態変更】なし(読み取り)
SELECT count(*) FROM items;
検証では、変更の前に2件、1件を追加した後に3件と、想定どおりに変わったことを確かめました。想定と違う件数になったら、そこで止めます。元に戻すときは、今の状態もpg_dumpで控えたうえで、取っておいたダンプから戻します。戻す手順と、戻せることの確かめ方はサーバーのバックアップと復元確認で紹介しています。
つまずきやすい点
検証で表示された誤りと、その意味です。
password authentication failed for user "appuser":パスワードが違う。または、パスワードがmd5で保存されたまま、pg_hba.confの方式がscram-sha-256になっているno pg_hba.conf entry for host ...:送り元・ユーザー・DBの組み合わせに合う行が無いpg_hba.conf rejects connection for host ...:rejectの行に先に一致しているpermission denied for schema public:自分が所有していないDBのpublic スキーマに表を作ろうとしているpermission denied for database ...:そのDBへのCONNECTが取り消されている
md5については、検証で、md5で保存したパスワードのロールが、scram-sha-256の行では接続できず、md5の行では接続できました。古い版から移ったDBでは、password_encryptionがscram-sha-256の状態で、パスワードを設定し直してください。
このサイトで実際にしていること
このサイトのアプリ用のロールも、自分のDBの所有者だけで、スーパーユーザー・ロールの作成・DBの作成の権限は持たせていません。表はすべてアプリ用のロールが所有し、接続はlocalhostだけで受けています。DBを変更する作業の前には、必ずバックアップを取り、変更の前と後で件数を比べてから進めています。
Claude Codeに任せる範囲の判断
ロールの作成、パスワードの設定、pg_hba.confの変更は、間違えると接続できなくなったり、守りが弱くなったりします。Claude Codeには、まず読み取りだけを頼み、結果を見てから自分で実行します。読み取りの考え方はサーバーの状態確認をClaude Codeに読み取り専用で任せる方法にまとめています。
【用途】DBの作業の前に、現状の読み取りだけを頼む /【実行場所】Claude Code /【状態変更】なし(変更の前に必ず止めて報告させる)
PostgreSQLにアプリ用のロールとDBを作る準備として、サーバーの状態を読み取りだけで確認してください。
- dnf module list postgresql で、有効になっているストリームと版
- PostgreSQLが動いているか(systemctl status postgresql)
- pg_hba.conf の場所と、host の行の一覧(内容は表示するだけ)
ロールの作成・パスワードの設定・設定ファイルの変更・サービスの再起動はしないでください。
結果と、次に実行するSQLとコマンドの案を報告して、私の確認を待ってください。
パスワードは、Claude Codeへの依頼文やチャットに書かず、自分で入力します。サーバー全体の作業の流れはClaude CodeでAlmaLinuxサーバーを構築・運用する方法を参考にしてください。
まとめ
- AlmaLinux 8の既定のストリームは支援の終わった10なので、16のように支援中の版を指定して入れる
- アプリ用のロールはLOGINだけで作り、DBの所有者にする。CREATEDB・CREATEROLE・スーパーユーザーは付けない
- pg_hba.confでは、アプリ用の行を127.0.0.1とscram-sha-256で、他の行より上に書く。変更の前に控えを取る
- 接続文字列は.envに置き、Gitに入れない
- 変更の前にはpg_dumpを取り、前後で件数を比べる
まずはdnf module list postgresqlで、入る版を確かめるところから始めてみてください。
よくある質問
postgresユーザーのままアプリから接続してはいけないのですか?
postgresはスーパーユーザーで、すべてのDBとロールを変更できます。アプリの不具合や設定の漏れがそのまま大きな事故になるため、アプリ専用のロールを作り、自分のDBの所有者に限るのが安全です。検証では、CREATEDBやCREATEROLEを付けないロールでも、自分のDBに表を作れました。
md5とscram-sha-256のどちらを使えばよいですか?
新しく作るならscram-sha-256です。PostgreSQL 16では、パスワードの保存方式の既定がscram-sha-256でした。md5で保存されたパスワードは、pg_hba.confの方式がscram-sha-256の行では接続できなかったため、移るときはパスワードを設定し直します。
すでにPostgreSQL 10で動いている場合はどうすればよいですか?
PostgreSQL 10は2022年11月に支援が終わっています。新しい版への移行は、データの移し方やアプリの確認を含む別の作業になるため、この記事の手順をそのまま上書きで使わず、バックアップを取ったうえで移行の計画を立ててください。
no pg_hba.conf entryと表示されるのはなぜですか?
接続の送り元・ユーザー・DBの組み合わせに一致する行が、pg_hba.confに無いためです。127.0.0.1から接続しているのか、どのユーザーとDBで接続しているのかを確かめ、該当する行を足して設定を読み直させます。
パスワードはどこに書けばよいですか?
アプリの.envに接続文字列として書き、Gitに入れないようにして、ファイルの権限を所有者だけが読める状態にします。記事やチャット、コマンドの例に本物のパスワードを書かないようにしてください。