0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHP のローカル開発サーバーを Cloudflare Tunnel と Access で安全に一時公開してみた

0
Posted at

はじめに

ローカルで作っている Web ページや PHP アプリを、サーバーにデプロイせずに、少しだけ外部から確認したいことがあります。

たとえば、次のような場面です。

  • 制作中のページをスマホ実機で確認したい
  • デザイナーやクライアントに一時的に見てもらいたい
  • PHP の学習用アプリを別ネットワークから確認したい
  • Webhook の受信テストをしたい
  • 本番サーバーに上げる前に見た目や動作だけ共有したい

このような用途では、ngrok が有名です。

一方で、Cloudflare を使っている場合は、Cloudflare Tunnel を使うことで、ローカルサーバーを独自ドメイン経由で公開できます。さらに Cloudflare Access を組み合わせると、ログイン認証を前段に置けます。

この記事では、PHP のビルトインサーバーを例に、次のような構成を作ります。

https://preview.example.com
  ↓
Cloudflare Access で認証
  ↓
Cloudflare Tunnel
  ↓
手元の cloudflared
  ↓
http://127.0.0.1:8000
  ↓
PHP ビルトインサーバー

この記事の目的は、単にコマンドを並べることではありません。

初心者エンジニアやデザイナーでも、次の区別がわかるように整理することを目指します。

  • 公開 URL
  • Cloudflare Tunnel
  • cloudflared
  • 内部ホスト名 / IP アドレス
  • Cloudflare Access
  • PHP ビルトインサーバー

今回やること

この記事では、次の流れで進めます。

PHP ビルトインサーバーをローカルで起動する
Cloudflare Zero Trust で Tunnel を作る
cloudflared をローカルにインストールする
独自ドメインのサブドメインを Tunnel に割り当てる
Cloudflare Access で認証をかける
使わないときは cloudflared service を止める

最終的には、次のような URL で確認できる状態を目指します。

https://preview.example.com

もちろん example.com の部分は、自分のドメインに置き換えます。

前提

この記事では、次の前提で説明します。

  • Cloudflare アカウントを持っている
  • 独自ドメインを Cloudflare で管理している
  • ローカル環境で PHP が使える
  • Linux / Debian 系の環境で cloudflared を動かす
  • PHP ビルトインサーバーを 127.0.0.1:8000 で起動する

私は今回、PHP のビルトインサーバーを一時公開する用途で試しました。

ただし、PHP のビルトインサーバーは開発用です。本番公開には使いません。この記事で扱うのは、あくまで一時的な確認や学習用途です。

まず PHP ビルトインサーバーを起動する

最初に、ローカルで PHP のビルトインサーバーを起動します。

たとえば、プロジェクトの public ディレクトリを公開したい場合は次のようにします。

cd /path/to/your/project
php -S 127.0.0.1:8000 -t public

public ディレクトリがない単純な構成であれば、次のように起動してもかまいません。

cd /path/to/your/project
php -S 127.0.0.1:8000

ここで重要なのは、0.0.0.0 ではなく 127.0.0.1 で待ち受けることです。

Cloudflare Tunnel を使う場合、PHP サーバー自体を LAN やインターネットに直接公開する必要はありません。手元の cloudflared127.0.0.1:8000 に接続できれば十分です。

ローカルで確認するには、別ターミナルから次を実行します。

curl -I http://127.0.0.1:8000

正常に応答が返ってくれば、PHP 側の準備はできています。

Cloudflare Tunnel とは何か

Cloudflare Tunnel は、ローカル環境や社内ネットワークにあるアプリを、Cloudflare 経由で外部からアクセスできるようにする仕組みです。

通常、自宅や手元の開発環境に外部からアクセスさせようとすると、次のような作業が必要になりがちです。

  • ルーターのポート開放
  • グローバル IP の確認
  • ファイアウォール設定
  • HTTPS 証明書の用意
  • サーバーの公開設定

Cloudflare Tunnel では、ローカル側に cloudflared というソフトウェアを入れます。

cloudflared が Cloudflare 側へ外向きの接続を張ることで、外部からのアクセスをローカルサービスへ届けられるようになります。

図にすると、次のようなイメージです。

ブラウザー
  ↓
Cloudflare
  ↓
Tunnel
  ↓
cloudflared が動いているPC
  ↓
127.0.0.1:8000
  ↓
PHP ビルトインサーバー

初心者向けに言い換えるなら、Cloudflare Tunnel は、Cloudflare の入口から自分の PC までつながる「専用通路」のようなものです。

