QNAPのDockerで1つのCloudflare Tunnelを使って複数サイトを運用する方法

QNAPのDockerで1つのCloudflare Tunnelを使って複数サイトを運用する方法

はじめに

自宅のQNAP NASでWordPressを複数サイト運用する場合、Cloudflare Tunnelを使うことでルーターのポート開放なしにインターネットへ公開できます。

さらに1つのトンネルで複数のドメイン・サイトをまとめて管理できるため、サイトが増えても設定の手間が最小限で済みます。

この記事では、1つのCloudflare Tunnelで複数のWordPressサイトを運用するためのconfig.ymlの設定方法を解説します。


Cloudflare Tunnelを使うメリット

  • ポート開放不要:ルーターの設定変更なしにインターネット公開できる
  • 無料で使える:Cloudflareの無料プランで利用可能
  • DDoS対策:Cloudflareのネットワークで保護される
  • 複数サイト対応:1つのトンネルで複数ドメインを管理できる

全体構成

[ブラウザ]
    ↓
[Cloudflare](DDoS保護・SSL終端)
    ↓
[Cloudflare Tunnel](暗号化トンネル)
    ↓
[cloudflared コンテナ](QNAP NAS上)
    ↓
[Nginx リバースプロキシ](ドメインで振り分け)
    ↓              ↓
[WordPress A]  [WordPress B]

ポイント: Cloudflare TunnelはNASからCloudflareへのアウトバウンド接続のみで動作します。インバウンドのポート開放は不要です。


環境

  • QNAP NAS(ContainerStation インストール済み)
  • Cloudflareアカウント(無料プラン)
  • Docker Compose で構築
  • 運用サイト:複数WordPressサイト

ファイル構成

shared/
├── docker-compose.yml
└── cloudflared/
    ├── config.yml          ← トンネルの設定ファイル
    └── credentials.json    ← トンネルの認証情報

Step 1:Cloudflareダッシュボードでトンネルを作成する

