brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
ngrokExposes local services to the internet through ngrok tunnels with a public URL. Use it to share a development server, test webhooks locally, demo an app to a client, inspect and replay incoming requests, or put a temporary public URL on any local port.
Independent GitHub snapshot · Automated classification · Original documentation governs
ngrok is a cloud gateway plus a small agent (ngrok CLI, v3) that publishes a local port at a public URL, with request inspection and Traffic Policy rules for auth, rate limits and webhook verification. Typical uses: share a dev server, receive Stripe/GitHub/Telegram webhooks on localhost, demo to a client, expose SSH or a database. This page was checked against ngrok 3.39 and the docs at ngrok.com/docs (October 2026).
Key v3 changes to know: the CLI flags --domain, --basic-auth, --oauth, --verify-webhook and --cidr-allow on ngrok http are deprecated (they still print a warning and run). Use --url and a Traffic Policy instead. The config file uses version: 3 and endpoints:.
brew install ngrok, snap install ngrok, choco install ngrok, or the apt repository / packages listed at https://ngrok.com/download.ngrok config add-authtoken "$NGROK_AUTHTOKEN" (copy it from the dashboard, never commit it).ngrok http 3000
Prints a public https:// URL forwarding to localhost:3000 and serves a local inspector at http://127.0.0.1:4040. The URL is random on each run unless you choose one. Other upstream forms: ngrok http https://localhost:8443, ngrok http intranet.local:9000.
ngrok http 3000 --url https://shop-demo.ngrok.app # a domain you own on a paid plan, or an ngrok domain
Every account gets one dev domain (for free accounts it ends in ngrok-free.dev or ngrok-free.app), shown in the dashboard. Free accounts cannot pick or reserve names; custom names and your own domain (via DNS CNAME) need a paid plan.
ngrok http 8080
curl -s http://127.0.0.1:4040/api/requests/http | head -c 600 # list captured requests as JSON
The inspector shows headers, bodies and timings for every request and lets you replay one without re-triggering the sender (and the Traffic Inspector in the dashboard keeps history).
Policies are YAML with phases such as on_http_request. Save as policy.yml and pass it:
on_http_request:
- actions:
- type: basic-auth
config:
credentials:
- "reviewer:correct-horse-battery"
- actions:
- type: rate-limit
config:
name: per-ip-burst
algorithm: sliding_window
capacity: 100
rate: 60s
bucket_key:
- conn.client_ip
- expressions:
- req.url.path.startsWith('/webhooks/stripe')
actions:
- type: verify-webhook
config:
provider: stripe
secret: ${STRIPE_WEBHOOK_SECRET}
ngrok http 3000 --url https://shop-demo.ngrok.app --traffic-policy-file policy.yml
basic-auth takes up to 10 user:password pairs and answers 401; rate-limit answers 429 with a retry-after header; verify-webhook answers 403 on a bad signature (set enforce: false to log only). Other actions include restrict-ips (allow / deny CIDR lists; works in on_tcp_connect too) and custom-response. The ${...} in the example is for illustration: ngrok does not read your shell, so write the real secret into the file or generate it with envsubst, and do not commit it.
ngrok config check shows which config file is used and validates it; ngrok config edit opens it.
version: 3
agent:
authtoken: your-token-written-by-add-authtoken
endpoints:
- name: webapp
url: https://shop-demo.ngrok.app
upstream:
url: 3000
traffic_policy:
on_http_request:
- actions:
- type: basic-auth
config:
credentials:
- "reviewer:correct-horse-battery"
- name: api
url: https://shop-api.ngrok.app
upstream:
url: 8080
ngrok config check # "Valid configuration file at ..."
ngrok start --all # all endpoints
ngrok start webapp api # only these
ngrok tcp 22 # SSH; prints a tcp:// address
ngrok tcp 5432 --cidr-allow 203.0.113.0/24 # only this CIDR may connect
ngrok tls --url=app.northwind-labs.com 443 # TLS passthrough on your own domain
TCP endpoints may require a verified or paid account, and a stable TCP address must be reserved first. Expose a database only with an IP allowlist, never openly.
--pooling-enabled on two agents with the same --url balances traffic between them. ngrok http file:///var/log serves a directory read-only.
ngrok api endpoints list --api-key "$NGROK_API_KEY" # active endpoints; also: tunnels, reserved-domains
curl -s https://api.ngrok.com/endpoints -H "Authorization: Bearer $NGROK_API_KEY" -H "Ngrok-Version: 2"
# docker-compose.yml
services:
app:
build: .
ngrok:
image: ngrok/ngrok:latest
restart: unless-stopped
command: ["http", "app:3000", "--url", "https://shop-demo.ngrok.app"]
environment:
NGROK_AUTHTOKEN: ${NGROK_AUTHTOKEN}
depends_on: [app]
I'm building a Next.js app on port 3000. Give a client a stable link protected by a password.
Write policy.yml with the basic-auth action (above), then run ngrok http 3000 --url https://shop-demo.ngrok.app --traffic-policy-file policy.yml. The terminal shows Forwarding https://shop-demo.ngrok.app -> http://localhost:3000; the client is asked for the username and password, and 401 is returned otherwise.
Receive Stripe webhooks on my local server (port 8080) and reject unsigned requests.
Put the verify-webhook action (provider stripe, the endpoint's whsec_ secret) in a policy for /webhooks/stripe, run ngrok http 8080 --traffic-policy-file policy.yml, register https://shop-demo.ngrok.app/webhooks/stripe in the Stripe dashboard, then watch each delivery at http://127.0.0.1:4040 and replay a failed one after fixing your handler.
Let a colleague SSH to my workstation from 203.0.113.0/24 for an hour.
Run ngrok tcp 22 --cidr-allow 203.0.113.0/24, send them the printed tcp:// host and port, and stop the process (Ctrl+C) when done; the address disappears.
basic-auth, restrict-ips or OAuth through Traffic Policy before sharing, and stop the agent when finished.--url over --domain and Traffic Policy over --basic-auth, --verify-webhook, --cidr-allow (on http) and --oauth; the old flags are deprecated.ngrok-skip-browser-warning header.