Exposing a Local HTTP Service with ngrok: A Practical Tunnel Setup Guide
Get a public URL in front of a local HTTP service with the ngrok agent: authtoken setup, starting the tunnel, three-way verification, edge auth options, and clean shutdown.
02 Mar 2026, 02:30 UTC

The problem and the payoff
You need a webhook receiver, a demo URL, or a way for a teammate to hit the app running on your laptop — but your machine sits behind NAT and a firewall, so nothing inbound can reach it. The ngrok agent solves this by opening an outbound TLS connection to ngrok's edge, which then forwards public traffic back down that connection to your local port. No router changes, no port forwarding, no deploy. This guide walks through getting a stable, authenticated tunnel in front of a local HTTP service, verifying it end to end, and shutting it down cleanly.
Assumptions: a current ngrok v3 agent on Linux, macOS, or Windows, and a local service already listening on a known port (the examples use 8080). Exact dashboard labels and free-tier limits change over time, so treat plan-specific details as worth confirming in your ngrok dashboard.
Prerequisites
- A local HTTP service you can already reach at
http://127.0.0.1:8080(substitute your port). - An ngrok account and its authtoken, found in the dashboard under "Your Authtoken". An authtoken is a per-account secret that identifies your agent; without one you are limited to short-lived anonymous sessions.
- The ngrok agent installed. Verify with
ngrok versionin a terminal. Any user can run the agent; no administrator rights are needed because it only makes outbound connections.
Step 1: Register your authtoken
Run this once per machine, in any terminal, as your normal user:
ngrok config add-authtoken <YOUR_AUTHTOKEN>This writes the token to the agent's config file (typically ~/.config/ngrok/ngrok.yml on Linux, ~/Library/Application Support/ngrok/ngrok.yml on macOS). The file contains a secret — keep it out of version control and shared dotfiles repos. Expected result: the command prints that the authtoken was saved. If it fails, check that you copied the full token without whitespace.
Step 2: Start the tunnel
With your local service running, open a tunnel:
ngrok http 8080Run this as the same user, in a terminal you can leave open — closing it kills the tunnel. The agent prints a session status screen. The line that matters is Forwarding, which maps a public URL such as https://random-name.ngrok-free.app to http://localhost:8080. On free plans the subdomain is random and changes every restart; reserved domains require a paid plan and are then passed with a flag such as ngrok http --domain=your-name.ngrok-free.app 8080 (confirm the current flag syntax with ngrok http --help, since CLI flags evolve between versions).
If your app checks the HTTP Host header (common with some frameworks and virtual-host setups), it may reject requests arriving with the ngrok hostname. Rewrite the header so the app sees what it expects:
ngrok http --host-header=rewrite 8080Step 3: Verify from three angles
- Locally:
curl -I https://<your-forwarding-url>should return your app's response headers, not an ngrok error page. - Externally: open the URL from a phone on cellular data (off your Wi-Fi). This proves the tunnel is genuinely public and not just hairpinning inside your network.
- Traffic inspection: the agent runs a local web interface at
http://127.0.0.1:4040. Every request through the tunnel appears there with headers, body, and response status, and you can replay requests — invaluable when debugging webhook payloads.
Security decisions worth making now
A public URL to your laptop is a real exposure. Anyone with the link reaches your app, and free-tier URLs are guessable once leaked in logs or screenshots. Mitigations:
- Rely on your app's own auth. If the service has login or token checks, keep them enabled even in development.
- Add edge protection. ngrok supports basic auth and OAuth at the edge, e.g.
ngrok http --basic-auth="user:password" 8080. Checkngrok http --helpfor the current flag set on your version. - Treat the tunnel as temporary. Stop it when you're done (see below). Don't leave a dev tunnel running overnight on a machine with real data.
Stopping the tunnel
This operation changes state — it closes the public endpoint — so know how to reverse it. Press Ctrl+C in the terminal running the agent. The forwarding URL immediately stops serving; on free plans, that URL is gone for good and the next start gets a new one. To resume, rerun ngrok http 8080 and distribute the new URL to whatever consumed the old one (webhook provider configs, teammates). If a webhook provider keeps the stale URL, deliveries will fail until you update it — that update is the rollback step.
Limitations to plan around
- Free-tier endpoints are ephemeral and may show an interstitial warning page to browser visitors; API clients are unaffected.
- Free plans carry connection and bandwidth limits; sustained load testing through a tunnel is a poor idea.
- The tunnel terminates TLS at ngrok's edge by default, meaning ngrok infrastructure can see plaintext traffic. For sensitive work, look into end-to-end TLS tunnel options in the ngrok docs.
- Everything here reflects well-established v3 agent behavior; confirm plan limits and flag names against your installed version before scripting around them.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.