Quick Tunnel と Named Tunnel の違い

Cloudflare Tunnel には、大きく分けて一時公開向けの使い方と、独自ドメインに紐づける使い方があります。

Quick Tunnel

一時的に試すだけなら、次のようなコマンドでランダム URL を発行できます。

cloudflared tunnel --url http://127.0.0.1:8000

この場合、次のような trycloudflare.com の URL が発行されます。

https://xxxxx-xxxxx-xxxxx.trycloudflare.com

これは非常に手軽です。

ただし、URL はランダムであり、独自ドメインや Cloudflare Access と組み合わせた継続的な運用には向きません。

Named Tunnel

今回使うのはこちらです。

Cloudflare Zero Trust の画面で Tunnel を作り、独自ドメインのサブドメインに割り当てます。

たとえば、次のような URL を作ります。

https://preview.example.com

この方式では、Cloudflare Access を使って認証をかけやすくなります。

一時公開であっても、毎回ランダム URL を共有するのではなく、固定の preview.example.com を用意しておくと便利です。

Cloudflare Zero Trust で Tunnel を作る

Cloudflare ダッシュボードから Zero Trust の画面に入ります。

画面構成は変わることがありますが、おおまかな流れは次のようになります。

Cloudflare Dashboard
→ Zero Trust
→ Networks / Networking
→ Tunnels
→ Create Tunnel

Tunnel の種類は cloudflared を選びます。

トンネル名は、たとえば次のようにします。

local-php-preview

ここで少し混乱しやすいのですが、トンネル名は公開 URL ではありません

たとえば、次のように役割が分かれます。

Tunnel name:
  local-php-preview

Public hostname:
  preview.example.com

Internal service:
  http://127.0.0.1:8000

local-php-preview は、Cloudflare とローカル環境をつなぐ接続の管理名です。

preview.example.com は、ブラウザーからアクセスする公開 URL です。

127.0.0.1:8000 は、手元の cloudflared から見たローカルの PHP サーバーです。

cloudflared をインストールする

Cloudflare の画面で OS とアーキテクチャを選ぶと、cloudflared のインストール手順が表示されます。

Debian / Ubuntu 系では、APT 経由でインストールできます。

sudo mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg \
  | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null

echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main" \
  | sudo tee /etc/apt/sources.list.d/cloudflared.list

sudo apt-get update
sudo apt-get install cloudflared

インストールできたか確認します。

cloudflared --version

cloudflared を service install する

Tunnel 作成画面では、token 付きのコマンドが表示されます。

たとえば次のような形です。

sudo cloudflared service install xxxxxxxxxxxxxx

この xxxxxxxxxxxxxx の部分には、Cloudflare の Tunnel に接続するための token が入ります。

この token は公開しないようにします。Qiita 記事やスクリーンショットに載せる場合は、必ず伏せます。

実行に成功すると、次のようなログが表示されます。

INF Using Systemd
INF Linux service for cloudflared installed successfully

これは、cloudflared が systemd の service として登録されたことを意味します。

状態を確認します。

systemctl status cloudflared

起動していなければ、次で起動します。

sudo systemctl start cloudflared

自動起動も有効にしたい場合は、次を実行します。

sudo systemctl enable cloudflared

ログを見るには次を使います。

journalctl -u cloudflared -f

Cloudflare ダッシュボード上で Tunnel が Healthy になっていれば、Cloudflare とローカル環境の接続はできています。

Public Hostname を設定する

次に、独自ドメインのサブドメインを Tunnel に割り当てます。

Tunnel の設定画面で、Public Hostname を追加します。

入力例は次のとおりです。

Subdomain:
  preview

Domain:
  example.com

Type:
  HTTP

Internal hostname or IP:
  127.0.0.1

Port:
  8000

画面によっては、次のように URL 形式で入力します。

Service URL:
  http://127.0.0.1:8000

これで、次の対応関係になります。

https://preview.example.com
  ↓
http://127.0.0.1:8000

ここでの 127.0.0.1 は、Cloudflare のサーバーから見た localhost ではありません。

cloudflared が動いているマシンから見た localhost です。

今回のように、PHP ビルトインサーバーと cloudflared を同じ PC 上で動かしている場合は、127.0.0.1:8000 で問題ありません。

もし cloudflared と Web アプリが別のマシンにある場合は、別の IP アドレスやホスト名を使います。

たとえば、同じ LAN 内の別マシンでアプリが動いているなら、次のような指定になります。

http://192.168.1.50:8000

