tunnel
A public HTTPS address for a port on your machine: xvii tunnel 3000 → https://<name>.tunnel.<d>.
For webhooks during development, showing work in progress, opening a local backend on a phone.
Host: tunnel.<d>. Binary: tunneld. Stage 6.
How it works
- The CLI opens a WebSocket to
tunnel.<d>/connect (authorized like the API), multiplexes streams over
it (hashicorp/yamux), and registers a name. tunneld accepts requests on *.tunnel.<d> and opens a
stream per request to the CLI, which proxies to localhost:<port>. WebSockets and streaming bodies
pass through.
- Names: random by default, or reserved names per team (
xvii tunnel 3000 --name api), unique per
instance. Reserved names survive reconnects.
- Access: public, password (basic auth), or only signed-in members of the team (OIDC through
id),
optional IP allow list.
- Inspector: every request and response (headers, bodies up to a limit) is recorded for the session and
shown in the panel and in the terminal (
--inspect), with replay; shared with hooks.
- Limits per team: concurrent tunnels, bandwidth per month, request size.
Later
TCP tunnels (xvii tunnel tcp 5432 → tunnel.<d>:<port>), custom domains, tunnels started from
xvii-node for services on private networks.
CLI
xvii tunnel <port> [--name] [--password] [--team-only] [--inspect], xvii tunnel list,
xvii tunnel names reserve <name>.
As built (stage 6)
-
xvii tunnel PORT|URL [--name] [--team] [--password] [--inspect] dials wss://tunnel.<d>/connect with
the person's token; kit/relay runs yamux over the WebSocket, and tunneld opens a stream per visitor
request to <name>.tunnel.<d> (one wildcard certificate), which the CLI answers from the local
address. WebSocket upgrades are spliced through, answers stream (flush per write). The CLI reconnects
with the same name and stops on a refusal (a 4xx).
-
Names: random (10 characters), any free one asked for, or a team's reserved name (xvii tunnel names --reserve api), which only its members open. One live tunnel per name.
-
Access: public, or a password (basic auth, bcrypt in memory). Team-only access through id comes later.
-
Inspector: the last 200 exchanges of a live tunnel in memory (headers, bodies up to 64 KB, timing,
visitor address), in the panel's sheet and --inspect; any request whose body was kept whole is sent
again ("Send again"), recorded as a replay.
-
Limits tunnel.tunnels (live), tunnel.names, tunnel.bandwidth (bytes a month, counted every half
minute); requests up to 32 MB.
-
A reserved name's own host name: Own domain next to it attaches a name in xvii domains (target
"tunnel names"); its visitors reach the tunnel connected under the name. Journal name.domain.