HTTP tunnels
How osmRouter routes a public hostname to your local port, and everything that flows through it.
An HTTP tunnel binds a public hostname to a port on your machine. A visitor hits the hostname, the edge forwards the request down your tunnel, your local service answers, and the response travels back out — all over a connection your machine opened outbound.
osmrouter http 8080
# -> https://<random-name>.osmrouter.com -> http://localhost:8080How a request flows
Your machine dials out
The agent opens an outbound connection to the relay and registers a hostname. Nothing needs to be open on your firewall, NAT, or CGNAT.
A visitor hits the hostname
DNS for *.osmrouter.com points at the edge. The edge terminates TLS with an
automatic Let's Encrypt certificate.
The edge forwards down your tunnel
The request is streamed over the tunnel your agent already opened, with response flushing enabled so streaming bodies are not buffered.
Your local service answers
The agent forwards to localhost:<port> and streams the response back. The
visitor sees real HTTPS on your hostname.
What passes through
TLS is terminated for you at the edge, so visitors always reach you over HTTPS regardless of how your local server listens. The following all pass through transparently:
- Plain HTTP and HTTPS
- WebSockets
- Server-Sent Events (SSE)
- Chunked and streaming responses
- Long-running requests — there is no wall-clock timeout; only the visitor cancelling ends the request
That makes HTTP tunnels a good fit for dev servers, webhook receivers, and on-device LLM inference behind OpenAI-compatible servers such as Ollama, vLLM, or llama-server.
Random vs pinned hostnames
By default each run gets a fresh random name. Set OSM_SUBDOMAIN to request a
stable hostname instead:
OSM_SUBDOMAIN=my-app osmrouter http 8080
# -> https://my-app.osmrouter.comWithout OSM_SUBDOMAIN, every run gets a new random name and the old URL goes
offline. Pin the subdomain whenever you need a fixed address — for webhooks, QR
codes, or anything you've shared.
Host headers and the origin
The request reaches your local service with the original Host and the standard
forwarding headers set, so framework host checks and absolute-URL generation work
as expected:
X-Forwarded-For— the visitor's IP.X-Forwarded-Proto—https.X-Forwarded-Host— the public hostname the visitor used.
If your dev server rejects requests for an unknown host, allow the tunnel hostname (or disable the host check in development).
Limits
A connection refused on localhost surfaces as a 502 at the edge — start your
local service before tunneling. Concurrent tunnels and monthly bandwidth are
bounded by your plan.
Next steps
- Streaming & WebSockets — long-lived connections in depth.
- Custom domains — bind tunnels to your own hostname.
- Traffic Inspector — watch requests as they arrive.