Docker Compose 内であれば、サービス名を使う場合もあります。

http://app:8000

ただし、今回の PHP 一時公開では、まずは次で十分です。

http://127.0.0.1:8000

Cloudflare Access で認証をかける

ここまでの設定だけでも、preview.example.com からローカルの PHP サーバーにアクセスできるようになります。

ただし、このままだと URL を知っている人がアクセスできてしまいます。

一時公開であっても、制作中のページや学習中のアプリを不用意に公開したくない場合は、Cloudflare Access で認証をかけます。

Cloudflare Zero Trust の画面で、Access アプリケーションを作成します。

流れは次のようになります。

Zero Trust
→ Access controls
→ Applications
→ Create application
→ Self-hosted

対象ホスト名には、先ほど設定したサブドメインを指定します。

preview.example.com

ポリシーは、たとえば自分だけ許可するなら次のようにします。

Action:
  Allow

Include:
  Email: yourname@example.com

顧客や共同作業者にも見せたい場合は、必要なメールアドレスを追加します。

Action:
  Allow

Include:
  Email: client@example.com
  Email: designer@example.com
  Email: yourname@example.com

同じドメインのメールアドレスをまとめて許可する場合は、次のような条件も考えられます。

Emails ending in:
  example.com

これで、preview.example.com にアクセスしたとき、Cloudflare Access のログイン画面が表示されます。

PHP アプリ側にログイン機能がなくても、Cloudflare 側でアクセス制限をかけられるのが便利な点です。

動作確認する

まず、ローカルの PHP サーバーが起動していることを確認します。

curl -I http://127.0.0.1:8000

次に、外部向けの URL を確認します。

curl -I -v https://preview.example.com

Access を設定している場合、curl ではアプリ本体ではなく、Cloudflare Access 側の応答が見えることがあります。

最終確認はブラウザーで行うのがわかりやすいです。

https://preview.example.com

期待する流れは次のとおりです。

Cloudflare Access のログイン画面が表示される
許可したメールアドレスでログインする
ローカルの PHP ページが表示される

HTTP バージョンを確認する

外側の HTTP バージョンを確認したい場合は、curl の -I-v を使います。

curl -I -v https://preview.example.com

たとえば、次のように表示されることがあります。

< HTTP/2 200

これは、利用者と Cloudflare Edge の間の通信が HTTP/2 であることを示しています。

注意したいのは、これがそのままローカルの PHP ビルトインサーバーの HTTP バージョンを意味するわけではないことです。

今回の構成では、おおまかに次のように区間が分かれます。

ブラウザー / curl
  ↓ HTTPS / HTTP/2 など
Cloudflare Edge
  ↓ Tunnel
cloudflared
  ↓ HTTP
PHP ビルトインサーバー

PHP ビルトインサーバーを HTTP/2 や HTTP/3 対応サーバーとして扱っているわけではありません。

ローカルサーバーが HTTPS の場合

今回の例では、ローカルの PHP サーバーを HTTP で起動しています。

http://127.0.0.1:8000

ローカル側が HTTPS の場合は、Tunnel の Service Type を HTTPS にできます。

https://127.0.0.1:8443

ただし、ローカル開発環境では自己署名証明書や mkcert の証明書を使うことがあります。

その場合、証明書検証でエラーになることがあります。

開発用途では noTLSVerify のような設定を使うこともできますが、証明書検証を無効化する設定なので、扱いには注意が必要です。

今回の目的が「PHP ビルトインサーバーを一時的に見せる」ことであれば、ローカル側は HTTP のままで十分です。

外部から見える部分は Cloudflare 側で HTTPS になります。

使わないときは cloudflared service を止める

一時公開用に使うなら、使わないときは cloudflared の service を止めておけばよいです。

sudo systemctl stop cloudflared

状態を確認します。

systemctl status cloudflared

inactive (dead) になっていれば停止しています。

PC 起動時に自動で Tunnel が立ち上がらないようにしたい場合は、自動起動も止めます。

sudo systemctl disable cloudflared

再開するときは次です。

sudo systemctl start cloudflared

自動起動も戻すなら次です。

sudo systemctl enable cloudflared

PHP ビルトインサーバーも使い終わったら Ctrl-C で停止します。

Cloudflare ダッシュボードを見ると、cloudflared を止めている間は Tunnel が Down / Inactive / Unhealthy のように表示されます。

これは、意図的に止めているなら正常です。

cloudflared service を停止
  ↓
Cloudflare とローカル環境の接続が切れる
  ↓
Tunnel が Down 表示になる
  ↓
