CentOS Stream 9にKeycloakをインストール:PostgreSQL 16とNginxで構築する本番仕様のSSO環境

クイックスタート:KeycloakとPostgreSQL環境を5分で構築する

Jira、GitLab、CRMなど社内で多数のアプリケーションを運用している企業の多くは、ユーザーが頻繁にパスワードを忘れるという共通の課題に直面しています。また、従業員の退職時には、IT管理者が各システム上で手動でアカウントを確認・失効させる必要があり、時間と手間がかかるだけでなく権限の剥奪漏れも生じがちです。Keycloakは、シングルサインオン(SSO)モデルによってこの問題を根本から解決します。1つのアカウントであらゆるサービスにアクセスでき、権限管理も単一のダッシュボードで一元化できます。

以下に、CentOS Stream 9環境へJava 17、PostgreSQL 16、Quarkus版Keycloakを迅速にセットアップする手順を示します。

1. OpenJDK 17とPostgreSQL 16のインストール

# OSの更新と必要パッケージのインストール
sudo dnf update -y
sudo dnf install -y java-17-openjdk-headless wget tar

# EL9向けPostgreSQL公式リポジトリの追加
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo dnf -qy module disable postgresql
sudo dnf install -y postgresql16-server postgresql16

# データベースの初期化とサービスの起動・有効化
sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
sudo systemctl enable --now postgresql-16

2. Keycloak用データベースとユーザーの作成

PostgreSQL 15以降では、publicスキーマに対するオブジェクト作成権限がデフォルトで制限されています。そのため、keycloakデータベースのスキーマに対して直接権限を付与する必要があります:

sudo -u postgres psql -c "CREATE DATABASE keycloak;"
sudo -u postgres psql -c "CREATE USER keycloak WITH ENCRYPTED PASSWORD 'MatKhauSieuKho2026!';"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak;"

# keycloakデータベースに接続してpublicスキーマの権限を付与
sudo -u postgres psql -d keycloak -c "GRANT ALL ON SCHEMA public TO keycloak;"

3. Keycloakのダウンロードと開発モードでの動作確認

cd /opt
sudo wget https://github.com/keycloak/keycloak/releases/download/24.0.2/keycloak-24.0.2.tar.gz
sudo tar -xvzf keycloak-24.0.2.tar.gz
sudo mv keycloak-24.0.2 keycloak

# 初期管理者アカウントを設定しポート8080で起動テスト
export KEYCLOAK_ADMIN=admin
export KEYCLOAK_ADMIN_PASSWORD=AdminSecurePass123!
/opt/keycloak/bin/kc.sh start-dev

本番設定へ移行する前に、http://<サーバーIP>:8080 にアクセスして管理者コンソール(Admin Console)の表示を確認します。

運用アーキテクチャ:なぜKeycloak、PostgreSQL、Nginxが必要なのか?

数百から数万規模のアクティブセッションを安定して処理するために、責務を明確に分離した3層アーキテクチャを採用します:

  • Keycloak(Identity Provider – IdP):OIDC、OAuth 2.0、SAML 2.0の全認証フローを担当します。JWTトークンの発行、リフレッシュトークンの処理、ログインセッションの管理、クライアントアプリケーション向けのRBAC(ロールベースアクセス制御)を実行します。
  • PostgreSQL(ストレージ層):アカウント情報、レルム(Realm)、クライアントシークレット、監査ログを永続化します。Keycloakには組み込みのH2データベースが含まれていますが、これはローカル検証専用であり、同時アクセス負荷がかかるとデータ破損の原因となります。
  • Nginx(リバースプロキシ & SSL終端):Keycloakを外部の脅威から保護するゲートウェイとして機能します。HTTPSの暗号化解除、SSL暗号スイートの制御、ヘッダー圧縮を行い、安全に内部ポート8080へパケットをルーティングします。

PostgreSQL接続とKeycloak本番モード(Production Mode)の設定

