<!--
hoody-tunnel Subskill (http)
Auto-generated by Hoody Skills Generator
Generated: 2026-06-20T00:39:27.569Z
Model: mimo-v2.5-pro
Mode: http


Tokens: 6071

DO NOT EDIT MANUALLY - Changes will be overwritten on next generation
-->

# hoody-tunnel Subskill

## Overview

The `hoody-tunnel` service provides a **multiplexed, secure tunneling layer** for direct container-to-client and client-to-container communication within the Hoody ecosystem. It acts as a reverse tunnel broker, allowing containers to securely expose services (`EXPOSE` bindings) and clients to securely pull connections (`PULL` bindings) over a single, authenticated WebSocket session.

**When to use this service:**
- To establish a persistent, multiplexed network tunnel to a running container.
- To securely expose a container's internal port (e.g., a database or debug server) to a client.
- To enable a client to initiate a direct connection into a container's network namespace.
- To monitor active tunnel sessions, bindings, and connection health.
- To programmatically manage (kill) active tunnel sessions.

**Philosophy Fit:** This service embodies Hoody's core principles of **secure, zero-config networking** and **developer empowerment**. It removes the complexity of manual port forwarding, firewall rules, and DNS setup. By providing automatic routing, authentication, and isolation, `hoody-tunnel` allows developers to focus on their application logic while the platform handles secure connectivity. It integrates with the Hoody Proxy routing system for consistent domain-based access.

---

## Common Workflows

### 1. Checking Service Health
Verify the tunnel service is running and responsive. No authentication is required for this endpoint.
```
# Replace {base_url} with your hoody-tunnel service's URL.
curl -s -X GET "{base_url}/api/v1/tunnel/health"
```
**Example Response:**
```
{
  "status": "ready",
  "service": "hoody-tunnel",
  "built": "2024-10-26T14:30:00Z",
  "started": "2025-11-05T08:15:22Z",
  "memory": {
    "rss": 23456789,
    "heapTotal": 15000000,
    "heapUsed": 12000000
  },
  "fds": 45,
  "pid": 1234,
  "ip": "192.168.1.100",
  "userAgent": "hoody-tunnel/1.2.3"
}
```
**Next Step:** A `status` of `"ready"` confirms the service is operational. Proceed to list active tunnels or establish a connection.

### 2. Listing All Active Tunnels and Bindings
Get a unified view of all active tunnel sessions, their bindings, and resource status. This is your primary discovery endpoint.
```
curl -s -X GET "{base_url}/api/v1/tunnel/tunnels"
```
**Example Response:**
```
[
  {
    "session_id": "sess_abc123xyz",
    "container_id": "ctr_987654",
    "protocol_version": "hoody-tunnel.v2",
    "created_at": "2025-11-05T09:00:00Z",
    "bindings": [
      {
        "bind_id": "bind_expose_001",
        "kind": "EXPOSE",
        "port": 5432,
        "mode": "tcp"
      },
      {
        "bind_id": "bind_pull_002",
        "kind": "PULL",
        "port": 22,
        "mode": "tcp"
      }
    ],
    "stream_count": 5,
    "orphan_count": 0,
    "fd_budget": {
      "used": 15,
      "limit": 100
    }
  }
]
```
**Next Step:** Use the `session_id` to connect to a specific tunnel or to manage (kill) a session.

### 3. Establishing a New Tunnel Connection
Initiate a WebSocket-based tunnel session. This is a client-side operation performed with a WebSocket client (e.g., `websocat`, `wscat`, or application code). The client must request the correct subprotocol.
```
# This is a conceptual example. Actual command depends on your WebSocket client.
websocat --header "Authorization: Bearer {your_token}" \
         --protocol hoody-tunnel.v2 \
         "{base_url}/api/v1/tunnel/connect"
```
**Client Requirements:**
1.  **Subprotocol:** MUST request `hoody-tunnel.v1` or `hoody-tunnel.v2`.
2.  **First Message:** The first binary message sent MUST be a `HELLO` frame. The format is defined in the service's protocol specification (README).
3.  **Authentication:** The WebSocket handshake request must include valid Hoody authentication credentials.

**State Verification:** After a successful handshake, the new session will appear in the output of `GET /api/v1/tunnel/sessions` and `GET /api/v1/tunnel/tunnels`.

### 4. Monitoring Session and Binding Details
Inspect detailed information about active sessions and their specific bindings.
```
# List all sessions with binding details
curl -s -X GET "{base_url}/api/v1/tunnel/sessions"

# List only the active bindings (port, kind, mode)
curl -s -X GET "{base_url}/api/v1/tunnel/bindings"
```
**Example `/sessions` Response:**
```
[
  {
    "session_id": "sess_abc123xyz",
    "container_id": "ctr_987654",
    "protocol_version": "hoody-tunnel.v2",
    "created_at": "2025-11-05T09:00:00Z",
    "bindings": [
      {
        "bind_id": "bind_expose_001",
        "kind": "EXPOSE",
        "port": 5432,
        "mode": "tcp"
      }
    ],
    "stream_count": 3,
    "max_streams": 50
  }
]
```
**Use Case:** Correlate a container ID from your deployment with its active tunnel session and exposed ports.

