Use ngrok reserved domains and IP allowlists for local webhook development
Run a stable public webhook endpoint on localhost with ngrok reserved domains and IP allowlists, then verify traffic in the local request inspector.
19 Feb 2026, 07:38 UTC

The problem: webhooks need a stable address, your laptop does not
You are integrating a third-party service—perhaps a payment provider or version-control platform—that sends webhook POSTs to a public URL. Your application runs on localhost:8000, but your laptop sits behind a router with no public IP address. A free ngrok tunnel solves reachability, but its URL is random and changes whenever the agent restarts or the session expires. If you register that URL as a webhook callback, the subscription breaks the next time you close your laptop.
The practical fix is to pair a reserved ngrok domain with an IP allowlist. The reserved domain gives the provider one stable HTTPS callback address. The allowlist tells ngrok to accept tunnel traffic only from known source IP ranges, so random internet scanners cannot reach your local port just by guessing the URL.
What reserved domains and IP allowlists actually do
A reserved domain is a custom ngrok hostname attached to your account, such as your-app.ngrok.app. Unlike anonymous free tunnels, it survives agent restarts. ngrok terminates TLS at its edge and forwards decrypted traffic to the local agent, which then sends it to your application.
An IP allowlist is an edge-level rule. You list CIDR ranges—typically the webhook provider’s published outbound IP addresses—and ngrok rejects connections from anything else. This does not validate the webhook payload itself; it only shrinks the set of hosts that can open a tunnel to your machine.
Worked example: configure a stable local webhook tunnel
Run these commands in a terminal on your local development machine. You need the ngrok agent installed and an authtoken configured in your ngrok config file. Reserved domains and IP allowlists are paid-plan features; confirm your plan includes them before relying on this setup.
- Create or edit your ngrok config file:
version: "2"
authtoken: YOUR_NGROK_AUTHTOKEN
tunnels:
webhook-local:
addr: 8000
proto: http
domain: YOUR_RESERVED_DOMAIN.ngrok.app
Replace YOUR_RESERVED_DOMAIN with the domain reserved in your ngrok dashboard. The addr: 8000 value assumes your application listens on port 8000; change it to match your local service.
- Start the tunnel:
ngrok start webhook-local
Required permissions: an ordinary user account is enough, provided port 8000 is free and your firewall allows outbound HTTPS to ngrok. Risk: the local service becomes reachable from the internet through the reserved domain until you stop the agent.
- Add the IP allowlist in the ngrok dashboard or API, not in the local config file. Enter the webhook provider’s documented outbound IP ranges as CIDR blocks, for example
203.0.113.0/24. Replace that placeholder with the actual ranges published by your provider.
- Verify traffic in the local inspector. Open
http://127.0.0.1:4040in a browser. The inspector shows headers, request bodies, and timings for each tunneled request. Send a test request from an allowed IP:
curl -X POST https://YOUR_RESERVED_DOMAIN.ngrok.app/webhook \
-H "Content-Type: application/json" \
-d '{"event":"test","id":"123"}'
Expected check: the request appears in the inspector list with a successful response from your local app. Then attempt the same request from a network outside the allowlist; ngrok should refuse or drop the connection before it reaches your application.
Limitations and how to verify the result
- ngrok decrypts traffic at its edge. If the payload contains secrets or personal data, add application-layer encryption or verify webhook signatures in code; the tunnel itself is not end-to-end encryption.
- IP allowlists do not authenticate the sender. An attacker who controls an allowed IP can still POST to your endpoint. Verify provider signatures or shared secrets in your application code.
- Free anonymous URLs are ephemeral. Do not register them for long-lived subscriptions.
Practical check: after restarting ngrok start webhook-local, confirm the public URL in the inspector dashboard remains https://YOUR_RESERVED_DOMAIN.ngrok.app. Then confirm a request from an allowed IP reaches your app and one from a disallowed network does not.
Closing
Use a reserved domain when your webhook provider requires a callback URL that will not change. Add an IP allowlist to reduce exposure, but treat it as network hygiene, not payload authentication. Start the agent, inspect a test request at 127.0.0.1:4040, and verify the allowlist behavior before you register the endpoint with the provider.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.