これは正常

設定を削除する必要はありません。

次に使うときに cloudflared と PHP サーバーを再度起動すれば、同じ preview.example.com を再利用できます。

ngrok との違い

ローカルサーバーを外部公開する道具としては、ngrok がよく知られています。

ngrok は、とにかく手軽に localhost を外へ出す体験が強いツールです。Webhook の受信テストなどでもよく使われます。

一方、Cloudflare Tunnel は、Cloudflare の DNS、独自ドメイン、Access、Zero Trust と組み合わせやすいのが特徴です。

ざっくり使い分けるなら、次のようになります。

数分だけ localhost を共有したい:
  ngrok または Cloudflare Quick Tunnel

独自ドメインで固定 URL を使いたい:
  Cloudflare Tunnel

認証つきの制作確認 URL を作りたい:
  Cloudflare Tunnel + Cloudflare Access

Webhook のリクエスト内容を見ながら開発したい:
  ngrok が便利な場合もある

社内ツールやステージング環境にも応用したい:
  Cloudflare Tunnel

今回のように、独自ドメインを持っていて、認証付きの一時公開 URL を作りたい場合は、Cloudflare Tunnel と Access の組み合わせが扱いやすいと思います。

注意点

最後に、注意点をまとめます。

PHP ビルトインサーバーは本番用ではない

PHP ビルトインサーバーは開発用です。

一時的な確認には便利ですが、本番公開には使わないようにします。

本番や長期運用に近づく場合は、Caddy、nginx、Apache、FrankenPHP などを検討したほうがよいです。

公開ディレクトリを絞る

可能であれば、-t public のように公開ディレクトリを限定します。

php -S 127.0.0.1:8000 -t public

.env や設定ファイル、作業用ファイルが見える場所を公開しないようにします。

token を公開しない

sudo cloudflared service install xxxxxxxxxxxxxx の token 部分は公開しません。

記事やスクリーンショットでは必ず伏せます。

Access は万能ではない

Cloudflare Access は便利ですが、アプリケーション側の設計ミスをすべて解決してくれるわけではありません。

たとえば、危険な管理画面や、DB を破壊できる機能を軽い気持ちで公開するのは避けたほうがよいです。

使わないときは止める

一時公開用途であれば、使わないときは cloudflared と PHP サーバーを止めておくと安心です。

sudo systemctl stop cloudflared

まとめ

今回、PHP のビルトインサーバーを Cloudflare Tunnel と Access で一時公開してみました。

最初は「ローカルサーバーを少し外に見せたい」だけでしたが、実際に触ってみると、Cloudflare Tunnel は単なる localhost 公開ツール以上の学びがありました。

特に重要だったのは、次の区別です。

公開 URL:
  https://preview.example.com

Tunnel:
  Cloudflare とローカル環境をつなぐ接続

cloudflared:
  ローカル側で Tunnel を維持するソフトウェア

内部ホスト名 / IP:
  cloudflared から見たアプリの場所
  今回は http://127.0.0.1:8000

Cloudflare Access:
  公開 URL の前段に置く認証レイヤー

初心者のうちは、Cloudflare の画面に出てくる「トンネル」「アプリケーション」「内部ホスト名」「Public Hostname」などの用語が混乱しやすいです。

しかし、次の構成を頭に入れておくと見通しがよくなります。

ブラウザー
  ↓
preview.example.com
  ↓
Cloudflare Access
  ↓
Cloudflare Tunnel
  ↓
cloudflared
  ↓
127.0.0.1:8000
  ↓
PHP ビルトインサーバー

制作中のページを安全に共有したい人、ローカル開発環境をスマホや別ネットワークから確認したい人、Cloudflare Zero Trust の入口を学びたい人にとって、Cloudflare Tunnel はよい練習題材になると思います。

今回よく使ったコマンド

最後に、今回よく使ったコマンドをまとめます。

PHP ビルトインサーバーを起動します。

cd /path/to/your/project
php -S 127.0.0.1:8000 -t public

ローカル確認します。

curl -I http://127.0.0.1:8000

cloudflared の状態を確認します。

systemctl status cloudflared

cloudflared を起動します。

sudo systemctl start cloudflared

cloudflared を停止します。

sudo systemctl stop cloudflared

自動起動を有効化します。

sudo systemctl enable cloudflared

自動起動を無効化します。

sudo systemctl disable cloudflared

外部 URL の HTTP ヘッダーを確認します。

curl -I -v https://preview.example.com

ログを確認します。

journalctl -u cloudflared -f
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?