expose-localhost
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExpose Localhost
暴露本地服务
Expose a local service to the public internet using ngrok. Optionally add OAuth, OWASP protection, or rate limiting via Traffic Policy.
使用ngrok将本地服务暴露至公网。可通过Traffic Policy(流量策略)选择性添加OAuth认证、OWASP防护或速率限制。
Prerequisites
前置条件
- ngrok CLI installed (command available)
ngrok - Auth token configured ()
ngrok config add-authtoken <TOKEN>
- 已安装ngrok CLI(可执行命令)
ngrok - 已配置认证令牌(执行)
ngrok config add-authtoken <TOKEN>
Workflow
工作流程
Step 1: Pre-flight & Configuration
步骤1:预检与配置
Silently verify ngrok is ready:
bash
ngrok config checkIf auth token missing, tell user to run: (get token at https://dashboard.ngrok.com/get-started/your-authtoken)
ngrok config add-authtoken <TOKEN>Then ask all questions upfront before doing anything:
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?Do NOT mention cloud endpoints, reserved domains, or internal endpoints — those are advanced concepts the user shouldn't need to think about.
Detecting the port: Check scripts for , for , for port mappings.
package.json--port.envPORT=docker-compose.ymlDomains: Most ngrok accounts have a free static dev domain (e.g., ). Running uses it automatically. Users can also provide a custom domain configured in the ngrok dashboard. Some accounts (especially new ones) may not have a dev domain yet — if ngrok fails with , tell the user: "You don't have a dev domain yet. Claim your free one at https://dashboard.ngrok.com/domains — then we can try again."
something.ngrok-free.devngrok http PORTERR_NGROK_15013If user requests OAuth, also ask: "Should only specific people be able to access it? I can restrict by email address or email domain."
After gathering answers, confirm and get a Y/n before proceeding.
静默验证ngrok是否就绪:
bash
ngrok config check如果缺少认证令牌,请告知用户执行:(令牌获取地址:https://dashboard.ngrok.com/get-started/your-authtoken)
ngrok config add-authtoken <TOKEN>然后在执行任何操作前先收集所有必要信息:
在为您暴露服务前,我需要了解几个细节:
1. **端口**:我检测到您的应用运行在3000端口,是否正确?
2. **域名**:使用您的开发域名,还是您有自定义域名?
3. **访问控制**:开放访问,还是需要登录验证(Google/GitHub等)?
4. **保存配置?**:仅单次使用,还是保存配置以便复用?请勿提及云端点、预留域名或内部端点——这些是高级概念,无需用户考虑。
端口检测:检查脚本中的参数、文件中的配置、中的端口映射。
package.json--port.envPORT=docker-compose.yml域名说明:大多数ngrok账号拥有免费静态开发域名(例如:)。执行会自动使用该域名。用户也可提供在ngrok控制台配置的自定义域名。部分账号(尤其是新注册的)可能尚未拥有开发域名——如果ngrok返回错误,请告知用户:"您尚未拥有开发域名,请前往https://dashboard.ngrok.com/domains领取免费域名,之后我们可再次尝试。"
something.ngrok-free.devngrok http PORTERR_NGROK_15013若用户请求OAuth认证,还需询问:"是否仅允许特定人员访问?我可以通过邮箱地址或邮箱域名进行限制。"
收集完所有信息后,请确认并获取用户的Y/n确认后再继续。
Step 2: Start the Tunnel
步骤2:启动隧道
No security (simplest)
无安全防护(最简模式)
bash
ngrok http {PORT} &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1With a specific domain, add .
--url https://{DOMAIN}bash
ngrok http {PORT} &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1若使用特定域名,添加参数。
--url https://{DOMAIN}With security (Traffic Policy)
带安全防护(Traffic Policy)
Create the traffic policy file first, then start ngrok with it.
OAuth-only (default when user requests auth):
yaml
on_http_request:
- actions:
- type: oauth
config:
provider: googleReplace with the chosen provider (google, github, microsoft, gitlab, linkedin, twitch).
googleIf the user requests OAuth, default to OAuth-only. Do NOT add OWASP or rate limiting unless explicitly asked — OAuth already blocks unauthenticated access.
OAuth with email restriction — use a separate rule with a CEL expression to deny non-matching emails. Do NOT add an field to the OAuth action.
allowSingle email:
yaml
on_http_request:
- actions:
- type: oauth
config:
provider: google
- expressions:
- "actions.ngrok.oauth.identity.email != 'user@example.com'"
actions:
- type: deny
config:
status_code: 403Email domain:
yaml
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: 403Multiple emails — use in the expression.
!(... in ['a@x.com', 'b@x.com'])Open-access hardening (no auth, but wants protection):
yaml
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: haltAfter writing the policy file, start ngrok:
bash
ngrok http {PORT} --traffic-policy-file .ngrok/traffic-policy.yml &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1Add if using a specific domain.
--url https://{DOMAIN}先创建流量策略文件,再启动ngrok。
仅OAuth认证(用户请求认证时的默认配置):
yaml
on_http_request:
- actions:
- type: oauth
config:
provider: google将替换为用户选择的服务商(google、github、microsoft、gitlab、linkedin、twitch)。
google若用户请求OAuth认证,默认使用仅OAuth模式。除非用户明确要求,否则请勿添加OWASP防护或速率限制——OAuth已可阻止未认证访问。
带邮箱限制的OAuth认证——使用单独规则配合CEL表达式拒绝不符合条件的邮箱。请勿在OAuth动作中添加字段。
allow单个邮箱限制:
yaml
on_http_request:
- actions:
- type: oauth
config:
provider: google
- expressions:
- "actions.ngrok.oauth.identity.email != 'user@example.com'"
actions:
- type: deny
config:
status_code: 403邮箱域名限制:
yaml
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 ['a@x.com', 'b@x.com'])开放访问加固(无认证,但需防护):
yaml
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:
bash
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}Step 3: Handle Errors
步骤3:错误处理
If a traffic policy action fails due to plan limitations:
- Tell the user which specific action requires an upgrade
- Offer to remove that action from the policy and retry
- Do NOT suggest switching to cloud endpoints as a workaround
若因套餐限制导致流量策略动作失败:
- 告知用户具体哪个动作需要升级套餐
- 提议从策略中移除该动作并重试
- 请勿建议切换至云端点作为替代方案
Step 4: Persistent Configuration (If Requested)
步骤4:持久化配置(若用户要求)
Save these files to the project:
- — the policy (if security was configured)
.ngrok/traffic-policy.yml - :
.ngrok/expose.sh
bash
#!/bin/bash
set -e
echo "Your service will be at: https://{DOMAIN}"
ngrok http {PORT} --url https://{DOMAIN} --traffic-policy-file .ngrok/traffic-policy.ymlOmit if no policy. Omit if no specific domain.
--traffic-policy-file--urlOptionally add to :
package.jsonjson
{ "scripts": { "tunnel": "bash .ngrok/expose.sh" } }将以下文件保存至项目中:
- —— 流量策略文件(若配置了安全防护)
.ngrok/traffic-policy.yml - :
.ngrok/expose.sh
bash
#!/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.jsonjson
{ "scripts": { "tunnel": "bash .ngrok/expose.sh" } }Teardown
停止服务
bash
pkill ngrokbash
pkill ngrokCloud Endpoints (Advanced)
云端点(高级功能)
Only use if the user explicitly needs a URL that persists after the agent stops (e.g., webhooks, long-lived integrations).
Requires an API key: (get at https://dashboard.ngrok.com/api-keys)
ngrok config add-api-key <KEY>- Reserve domain:
ngrok api reserved-domains create --domain "{DOMAIN}" - Create cloud endpoint with a traffic policy that includes as the last action:
forward-internal
bash
ngrok api endpoints create --url "https://{DOMAIN}" --bindings public --traffic-policy "$(cat .ngrok/traffic-policy.yml)"The traffic policy must end with:
yaml
- type: forward-internal
config:
url: https://{NAME}.internal- Start the internal agent:
ngrok http {PORT} --url https://{NAME}.internal - Teardown:
ngrok api endpoints delete {ENDPOINT_ID}
仅当用户明确需要在Agent停止后仍可访问的URL时使用(例如:Webhook、长期集成)。
需要API密钥:(获取地址:https://dashboard.ngrok.com/api-keys)
ngrok config add-api-key <KEY>- 预留域名:
ngrok api reserved-domains create --domain "{DOMAIN}" - 创建带流量策略的云端点,其中需作为最后一个动作:
forward-internal
bash
ngrok api endpoints create --url "https://{DOMAIN}" --bindings public --traffic-policy "$(cat .ngrok/traffic-policy.yml)"流量策略必须以以下内容结尾:
yaml
- type: forward-internal
config:
url: https://{NAME}.internal- 启动内部Agent:
ngrok http {PORT} --url https://{NAME}.internal - 停止服务:
ngrok api endpoints delete {ENDPOINT_ID}