# Tunnel — Recipes

> End-to-end tunnel walkthroughs: ship a public demo URL, a private cross-NAT database link, and a remote-desktop session over raw QUIC.

Longer worked examples that combine several `clutchcall` commands into a
realistic scenario.

## Recipe 1 — Ship a public demo URL with a stable subdomain

Take a local web app from `localhost:3000` to a shareable HTTPS URL that survives
restarts and Wi-Fi changes, using a reserved subdomain.

  1. **Sign in once**
```sh
    clutchcall login          # provider device flow; nothing is stored but a session token
    ```
  2. **Reserve your subdomain**
```sh
    clutchcall claim acme     # → https://acme.clutchcall.dev
    ```
    The handle is bound to your account and enforced by the session token — a stale
    slug can't escape your namespace.
  3. **Expose the app**
```sh
    clutchcall http 3000      # → https://acme.clutchcall.dev
    ```
    The CLI dials the nearest edge PoP over QUIC, registers the slug, and parks a
    pool of streams. Public requests to `acme.clutchcall.dev` are spliced back over
    those streams to `localhost:3000`.
  4. **Run named tunnels for extra services**
```sh
    clutchcall http 8080 --name api   # → https://acme-api.clutchcall.dev
    ```
    Each service gets its own URL and its own stream pool — no head-of-line blocking
    between them.
  5. **Verify it from anywhere**
A stranger on the internet loads `https://acme.clutchcall.dev`; WebSocket
    upgrade, SSE, and large uploads all pass through. If your laptop hops from Wi-Fi
    to cellular, QUIC migration keeps the URL live without a reconnect.

> **NOTE:**
> The URL is reachable from every region: traffic that lands on a far PoP is routed
> to the PoP your box is connected to over the edge mesh.

---

## Recipe 2 — A private cross-NAT database link

Reach a Postgres instance on a home server from your laptop on a different network,
with **no inbound ports** and the edge **never carrying your bytes**.

  1. **Configure a STUN reflector on both boxes**
```sh
    export <P>_STUN=stun.clutchcall.dev:3478
    ```
    Each side gathers its server-reflexive candidate (public `ip:port`) so the two
    can punch toward each other.
  2. **Share the database from the home server**
```sh
    home$ clutchcall p2p share pglink --port 5432
    ```
    `pglink` is a shared pair-id both peers agree on out of band. The CLI binds a
    local UDP port, STUN-gathers, and publishes its candidates to the rendezvous,
    then waits for the peer.
  3. **Connect from the laptop**
```sh
    laptop$ clutchcall p2p connect pglink --listen 5432
    ```
    The laptop publishes its own candidates under the same pair-id. The control
    plane brokers the exchange; both sides then punch and the QUIC engine rebinds
    the same local port to form a **direct** link.
  4. **Use the link**
```sh
    laptop$ psql -h localhost -p 5432
    ```
    Each `psql` connection becomes its own QUIC stream over the direct link. The
    pair-id gates the tunnel end to end; the edge only ever saw the candidate
    exchange, never query bytes.

> **WARNING:**
> On a symmetric NAT the direct punch can fail; the flow falls back to the relayed
> path so the link still forms (the edge then forwards bytes for that session).

<Accordion title="Why no inbound port is ever opened">
Both peers are QUIC **clients** that dial outward — whoever dials is the client.
The home server never accepts an unsolicited inbound connection, so there is no
firewall hole to punch and no static public IP to maintain.
</Accordion>

---

## Recipe 3 — Remote desktop over the raw-QUIC relay

Control a headless box from a laptop using a remote-desktop client whose transport
rides the same tunnel relay — both legs are QUIC, end-to-end encryption is the
client's own.

  1. **Point both clients at the relay**
In the remote-desktop client (an open-source remote-desktop fork built with the
    QUIC transport feature), set the relay endpoint:
    ```text
    quic-relay-server = relay.clutchcall.dev:4443
    ```
    This replaces the client's own rendezvous/relay with the ClutchCall tunnel
    relay (ALPN `clutchcall-engine`).
  2. **The controlled box registers**
On launch, the controlled box dials the relay and registers its **device id as
    a slug** with `proto":"quick"`, then pre-opens and parks bidi work streams —
    exactly the parked-stream pool the HTTP/TCP tunnels use.
  3. **The controller dials by slug**
The controller enters the box's device id; the relay looks up the slug, pops a
    parked stream, writes an `open` metadata frame, and splices the controller's
    QUIC stream to the box's parked stream.
  4. **Session runs end to end encrypted**
The remote-desktop client's signed key exchange and message framing ride
    unchanged on top of the QUIC byte pipe. The relay is **untrusted**: QUIC TLS
    only secures the hop to the PoP — confidentiality and peer auth stay in the
    client's own crypto.

> **NOTE:**
> No extra CLI is needed for this path — the remote-desktop client speaks the tunnel
> wire protocol directly. The HTTP/TCP/P2P tunnels and the remote-desktop session all
> share one transport, one slug namespace, and one parked-stream model.

---

## Recipe 4 — Self-hosted control plane + edge

Run the whole stack against your own infrastructure for a zero-trust ingress to
internal services.

  1. **Point the CLI at your control plane**
```sh
    export <P>_API=https://api.internal.example.com
    export <P>_POP=edge.internal.example.com:4443
    clutchcall login
    ```
  2. **Expose an internal admin panel**
```sh
    clutchcall claim admin
    clutchcall http 9000      # → https://admin.internal.example.com
    ```
    The box on the internal network dials out to your edge; nobody opens an inbound
    port to the admin host.
  3. **Gate access at the edge**
Front the public URL with your SSO/OIDC at the edge so only authenticated users
    reach the internal service — the zero-trust ingress pattern. The box-side agent
    stays a pure byte pipe; policy lives at the PoP.

## Related

- [Tunnel overview](/modalities/tunnel/details) — wire model & architecture
- [SDK & CLI](/modalities/tunnel/sdk-methods) — full command surface
- [Cookbook](/modalities/tunnel/cookbook) — short task snippets
