「とりあえず動く」と「運用できる」の間には、深くて暗い川がある。
こんにちは!「LINUX工房」管理人の「リナックス先生」です。
前回(第6回)までで、Keycloakを中心としたSSOシステムは機能的に完成しました。
AD連携も、WebアプリのSSOも、Windows統合認証もバッチリ動いています。
しかし、今の環境をそのまま本番公開したらどうなるでしょうか?
プロの目から見ると、現在の構成は「穴だらけ」です。
- データベースのポートが全開放されていて、パスワード総当りの的になっている。
- SSL証明書の管理が各コンテナに散らばっていて更新が大変。
- ログが無限に溜まり続け、いつかディスクが溢れてサーバーが止まる。
- Keycloakがフリーズしても、誰も気づかず放置される。
ええっ!? 完璧だと思ってたのに…。
確かにデータベースのポートとか、Dockerの設定で開けっ放しにしたままです。
でも、閉じちゃったらKeycloakから繋がらなくなりませんか?
そこがDockerネットワークの面白いところよ。
コンテナ同士は「裏口(内部ネットワーク)」で繋がっているから、外向けの扉(ポート)を閉めても通信できるの。
今回は、システムの前に最強の盾「Nginx」を置いて、通信の流れを整理整頓するわよ。
これができれば、インフラエンジニアとして一人前と言っても過言じゃないわ!
本記事では、セキュリティ強化(Hardening)と可用性向上(High Availability)に焦点を当て、SSO基盤を「本番運用グレード」に引き上げる手順を徹底解説します。
🚀 本連載のカリキュラム(全8回)
- 【第1回】SSOの基礎知識と設計:AD連携を含めた全体像
- 【第2回】サーバー構築の準備:AlmaLinux 9とDocker、SSL証明書
- 【第3回】認証基盤 Keycloakの導入:コンテナ起動と日本語化
- 【第4回】ユーザー情報の統合:Active Directory (AD) とのFederation設定
- 【第5回】WebアプリのSSO化:OIDCによる認証連携
- 【第6回】Windows統合認証 (IWA):ADドメイン参加とKerberos設定
- 【第7回】セキュリティと冗長化(今回):本番運用に向けた堅牢化
- 【第8回】運用とトラブルシューティング:ログ解析と緊急対応
目次
1. 【DB保護】PostgreSQLを「密室」に閉じ込める
現在、PostgreSQLはホストのポート(5432)に公開されています。
しかし、Keycloakのデータベースに外部から直接アクセスする必要はあるでしょうか? いいえ、ありません。
Keycloakコンテナからのみアクセスできれば十分です。
docker-compose.yml の修正
作業ディレクトリの docker-compose.yml を開き、postgresサービスの記述を修正します。
vi ~/sso-project/docker-compose.yml
ports セクションを削除(またはコメントアウト)します。
postgres:
image: postgres:16
container_name: sso-postgres
# ports: <-- この行を削除
# - "5432:5432" <-- この行を削除
volumes:
- ./postgres/data:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password123
networks:
- sso-net
restart: always
これだけで、PostgreSQLは外部ネットワークから遮断され、同じ sso-net ネットワークに参加しているKeycloakコンテナからしか見えなくなります。
セキュリティレベルが格段に向上しました。
2. 【通信保護】Nginxリバースプロキシの導入とSSL集約
これまではKeycloak自身にSSL証明書を持たせていました。
しかし、システムが大きくなると「証明書の更新作業」が大変になります。
そこで、前段にWebサーバー(Nginx)を置き、そこでSSL通信を一括で引き受ける「SSLオフロード(TLS Termination)」構成に変更します。
2-1. Nginx用ディレクトリと設定ファイルの作成
mkdir -p ~/sso-project/nginx vi ~/sso-project/nginx/nginx.conf
以下の設定ファイルを作成します。
※SSL証明書のパスは、コンテナ内でのパスを指定します。
events {
worker_connections 1024;
}
http {
server {
listen 443 ssl;
server_name sso.linuxkoubou.local;
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
# 推奨されるセキュリティ設定
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://keycloak:8080;
# Keycloakに「プロキシ経由だよ」と伝えるためのヘッダ
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;
}
}
}
💡 プロのノウハウ:X-Forwarded-Protoの重要性
リバースプロキシ構築で最もハマるのが「無限リダイレクト」です。
NginxとKeycloakの間はHTTP(平文)で通信するため、Keycloakは「安全じゃない通信だ!」と判断してHTTPSへリダイレクトしようとします。proxy_set_header X-Forwarded-Proto https; を付けることで、「ユーザーとはHTTPSで話してるから安心して!」とKeycloakに伝えることができます。
2-2. docker-compose.yml へのNginx追加
Nginxサービスを追加し、既存のKeycloakのポート設定を変更します。
# --- リバースプロキシ (Nginx) ---
nginx:
image: nginx:latest
container_name: sso-nginx
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs/server.crt:/etc/nginx/certs/server.crt:ro
- ./certs/server.key:/etc/nginx/certs/server.key:ro
ports:
- "443:443" # 443番ポートはNginxが受け持つ
networks:
- sso-net
depends_on:
- keycloak
restart: always
# --- 認証サーバー (Keycloak) ---
keycloak:
# (中略)
environment:
# プロキシ配下での動作モード設定
KC_PROXY: edge
KC_HOSTNAME_STRICT: "false"
KC_HTTP_ENABLED: "true" # HTTPでの待受を許可
# ports: <-- 削除 (直接アクセスさせない)
# - "8443:8443" <-- 削除
# (以下略)
3. 【Keycloak設定】プロキシ配下での動作モード変更
Keycloakはデフォルトでは「自分が最前面にいる」と認識して動作します。
Nginxの後ろに隠れる場合、環境変数でその旨を伝える必要があります。
重要な環境変数
- KC_PROXY=edge:
SSL終端(復号)はNginxで行い、KeycloakまではHTTPで通信するモードです。
この設定がないと、管理画面が正しく表示されなかったり、ログイン後にエラーになったりします。 - KC_HTTP_ENABLED=true:
Keycloak自体がHTTP(8080ポート)でリクエストを受け付けるようにします。
前項の docker-compose.yml 修正でこれらを反映済みですので、確認してください。
4. 【自動復旧】コンテナのヘルスチェック(死活監視)設定
「プロセスは動いているけど、応答がない(フリーズした)」状態を検知し、自動的に再起動する仕組みを導入します。
Dockerの healthcheck 機能を使います。
docker-compose.yml へのヘルスチェック追加
Keycloakサービス部分に以下を追記します。
![]() |
ゼロからスタート! 教育系YouTuberまさるのLinuC1冊目の教科書 新品価格 |
keycloak:
# (中略)
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/health/ready || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
解説:
- test: Keycloakのヘルスチェック用URLを叩きます。エラーなら異常とみなします。
- interval: 30秒ごとにチェックします。
- retries: 3回連続で失敗したら「Unhealthy(不健康)」と判定し、コンテナを再起動します。
- start_period: 起動直後の60秒間はチェックが失敗しても無視します(Javaの起動は遅いため)。
5. 【ディスク保護】ログローテーションの適用
Dockerコンテナのログ(標準出力)は、放っておくと /var/lib/docker/... に無限に溜まり続け、サーバーのディスクを食いつぶします。
これを防ぐ設定を入れます。
docker-compose.yml へのログ設定追加
すべてのサービス(keycloak, postgres, nginxなど)に以下を追加するのがベストプラクティスです。
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
これにより、ログファイルは最大10MBになり、3世代までしか保持されなくなります。
古いログは自動的に削除されるため、ディスク容量不足の心配がなくなります。
6. 【転ばぬ先の杖】バックアップ運用の基本
いくら堅牢にしても、データが消える時は消えます。
Keycloakの設定とユーザー情報はすべてPostgreSQLに入っています。これをバックアップしましょう。
バックアップスクリプトの作成
~/sso-project/backup.sh を作成します。
#!/bin/bash # バックアップ保存先 BACKUP_DIR="/home/user/sso-project/backups" TIMESTAMP=$(date +%Y%m%d_%H%M%S) mkdir -p $BACKUP_DIR # PostgreSQLのダンプ実行 docker exec sso-postgres pg_dump -U keycloak keycloak > "$BACKUP_DIR/db_backup_$TIMESTAMP.sql" # 7日以上前のバックアップを削除 find $BACKUP_DIR -name "db_backup_*.sql" -mtime +7 -delete echo "Backup completed: $TIMESTAMP"
実行権限を与えます。
chmod +x backup.sh
あとはこれをCronに登録して、毎晩実行するようにすれば完璧です。
リストア(復元)する際は、psql コマンドでこのSQLファイルを流し込むだけで、元の環境に戻せます。
まとめ:堅牢な城塞が完成した
お疲れ様でした!
これで、あなたのSSO環境は「ただ動くだけ」のおもちゃから、「プロが運用するインフラ」へと進化しました。
今回の達成項目:
- データベースのポートを閉じ、外部からの攻撃を遮断した。
- Nginxを導入し、SSL管理を一元化した。
- Keycloakをプロキシ配下で正しく動作するように設定した。
- ヘルスチェックとログローテーションで、長期安定稼働の下地を作った。
先生、やること多すぎです!
でも、これを全部設定したら、すごく安心感が出ました。
Nginxのログも見れるし、何かあっても自動で再起動してくれるし、バックアップもあるし、もう怖くないです!
素晴らしいわ、コウ君。
でもね、システムは「作って終わり」じゃないの。
運用が始まれば、「ログインできない!」「遅い!」「エラーが出る!」という問い合わせが必ず来るわ。
いよいよ次回、最終回!
【第8回】運用とトラブルシューティングでは、実際に起こりうるトラブルの事例と、ログから原因を特定する「探偵ごっこ」の極意を伝授します。
最後まで走り抜けましょう!
▼ 安定したサーバーを選ぼう ▼
本番運用にも耐える
「おすすめVPS」
SREエンジニアを目指す
「ITエンジニア転職」


コメント