/opt/keycloak/conf/keycloak.conf を開き、接続パラメータを設定します:

# /opt/keycloak/conf/keycloak.conf

# Database configuration
db=postgres
db-username=keycloak
db-password=MatKhauSieuKho2026!
db-url=jdbc:postgresql://127.0.0.1:5432/keycloak

# リバースプロキシ設定(Keycloak 24以降の標準)
proxy-headers=xforwarded
http-enabled=true
hostname=sso.example.com

デーモンとして稼働させる前に、Quarkusに設定を最適化させるための再ビルドを実行します:

cd /opt/keycloak
sudo ./bin/kc.sh build

Systemd、SELinux、Nginxによる本番環境デプロイ

1. 専用ユーザーの作成とSystemdサービスの設定

本番環境では、アプリケーションプロセスをrootユーザーで実行してはなりません:

sudo useradd -r -d /opt/keycloak -s /sbin/nologin keycloak
sudo chown -R keycloak:keycloak /opt/keycloak

# Systemdユニットファイルの作成
sudo tee /etc/systemd/system/keycloak.service << 'EOF'
[Unit]
Description=Keycloak Identity Provider Server
After=network.target postgresql-16.service
Wants=postgresql-16.service

[Service]
Type=exec
User=keycloak
Group=keycloak
ExecStart=/opt/keycloak/bin/kc.sh start --optimized
Restart=on-failure
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now keycloak

2. HTTPS対応Nginxリバースプロキシの設定

Nginxをインストールします:

sudo dnf install -y nginx
sudo systemctl enable --now nginx

/etc/nginx/conf.d/keycloak.conf にバーチャルホストを作成します。Keycloakが大きなCookieやJWTトークンを含むヘッダーを返した際に502 Bad Gatewayエラーが発生するのを防ぐため、バッファサイズを拡張しておく点に注意してください:

server {
    listen 80;
    server_name sso.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name sso.example.com;

    ssl_certificate /etc/pki/tls/certs/sso.example.com.crt;
    ssl_certificate_key /etc/pki/tls/private/sso.example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;

        # 大容量のJWTトークンに対応するためのバッファヘッダー設定
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }
}

構文チェックを行い、設定を反映します:

sudo nginx -t
sudo systemctl reload nginx

Keycloak運用における実践ノウハウ・トラブルシューティング

1. SELinuxによるNginxとKeycloak間の通信遮断エラー

Nginxの設定完了後、502 Bad Gatewayエラーに直面することがよくあります。/var/log/nginx/error.logを確認すると、Permission denied while connecting to upstreamというログが出力されています。これは、RHEL/CentOS 9のSELinuxがデフォルトでWebプロセスから内部ネットワークへの接続をブロックしているためです。ブール値フラグを有効化することで解決できます:

sudo setsebool -P httpd_can_network_connect 1

2. JVMのメモリ(RAM)とヒープサイズのチューニング

QuarkusベースのKeycloakは起動時間がわずか3〜5秒程度であり、従来のWildFlyベース(通常30〜45秒)と比較して圧倒的に高速です。初期のメモリ消費量も約450MBに抑えられています。しかし、同時オンラインユーザー数が1,000人規模に達すると、JVMがメモリを自動的に拡張していきます。

4GB RAMのサーバーでは、ヒープサイズの上限を明示的に制御することを推奨します。/opt/keycloak/conf/kc.opts ファイルを作成して以下を設定します:

JAVA_OPTS_APPEND="-Xms512m -Xmx2048m -XX:+UseG1GC"

3. Masterレルムに対する2FA/MFAの必須化

IdPサーバーは、特権昇格を狙うサイバー攻撃の最大の標的となります。Masterレルムにログインし、Authentication > Required Actionsを選択して、Configure OTPを有効化しDefault Actionに設定します。これにより、すべての管理者アカウントに対して初回ログイン時のGoogle AuthenticatorやYubiKeyによる連携設定が義務付けられます。

Share: