Tunnel your localhost to a custom domain

Random subdomains like a3f8k2x9.ttn.uz are fine for scratch work. The moment you hand a link to a client, a reviewer, or a webhook config that lives longer than the session, you want your own domain. staging.myapp.com pointing at your laptop. webhooks.myapp.com wired up to Stripe.

Here's how that works on TezTun and what to know before you wire it up.

The mental model

When someone hits myapp.com:

  1. Their browser asks DNS for the IP.
  2. DNS answers with TezTun's server IP (because you added a CNAME).
  3. Their browser connects to our server and does a TLS handshake.
  4. Our server looks at the Host header, sees myapp.com, finds the tunnel bound to that domain, and pipes the traffic down the WebSocket to your laptop.
  5. Your local service responds. The response flows back the same way.

The parts you set up: the DNS record and a one-time verification. The parts we handle: the TLS certificate (via Let's Encrypt), the Host-based routing, and the tunnel.

Step-by-step

1. Add the domain in the dashboard

At app.teztun.uz, open Domains → Custom Domains → Add. Enter myapp.com (or a subdomain like staging.myapp.com). You'll see the exact DNS record to add.

2. Add the DNS record

At your DNS provider (Cloudflare, Namecheap, Route 53, whatever), add:

Type:  CNAME
Name:  myapp.com  (or staging)
Value: ttn.uz

Apex domains (no subdomain): many providers don't allow CNAMEs at the root. Cloudflare "CNAME flattening" handles it. On other providers, use an A record pointing to our server IP instead — the UI will show the correct value.

On Cloudflare: set the CNAME to DNS only (grey cloud) for the initial verification. Switch it to proxied (orange cloud) afterwards if you want; either works.

3. Verify

Back in the dashboard, click Verify. We resolve the domain and check it points at us. Propagation is usually instant but can take a few minutes on slow DNS providers.

4. Start a tunnel

Run the CLI. When you pick a domain for this tunnel, your custom domain appears in the list alongside your subdomains. Pick it, and you're live:

$ teztun http 3000 --domain myapp.com --basic-auth admin:secret
Tunnel is active!
  Subdomain: https://myapp.ttn.uz  → localhost:3000
  Custom:    https://myapp.com        → localhost:3000 (basic auth on)

The --basic-auth flag is optional but handy here: a custom domain makes staging look real, and real-looking staging gets crawled by bots. A one-line user:password enforces a 401 at our edge before a single byte reaches your laptop. Drop it if the site should be public.

HTTPS is automatic

The first request to myapp.com triggers a Let's Encrypt certificate issue. It takes about two seconds. After that the cert is cached and renewed automatically. You don't manage keys, run certbot, or think about it.

Limits & edge cases

What it's good for

What it's not for

Wire up a custom domain
Free through December 31, 2027. New accounts include Max access.
Get started