### 5. Terminating a Specific Session
Gracefully close a tunnel session by its ID. The session receives a `GOAWAY` frame and is force-closed after a grace period.
```
# Replace {session_id} with the actual session ID from the /tunnels or /sessions response.
curl -s -X DELETE "{base_url}/api/v1/tunnel/sessions/{session_id}?session_id={session_id}"
```
**Note:** The `session_id` is required both in the URL path and as a query parameter per the schema.
**Verification:** The terminated `session_id` should disappear from subsequent calls to `GET /api/v1/tunnel/tunnels`.

---

## Advanced Operations

### 1. Multi-Tunnel Orchestration
When a single container exposes multiple services (e.g., app on 8080, debug on 9222), the tunnel system handles multiple bindings within one session.
1.  **Connect** to the container's tunnel endpoint once.
2.  The `HELLO` frame protocol defines which ports the client requests to expose or pull.
3.  **Verify** using `GET /api/v1/tunnel/tunnels`. The response will show an array of `bindings` for that `session_id`.
```
"bindings": [
  { "bind_id": "bind_expose_http", "kind": "EXPOSE", "port": 8080, "mode": "tcp" },
  { "bind_id": "bind_expose_debug", "kind": "EXPOSE", "port": 9222, "mode": "tcp" },
  { "bind_id": "bind_pull_ssh", "kind": "PULL", "port": 22, "mode": "tcp" }
]
```

### 2. Connection Error Recovery
If a tunnel connection drops:
1.  **Check Health:** `GET /api/v1/tunnel/health` to ensure the service is stable.
2.  **Check for Orphans:** Use `GET /api/v1/tunnel/tunnels` and look for sessions with a high `orphan_count` or sessions where your container no longer exists. These can be cleaned up with `DELETE`.
3.  **Reconnect:** Establish a new WebSocket connection via `/connect`. The system assigns a new `session_id`.

### 3. Performance Monitoring with Metrics
Use the Prometheus-format metrics endpoint to monitor tunnel load and set up alerts.
```
curl -s -X GET "{base_url}/api/v1/tunnel/metrics"
```
**Example Response Snippet:**
```
# HELP hoody_tunnel_sessions_active Number of active tunnel sessions.
# TYPE hoody_tunnel_sessions_active gauge
hoody_tunnel_sessions_active 12
# HELP hoody_tunnel_bindings_active Total active EXPOSE and PULL bindings.
# TYPE hoody_tunnel_bindings_active gauge
hoody_tunnel_bindings_active 28
# HELP hoody_tunnel_fd_permits_permit_count Current FD permit allocation.
# TYPE hoody_tunnel_fd_permits_permit_count gauge
hoody_tunnel_fd_permits_permit_count 150
```
**Consideration:** Monitor `hoody_tunnel_sessions_active` and `hoody_tunnel_fd_permits_permit_count` to understand capacity. A high number relative to limits may indicate a need to clean up stale sessions.

### 4. Session Lifecycle Scripting
Combine endpoints for automated management. Example script logic:
1.  `tunnels_list = GET /api/v1/tunnel/tunnels`
2.  `for tunnel in tunnels_list:`
    - `if tunnel.container_id == OLD_CONTAINER and tunnel.created_at < threshold:`
      - `DELETE /api/v1/tunnel/sessions/{tunnel.session_id}?session_id={tunnel.session_id}`
      - `print(f"Cleaned up stale session {tunnel.session_id}")`
3.  Verify cleanup with a final `GET /api/v1/tunnel/tunnels`.

---

## Quick Reference

| Endpoint | Method | Purpose | Key Parameters / Notes |
| :--- | :--- | :--- | :--- |
| `/api/v1/tunnel/health` | GET | Service health check | None. Returns 9-field status object. |
| `/api/v1/tunnel/tunnels` | GET | Unified view of sessions & bindings | Most comprehensive discovery endpoint. |
| `/api/v1/tunnel/sessions` | GET | List active sessions | Returns session details and binding list. |
| `/api/v1/tunnel/bindings` | GET | List all active bindings | Shows port, kind (EXPOSE/PULL), mode. |
| `/api/v1/tunnel/metrics` | GET | Prometheus metrics | Returns sessions_active, bindings_active, fd_permits. |
| `/api/v1/tunnel/connect` | GET (WS) | **WebSocket upgrade** for new tunnel | Requires subprotocol `hoody-tunnel.v1` or `v2`. First msg is `HELLO` frame. |
| `/api/v1/tunnel/sessions/{session_id}` | DELETE | Kill a specific session | **Required:** `session_id` in path **and** as query param. Sends `GOAWAY`. |

**Essential Response Fields:**
- `session_id` (string): Unique identifier for a tunnel connection. Use for management.
- `bind_id` (string): Unique identifier for a port binding within a session.
- `kind` (string): `"EXPOSE"` (container->client) or `"PULL"` (client->container).
- `port` (number): The TCP/UDP port number being bound.
- `mode` (string): Protocol, typically `"tcp"`.
- `stream_count` (number): Active data streams within the session.

**Base URL Derivation:**
`https://{projectId}-{containerId}-tunnel-{serviceId}.{node}.containers.hoody.com`
*(Replace variables with your Hoody project and container identifiers. Obtain the correct node from your Hoody platform configuration.)*