Cloudflare Tunnelで自宅サーバーを公開する【Art Navi開発記録 #7】
はじめに
こんにちは。
なかのひとカンパニーの archer です。
美術展検索サービス Art Navi の開発内容を、備忘録も兼ねて記事にしています。
- サービスURL: https://art-weekend.jp/
前回は、NginxでNext.jsにリバースプロキシする構成について書きました。
今回は、Cloudflare Tunnelを使って、自宅サーバー上で動かしているArt Naviを外部公開する構成についてまとめます。
今回やりたいこと
Art Naviは、自宅サーバー上のUbuntu VMで動かしています。
構成としては、Next.jsをDockerで起動し、その前段にNginxを置いています。
今回は、そのNginxに対してCloudflare Tunnel経由でアクセスできるようにします。
ざっくりした構成は以下です。
ユーザー
↓
Cloudflare
↓
Cloudflare Tunnel
↓
自宅サーバー
↓
Nginx
↓
Next.js
なぜCloudflare Tunnelを使うか
自宅サーバーでWebサービスを公開する場合、通常はルーター側でポート開放が必要になります。
ただ、今回はCloudflare Tunnelを使うことで、ルーターのポート開放をせずに公開する構成にしました。
Cloudflare Tunnelを使う理由は以下です。
- ルーターのポート開放を避けたい
- 自宅グローバルIPを直接公開したくない
- Cloudflare経由でHTTPS化したい
- 自宅サーバーでも比較的安全に公開したい
- 複数サービスをCloudflare側で管理しやすい
個人開発の本番公開として、かなり扱いやすい構成だと感じました。
全体構成
Art Naviの本番環境は、ざっくり以下のような構成です。
Cloudflare
↓
cloudflared
↓
Nginx
↓
Next.js
Docker Compose上では、以下のようなコンテナを動かしています。
cloudflared
nginx
nextjs
外部からのアクセスはCloudflareが受け取り、Cloudflare Tunnelを通って自宅サーバー内のNginxへ届きます。
Nginxは、そのリクエストをNext.jsへリバースプロキシします。
Cloudflare側でやること
Cloudflare側では、主に以下を設定します。
- ドメインをCloudflareに登録する
- Tunnelを作成する
- Public Hostnameを設定する
- 対象ドメインをTunnelに紐づける
Art Naviでは、以下のようなドメインを使っています。
art-weekend.jp
www.art-weekend.jp
Tunnelの接続先は、自宅サーバー内のNginxにします。
http://nginx:80
Docker Compose内で cloudflared と nginx を同じネットワークに置いているため、サービス名 nginx で接続できます。
Docker Composeでcloudflaredを動かす
Cloudflare Tunnelは、cloudflared コンテナとして起動します。
例としては以下のような構成です。
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: art-navi-cloudflared
command: tunnel --no-autoupdate run
environment:
TUNNEL_TOKEN: ${CLOUDFLARE_TUNNEL_TOKEN}
depends_on:
- nginx
restart: unless-stopped
Tunnel Tokenは秘密情報なので、.env.production などで管理します。
CLOUDFLARE_TUNNEL_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxx
この値はGitHubにpushしないように注意します。
.env.production
Nginxへの接続先
Cloudflare Tunnelの接続先は、Nginxにします。
http://nginx:80
ここで重要なのは、localhost:80 ではなく nginx:80 にすることです。
Docker Compose内では、コンテナ同士の通信にサービス名を使います。
localhost:80
cloudflaredコンテナ自身を見に行く
nginx:80
nginxコンテナを見に行く
前回のNginx記事と同じく、Docker環境では localhost の扱いに注意が必要です。
DNS設定で詰まったこと
Cloudflare Tunnelを使う場合、対象ドメインのDNSレコードをTunnelに向ける必要があります。
このとき、既存のAレコードやAAAAレコードが残っていると、うまくTunnelに紐づかないことがあります。
自分の場合も、既存レコードが残っていて一度エラーになりました。
最終的には、不要な既存レコードを整理して、Tunnel側でDNSを割り当てる形にしました。
対象は以下です。
art-weekend.jp
www.art-weekend.jp
このあたりは、Cloudflareの画面上で現在のDNSレコードを確認しながら進める必要があります。
起動手順
設定ができたら、Docker Composeで起動します。
docker compose up -d
コンテナの状態を確認します。
docker compose ps
cloudflaredのログを確認します。
docker compose logs -f cloudflared
正常に接続できていれば、Cloudflareのエッジに接続されたログが出ます。
動作確認
まずはサーバー内でNginxにアクセスできるか確認します。
curl -I http://localhost
次に、Cloudflare Tunnel経由で公開URLにアクセスします。
curl -I https://art-weekend.jp
ブラウザでも確認します。
https://art-weekend.jp
HTTPステータスが 200 で返ってくれば、Cloudflare Tunnel経由でNext.jsまで到達できています。
よく使うコマンド
コンテナ状態を確認します。
docker compose ps
cloudflaredのログを確認します。
docker compose logs -f cloudflared
Nginxのログを確認します。
docker compose logs -f nginx
Next.jsのログを確認します。
docker compose logs -f nextjs
再起動します。
docker compose restart cloudflared
全体を再作成します。
docker compose up -d --build
詰まりやすいポイント
Cloudflare Tunnelで詰まりやすいのは、以下のあたりです。
- Tunnel Tokenを間違えている
-
.env.productionが読み込まれていない - cloudflaredコンテナがNginxに到達できない
- 接続先を
localhost:80にしてしまう - 既存のDNSレコードが残っている
- Nginxコンテナが起動していない
- Next.jsコンテナが起動していない
特に、Docker Compose内では接続先をサービス名で書く点が重要でした。
http://nginx:80
この考え方に慣れると、NginxやNext.jsとの接続も理解しやすくなります。
Cloudflare Tunnelを使ってよかった点
Cloudflare Tunnelを使ってよかった点は以下です。
- ルーターのポート開放が不要
- 自宅サーバーを直接公開しなくてよい
- HTTPS公開しやすい
- Cloudflare側でDNS管理できる
- 自宅サーバーでも本番公開しやすい
- 複数サービス展開にも応用しやすい
個人開発で自宅サーバーを使う場合、Cloudflare Tunnelはかなり便利だと感じました。
気をつけること
便利な一方で、以下は注意が必要です。
- Tunnel Tokenは絶対に公開しない
-
.env.productionはGit管理しない - Cloudflare側のDNS設定を確認する
- cloudflaredのログを確認する
- サーバー再起動時に自動復旧できるようにする
- Docker Composeの
restart: unless-stoppedを設定する
特に、Tunnel Tokenは認証情報なので、GitHubにpushしないように注意しています。
まとめ
今回は、Cloudflare Tunnelを使って自宅サーバー上のArt Naviを公開する構成についてまとめました。
今回のポイントは以下です。
- 自宅サーバー公開にCloudflare Tunnelを使う
- ルーターのポート開放を避けられる
- cloudflaredコンテナをDocker Composeで起動する
- Tunnelの接続先はNginxにする
- Docker Compose内では
nginx:80のようにサービス名で接続する - Tunnel Tokenや本番環境変数はGit管理しない
これで、Cloudflare Tunnel経由で自宅サーバー上のNext.jsアプリを公開できるようになりました。
次回は、sitemap.xmlとrobots.txtを整備する内容について書く予定です。