← tunn3l.sh

Features

Everything tunn3l does, from one-liners to always-on tunnels with permanent URLs.

One-command install

A single curl downloads a standalone binary. No Node, no Python, no Docker, no package manager. Works on macOS and Linux, ARM and x64.

$ curl -sSf https://tunn3l.sh/install | sh
tunn3l installed! Open a new terminal, then:
  tunn3l http 3000

# or via npm:
$ npx tunn3l http 3000

HTTP tunnels

Expose any local port to the internet. Your dev server, your API, your webhook receiver — instantly reachable at a *.tunn3l.sh URL.

$ tunn3l http 3000

  tunn3l tunnel ready

  forwarding  https://glass-moss.tunn3l.sh → http://localhost:3000

SSH & TCP tunnels

Expose SSH, databases, or any TCP service. Each tunnel gets its own port on the relay. Connect from anywhere without VPNs or firewall changes.

$ tunn3l ssh

  tunn3l tcp tunnel ready

  forwarding  https://my-box.tunn3l.sh → tcp://localhost:22
  connect:    ssh user@tunn3l.sh -p 34821

Always-on daemon

Install tunn3l as a system service. It starts on boot, reconnects automatically, and stays up forever. One command to install, one to start.

$ tunn3l daemon install --port 3000 --subdomain my-server
  tunn3l daemon "default" installed

$ tunn3l daemon start
  tunn3l daemon "default" started

  forwarding  https://my-server.tunn3l.sh

Uses launchd on macOS, systemd on Linux. Check on it anytime with tunn3l daemon status.


Permanent URLs

Reserve a subdomain and it's yours. Every time your tunnel connects, it gets the same name — no more random URLs that change on every restart.

Reserve subdomains from the dashboard or let your daemon config lock one in with --subdomain.

Multi-device, one account

Install tunn3l on every machine with the same API key. Each device gets its own reserved subdomain, all managed from one dashboard.

# On your second machine:
$ curl -sSf https://tunn3l.sh/install | sh -s -- --key tk_your_key
$ tunn3l daemon install --port 3000 --subdomain my-laptop
$ tunn3l daemon start

  forwarding  https://my-laptop.tunn3l.sh

Dashboard

See all your active tunnels, reserve and release subdomains, claim your account — all from tunn3l.sh/dashboard. No signup required to start. Claim with an email whenever you're ready.

Built for AI agents

Every command supports --json for machine-readable output. Clean exit codes (0 = clean, 1 = auth, 2 = connection, 3 = subdomain taken). Fully configurable via environment variables. Zero interactive prompts — agents can install, connect, and manage tunnels without human intervention.

$ tunn3l http 3000 --json
{"url":"https://glass-moss.tunn3l.sh","subdomain":"glass-moss"}

CLI management commands

Everything you can do in the dashboard, you can do from the terminal. No browser needed.

$ tunn3l status

  API key:  tk_d99c...
  claimed:  you@example.com

  Reserved subdomains:
    my-server.tunn3l.sh
    my-laptop.tunn3l.sh

  Active tunnels:
    https://my-server.tunn3l.sh  (http)

$ tunn3l reserve my-new-box
  Reserved: my-new-box.tunn3l.sh

$ tunn3l unreserve my-new-box
  Released: my-new-box.tunn3l.sh

$ tunn3l claim you@example.com
  Account claimed: you@example.com

$ tunn3l status --json
{"api_key":"tk_d99c...","claimed":true,...}

The --json flag on status returns structured data — perfect for agents that need to read account state programmatically.


API key flexibility

Your API key lives in ~/.tunn3l/config.json by default. Move it to an environment variable or a dotenv file if you prefer:

// ~/.tunn3l/config.json
{
  "api_key_source": "env:TUNN3L_API_KEY"
}

// or read from a file:
{
  "api_key_source": "file:~/.env.local:TUNN3L_API_KEY"
}

Open source

MIT licensed. The relay, the CLI, the installer — everything is on GitHub. Run your own relay if you want. Point the CLI at it with --relay wss://your-server/ws/connect.