【画像:Cloudflareダッシュボード Overview画面のスクリーンショット(トンネルIDにモザイク)】

  1. dash.cloudflare.com にログイン
  2. 左メニューの Zero Trust をクリック !!!仕様変更で最近Zero Trustメニューから下のNetworkタブのTunnelsに変更されました。
  3. NetworksTunnels をクリック
  4. 「+ Create a tunnel」 をクリック
  5. トンネルタイプ:Cloudflared を選択
  6. トンネル名を入力(例:your-tunnel-name
  7. Save tunnel をクリック

トンネルが作成されるとトンネルIDインストールコマンドが表示されます。

トンネルIDは外部に公開しないでください トンネルIDは認証情報の一部です。記事やSNSに載せる際は必ずマスクしてください。


Step 2:credentials.jsonを取得する

トンネル作成時にCloudflareからcredentials.jsonが生成されます。

ファイルの構造はこのようになっています:

{
  "AccountTag": "あなたのアカウントID",
  "TunnelID": "あなたのトンネルID",
  "Endpoint": ""
}

このファイルをNASの以下の場所に配置します:

/share/CACHEDEV4_DATA/docker/shared/cloudflared/credentials.json

credentials.jsonは絶対に外部に公開しないでください このファイルがあればトンネルを操作できてしまいます。Gitリポジトリにも含めないようにしてください。


Step 3:config.ymlを作成する

config.ymlはCloudflare Tunnelの動作を定義するファイルです。

tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /etc/cloudflared/credentials.json

ingress:
  - hostname: your-site1.com
    service: https://nginx_reverse_proxy_shared:443
    originServerName: your-site1.com
    originRequest:
      noTLSVerify: true
  - hostname: www.your-site1.com
    service: https://nginx_reverse_proxy_shared:443
    originServerName: your-site1.com
    originRequest:
      noTLSVerify: true
  - hostname: your-site2.com
    service: https://nginx_reverse_proxy_shared:443
    originServerName: your-site2.com
    originRequest:
      noTLSVerify: true
  - hostname: www.your-site2.com
    service: https://nginx_reverse_proxy_shared:443
    originServerName: your-site2.com
    originRequest:
      noTLSVerify: true
  - service: http_status:404

各設定の意味:

設定意味
tunnelトンネルID(Cloudflareダッシュボードで確認)
credentials-filecredentials.jsonのコンテナ内パス
ingressルーティングルールの一覧
hostname受け付けるドメイン名
service転送先のサービス(コンテナ名:ポート)
originServerNameSSL証明書の検証に使うホスト名
noTLSVerify: trueオリジン(Nginx)のTLS証明書検証をスキップ
http_status:404どのルールにも一致しない場合404を返す

Step 4:ingressルールの仕組み

ingressルールは上から順に評価されます。

リクエストが来る
    ↓
your-site1.com に一致? → nginx_reverse_proxy_shared:443 に転送
    ↓(一致しない)
www.your-site1.com に一致? → nginx_reverse_proxy_shared:443 に転送
    ↓(一致しない)
your-site2.com に一致? → nginx_reverse_proxy_shared:443 に転送
    ↓(一致しない)
どれにも一致しない → 404を返す

最後のhttp_status:404は必須 これがないとconfig.ymlのバリデーションエラーになります。 必ずingressの最後に記述してください。


Step 5:noTLSVerifyについて

originRequest:
  noTLSVerify: true

CloudflareからNginxへの接続はHTTPSですが、NginxのSSL証明書はCloudflare Origin CA証明書(自己署名証明書)を使っています。

このためnoTLSVerify: trueを設定してTLS証明書の検証をスキップしています。

セキュリティ上の影響 NASはローカルネットワーク内にあり、CloudflaredとNginxは同じDockerネットワーク内で通信しています。 外部からの通信はCloudflareが保護しているため、noTLSVerify: trueでも実用上の問題はありません。


Step 6:docker-compose.ymlへの組み込み方

cloudflared:
  image: cloudflare/cloudflared:latest
  container_name: cloudflared_shared
  restart: unless-stopped
  command: tunnel --config /etc/cloudflared/config.yml run your-tunnel-name
  volumes:
    - ./cloudflared/config.yml:/etc/cloudflared/config.yml:ro
    - ./cloudflared/credentials.json:/etc/cloudflared/credentials.json:ro
  networks:
    - shared_proxy

⚠️ --configオプションは必須 tunnel run your-tunnel-nameだけではconfig.ymlが読み込まれません。 必ずtunnel --config /etc/cloudflared/config.yml run your-tunnel-nameと記述してください。 このオプションを忘れると複数サイトのルーティングが機能せず502エラーになります。


Step 7:Cloudflareダッシュボードで確認する

Cloudflareダッシュボードの Routes タブで全ルートがnginx_reverse_proxy_shared:443に転送されていることを確認できます。


Step 8:新しいサイトを追加するときの手順

新しいサイトを追加する場合はconfig.ymlにingressルールを追加するだけです。

ingress:
  - hostname: your-site1.com
    service: https://nginx_reverse_proxy_shared:443
    originServerName: your-site1.com
    originRequest:
      noTLSVerify: true
  # ↓ 追加するだけ
  - hostname: your-new-site.com
    service: https://nginx_reverse_proxy_shared:443
    originServerName: your-new-site.com
    originRequest:
      noTLSVerify: true
  - service: http_status:404

追加後にCloudflaredを再起動します:

cd /share/CACHEDEV4_DATA/docker/shared
docker compose up -d --force-recreate cloudflared

まとめ

1つのCloudflare Tunnelで複数サイトを運用するポイントをまとめます。

  • config.ymlingressにホスト名ごとのルールを追加する
  • 全ドメインの転送先はNginxリバースプロキシ1つに集約する
  • noTLSVerify: trueでOrigin CA証明書の検証をスキップする
  • ingressの最後には必ずhttp_status:404を入れる
  • docker-compose.ymlのcommand--configオプションを忘れずに記述する
  • 新しいサイトの追加はconfig.ymlにルールを追記してCloudflaredを再起動するだけ

関連記事