1Panel でデプロイした Discourse の全ユーザー IP が Cloudflare 由来として表示され、実際のブラウザ IP が取得できない問題の解決

VPS に 1Panel をインストールし、Discourse(コンテナデプロイ)と OpenResty(コンテナデプロイ)をリバースプロキシとして設定しました。ドメインは Cloudflare で管理し、CDN(黄色い雲アイコン)を有効にしています。以下では、ユーザーの IP アドレスが Cloudflare 由来ではなく、実際のブラウザ IP として正しく表示されるようにするための手順を解説します。

1. 1Panel で定期タスクを作成し、週に一度最新の Cloudflare IP リストをダウンロードして OpenResty の設定ディレクトリに保存する

  1. 1Panel の左サイドメニューから**「定期タスク」**をクリックします。

  2. 右上の**「定期タスクの作成」**をクリックします。

  3. 以下のパラメータを入力してください(そのままコピー&ペースト可能です):

  • タスクタイプShell スクリプトを選択。

  • タスク名:例 Cloudflare IP セグメントの自動更新

  • 実行周期週次(例:毎週土曜日の 03:00)を推奨。

  • スクリプト内容:以下の完全なコードをそのまま貼り付けてください(注意:コードの最上部にあるコンテナ名と設定ディレクトリパスを必ず変更してください):

#!/bin/bash
# 設定エリア
CONTAINER_NAME="1Panel 内の openresty コンテナ名"
# 指定したサイトの proxy ディレクトリに修正してください
CONF_DIR="/opt/1panel/www/sites/www.あなたのドメイン/proxy"

echo "[$(date)] Cloudflare 公式から最新の IP セグメントを取得開始..."
TEMP_DIR=$(mktemp -d)

# IP リストを取得し、Nginx が認識できる形式に変換
curl -fsS https://www.cloudflare.com/ips-v4 | sed 's/.*/set_real_ip_from \&;/' > $TEMP_DIR/cf-ips-v4.conf
curl -fsS https://www.cloudflare.com/ips-v6 | sed 's/.*/set_real_ip_from \&;/' > $TEMP_DIR/cf-ips-v6.conf

# ファイルの存在確認と移動
if [[ -s $TEMP_DIR/cf-ips-v4.conf ]] && [[ -s $TEMP_DIR/cf-ips-v6.conf ]]; then
    mv $TEMP_DIR/cf-ips-v4.conf $CONF_DIR/
    mv $TEMP_DIR/cf-ips-v6.conf $CONF_DIR/
    echo "[$(date)] 設定ファイルが $CONF_DIR に正常に更新されました。"
else
    echo "[$(date)] エラー:Cloudflare IP の取得に失敗しました!"
    rm -rf $TEMP_DIR
    exit 1
fi
rm -rf $TEMP_DIR

# Nginx の設定テストとリロード
echo "[$(date)] Nginx 設定のテストを実行中..."
if docker exec $CONTAINER_NAME nginx -t; then
    docker exec $CONTAINER_NAME nginx -s reload
    echo "[$(date)] 成功!OpenResty 設定のリロードが完了しました。"
else
    echo "[$(date)] 失敗!Nginx 設定テストに合格しませんでした。"
    exit 1
fi

タスクが正常に作成できたら、土曜日を待たずにすぐにテスト可能です。「定期タスク」リストから刚才作成したタスクを探し、右側の**「レポート」**ボタンをクリックしてください。表示されるログウィンドウを確認します。最後の数行に 成功!OpenResty 設定のリロードが完了しました と表示されていれば、1Panel 内部での処理フローは完璧に動作しています!

2. OpenResty への realip 設定の追加

ホストマシンの /opt/1panel/www/sites/www.あなたのドメイン/proxy/ ディレクトリに新しいファイルを作成します(ファイル名は任意ですが、.conf で終わっている必要があります。メイン設定の include *.conf によって自動的に読み込まれます):realip.conf

real_ip_header CF-Connecting-IP;
real_ip_recursive on;

3. OpenResty のリロード

docker exec 1Panel 内の openresty コンテナ名 nginx -t
docker exec 1Panel 内の openresty コンテナ名 nginx -s reload

4. OpenResty が実際の IP を取得できているか検証

OpenResty のアクセスログを確認します:

tail -f /opt/1panel/www/sites/www.あなたのドメイン/log/access.log

設定が正しければ、ログの最初の IP アドレスが Cloudflare の 173.245.x.x などのセグメントではなく、あなたの実際のパブリック IP に変わっているはずです。

5. Discourse 側の注意点

Discourse の app.yml- "templates/cloudflare.template.yml" を追加するのは、Discourse が直接 Cloudflare と通信している場合のみ有効です。今回は中間に OpenResty リバースプロキシが入っているため、Discourse コンテナが認識する送信元 IP は実際には Docker ゲートウェイ(例:172.17.0.1172.18.0.1)となり、テンプレート内の set_real_ip_from <CloudflareIP> はマッチしません。

ただし、上記の手順で OpenResty レベルで実際の IP を復元し、クリーンな X-Forwarded-For ヘッダーを渡すことができれば、Discourse バックエンドの Rails は正しく実際のユーザー IP を認識できます。これは、Rails がデフォルトで 172.x.x.x などの Docker 私有ネットワークセグメントを信頼しているためです。

したがって、Discourse の app.yml- "templates/cloudflare.template.yml" を追加する必要はありません。