expose-localhost について
expose-localhost は、ngrok を使ってローカルサービスをインターネットに公開するためのスキルです。開発サービスや TCP サービスの共有に向け、アクセス制御、トラフィックポリシー、再利用可能な設定を案内します。
主な機能
- 01ngrok で HTTP または TCP トンネルを作成
- 02OAuth、基本認証、IP 制限を設定
- 03公開アクセスにレート制限を適用
- 04サービスのポート検出と設定確認
- 05トンネルポリシーと起動スクリプトを保存
活用シーン
- 01レビュー担当者に保護された開発プレビューを共有
- 02SSH やデータベースへの接続を一時公開
- 03再利用可能なトンネル起動手順を設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ngrok/ skills --skill expose-localhostインストール後、Claude Code で/expose-localhostを入力して読み込まれたか確認します。
同梱ファイルreferences/TROUBLESHOOTING.md
詳細
ローカルホストを公開する
ngrok を使用して、ローカルサービスをパブリックインターネットに公開します。必要に応じて、Traffic Policy を使って OAuth、OWASP 保護、またはレート制限を追加できます。
前提条件
- ngrok CLI がインストールされている(
ngrokコマンドを実行できる) - 認証トークンが設定されている(
ngrok config add-authtoken <TOKEN>)
ワークフロー
ステップ 1:事前確認と設定
ngrok の準備ができていることを、通知せずに確認します。
ngrok config check
認証トークンが設定されていない場合は、次のコマンドを実行するようユーザーに伝えます:ngrok config add-authtoken <TOKEN>(https://dashboard.ngrok.com/get-started/your-authtoken でトークンを取得できます)
その後、作業を始める前にすべての質問をまとめて尋ねます。
Before I expose your service, I need a few details:
1. **Port**: I see your app runs on port 3000. Is that correct?
2. **Domain**: Use your dev domain, or do you have a custom domain?
3. **Access control**: Open access, or require login (Google/GitHub/etc.)?
4. **Save config?**: One-time setup, or save for reuse?
クラウドエンドポイント、予約済みドメイン、内部エンドポイントには触れないでください。これらは高度な概念であり、ユーザーが考慮する必要はありません。
ポートの検出:package.json のスクリプトで --port を、.env で PORT= を、docker-compose.yml でポートマッピングを確認します。
そもそも HTTP ですか? ユーザーが SSH、RDP、データベース、または 22、3389、5432、3306 などのポートを挙げた場合、これは生の TCP サービスです。HTTP 以外のサービス(TCP) に進みます。上記のドメインとアクセス制御に関する質問は適用されません。
ドメイン:ほとんどの ngrok アカウントには、無料の静的開発ドメイン(例:something.ngrok-free.dev)があります。ngrok http PORT を実行すると、自動的にこのドメインが使用されます。ユーザーは ngrok ダッシュボードで設定したカスタムドメインを指定することもできます。アカウントによっては(特に新しいアカウントでは)、まだ開発ドメインがない場合があります。ngrok が ERR_NGROK_15013 で失敗した場合は、ユーザーに「開発ドメインがまだありません。https://dashboard.ngrok.com/domains で無料のドメインを取得してください。取得したら、もう一度試せます」と伝えます。
ユーザーが OAuth を希望する場合は、次の質問もします:「特定の人だけがアクセスできるようにしますか?メールアドレスまたはメールドメインで制限できます。」
回答を集めたら、内容を確認し、続行する前に Y/n で確認を取ります。
ステップ 2:トンネルを開始する
セキュリティなし(最も簡単)
ngrok http {PORT} &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1
特定のドメインを指定する場合は、--url https://{DOMAIN} を追加します。
セキュリティあり(Traffic Policy)
まずトラフィックポリシーファイルを作成し、その後、それを指定して ngrok を開始します。
OAuth のみ(ユーザーが認証を希望した場合のデフォルト):
on_http_request:
- actions:
- type: oauth
config:
provider: google
google を選択したプロバイダー(google、github、microsoft、gitlab、linkedin、twitch)に置き換えます。
ユーザーが OAuth を希望する場合、デフォルトでは OAuth のみを使用します。明示的に求められない限り、OWASP やレート制限を追加しないでください。OAuth によって、認証されていないアクセスはすでにブロックされています。
メールアドレス制限付き OAuth — CEL 式を使った別のルールで、一致しないメールアドレスを拒否します。OAuth アクションに allow フィールドを追加しないでください。
単一のメールアドレス:
on_http_request:
- actions:
- type: oauth
config:
provider: google
- expressions:
- "actions.ngrok.oauth.identity.email != '[email protected]'"
actions:
- type: deny
config:
status_code: 403
メールドメイン:
on_http_request:
- actions:
- type: oauth
config:
provider: google
- expressions:
- "!actions.ngrok.oauth.identity.email.endsWith('@your-company.com')"
actions:
- type: deny
config:
status_code: 403
複数のメールアドレス — in の左側に、対象となる ID を明示して指定します。
- expressions:
- "!(actions.ngrok.oauth.identity.email in ['[email protected]', '[email protected]'])"
actions:
- type: deny
config:
status_code: 403
共有シークレット(IdP でログインしない相手 — 外部クライアントや会社のアカウントを持たないレビュー担当者など):
on_http_request:
- actions:
- type: basic-auth
config:
credentials:
- "reviewer:{PASSWORD}"
URL とパスワードは、すでに信頼しているチャネルを通じて相手に渡します。相手の IP アドレスが固定されている場合は、共有する情報が不要な restrict-ips も選択肢になります。
認証なしで公開する場合の保護(認証は不要だが保護は必要):
on_http_request:
- actions:
- type: rate-limit
config:
name: default-rate-limit
algorithm: sliding_window
capacity: 200
rate: "60s"
bucket_key:
- conn.client_ip
- type: owasp-crs-request
config:
on_error: halt
on_http_response:
- actions:
- type: owasp-crs-response
config:
on_error: halt
ポリシーファイルを書き込んだ後、ngrok を開始します。
ngrok http {PORT} --traffic-policy-file .ngrok/traffic-policy.yml &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1
特定のドメインを使う場合は、--url https://{DOMAIN} を追加します。
開発サーバーを共有しますか? Vite、Next、webpack は、Host ヘッダーが localhost 以外のリクエストを拒否します。また、ホットリロード用の WebSocket で ngrok ドメインを許可する必要があります。URL を渡す前に設定してください。references/TROUBLESHOOTING.md を参照してください。
ステップ 3:エラーに対処する
プランの制限によりトラフィックポリシーのアクションが失敗した場合:
- アップグレードが必要な具体的なアクションをユーザーに伝えます
- そのアクションをポリシーから削除して再試行することを提案します
- 回避策としてクラウドエンドポイントへの切り替えを提案しないでください
ステップ 4:永続的な設定(希望する場合)
次のファイルをプロジェクトに保存します。
.ngrok/traffic-policy.yml— ポリシー(セキュリティを設定した場合).ngrok/expose.sh:
#!/bin/bash
set -e
echo "Your service will be at: https://{DOMAIN}"
ngrok http {PORT} --url https://{DOMAIN} --traffic-policy-file .ngrok/traffic-policy.yml
ポリシーがない場合は --traffic-policy-file を省略します。特定のドメインがない場合は --url を省略します。
必要に応じて、package.json に追加します。
{ "scripts": { "tunnel": "bash .ngrok/expose.sh" } }
終了
pkill ngrok
非 HTTP サービス(TCP)
SSH、RDP、データベースには、ngrok http ではなく ngrok tcp を使用します。
ngrok tcp {PORT} &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1
ngrok は tcp://1.tcp.ngrok.io:12345 のようなアドレスを返します。クライアントではホストとポートを
別々に使用します。
# local sshd on port 22, reached through the address above
ssh -p 12345 {USER}@1.tcp.ngrok.io
一般的なポート:SSH 22、RDP 3389、PostgreSQL 5432、MySQL 3306。
アドレスは再起動のたびに変わります。 固定するには、あらかじめ予約してください。 ドメインとは異なり、ホスト名とポートは ngrok によって割り当てられ、選択できません。
ngrok api reserved-addrs create --description "SSH for {NAME}" --region us
ngrok tcp {PORT} --url tcp://{ADDR}
予約済みの TCP アドレスには有料プランが必要で、削除するまで課金が続きます。
アクセス制御の方法は異なります。 OAuth と OWASP は HTTP 専用のため、機能しません。TCP ポリシーは
on_tcp_connect フェーズで実行されます。一般的な制御には restrict-ips を使用します。
on_tcp_connect:
- actions:
- type: restrict-ips
config:
enforce: true
allow:
- 203.0.113.0/24
同じ方法で適用します:ngrok tcp {PORT} --traffic-policy-file .ngrok/traffic-policy.yml
クラウドエンドポイント(上級者向け)
エージェントの停止後も維持される URL(Webhook や長期的な連携など)がユーザーに明示的に必要な場合にのみ使用してください。
API キーが必要です:ngrok config add-api-key <KEY>(https://dashboard.ngrok.com/api-keys から取得)
- ドメインを予約します:
ngrok api reserved-domains create --domain "{DOMAIN}" forward-internalを最後のアクションとして含むトラフィックポリシーを使って、クラウドエンドポイントを作成します。
ngrok api endpoints create --url "https://{DOMAIN}" --bindings public --traffic-policy "$(cat .ngrok/traffic-policy.yml)"
トラフィックポリシーの末尾は次のようにしてください。
- type: forward-internal
config:
url: https://{NAME}.internal
- 内部エージェントを起動します:
ngrok http {PORT} --url https://{NAME}.internal - 削除します:
ngrok api endpoints delete {ENDPOINT_ID}
関連スキル
このスキルでは、サービスにパブリック URL を付与する方法を扱います。関連する作業にはそれぞれ専用の スキルがあります。ここで再実装せず、適切なスキルに引き継いでください。
- 認証、レート制限、IP ルール、またはメンテナンスページ全般 —
secure-endpoint。(名前を指定した 1 人にプレビューを共有する場合は、ステップ 2 で扱います。) - Webhook を受信する場合 —
receive-webhooksはプロバイダーの署名をエッジで検証し、 受信サーバーをパブリックインターネットから隔離できます。 - MCP サーバーの場合 —
run-mcp-gatewayがプロバイダーごとの認証情報を管理します。 - コントロールプレーンで作成する、サンドボックス、テナント、またはデバイスごとのエンドポイント —
provision-sandbox-access。 - 何かが壊れている場合(
ERR_NGROK_*、localhost では発生しないが URL 経由では発生する 400)—troubleshoot-ngrok。 - セットアップまたは認証の問題 —
ngrok-setup。
基盤となるモデル(エンドポイントの種類、HTTP と TCP の違い、Traffic Policy のアクション一覧)については、
ngrok-engine を参照してください。CLI 以外の環境(SDK、REST API、Terraform、Kubernetes)での
設定適用については、ngrok-surfaces を参照してください。