<!-- source: https://deepwiki.com/qhkm/zeptoclaw/12.6-tunnel-integration -->

# Tunnel Integration

- src/tunnel/cloudflare.rs
- src/tunnel/ngrok.rs
- src/tunnel/tailscale.rs

## Purpose and Scope

This page documents ZeptoClaw's tunnel integration system, which provides secure remote access to gateway deployments by integrating with external tunnel providers (Cloudflare, ngrok, and Tailscale). Tunnel integration allows ZeptoClaw to expose its local gateway to the internet without manual port forwarding or firewall configuration.

For information about gateway deployment modes, see [Container Gateway Mode](/qhkm/zeptoclaw/12.3-container-gateway-mode). For general deployment strategies, see [Deployment Options](/qhkm/zeptoclaw/12.1-deployment-options). For gateway CLI commands, see [Gateway Commands](/qhkm/zeptoclaw/4.3-gateway-commands).

**Sources:** [src/tunnel/cloudflare.rs1-4](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L1-L4) [src/tunnel/ngrok.rs1-5](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L1-L5) [src/tunnel/tailscale.rs1-4](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L1-L4)

## Overview

Tunnel integration is an optional feature that automatically starts and manages an external tunnel when running ZeptoClaw in gateway mode. The tunnel creates a secure connection from a public endpoint to your local ZeptoClaw gateway, enabling communication channels to reach the agent without exposing your server directly to the internet.

The system supports three tunnel providers with automatic fallback and a common lifecycle interface.

**Sources:** [src/tunnel/cloudflare.rs1-4](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L1-L4) [src/tunnel/ngrok.rs1-5](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L1-L5) [src/tunnel/tailscale.rs1-4](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L1-L4)

## System Architecture

### Tunnel Provider Abstraction

```

```

**Diagram: Tunnel Provider Architecture**

The `TunnelProvider` trait defines a common interface for all tunnel implementations. Each provider wraps an external binary (`cloudflared`, `ngrok`, `tailscale`) and manages its lifecycle via `tokio::process::Child`.

**Sources:** [src/tunnel/cloudflare.rs16-20](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L16-L20) [src/tunnel/ngrok.rs16-20](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L16-L20) [src/tunnel/tailscale.rs15-19](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L15-L19) [src/tunnel/types.rs1-20](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/types.rs#L1-L20)

## TunnelProvider Trait

The `TunnelProvider` trait defines the lifecycle interface for all tunnel implementations:

```

```

**Key Methods:**

**Sources:** [src/tunnel/cloudflare.rs62-65](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L62-L65) [src/tunnel/ngrok.rs69-72](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L69-L72) [src/tunnel/tailscale.rs73-76](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L73-L76) [src/tunnel/types.rs1-20](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/types.rs#L1-L20)

## Supported Tunnel Providers

### Cloudflare Tunnel

The `CloudflareTunnel` provider uses Cloudflare's tunnel feature via the `cloudflared` binary. It supports both "Quick Tunnels" (free, random URL) and "Named Tunnels" (via a token).

**Implementation Details:**

- Binary: cloudflared src/tunnel/cloudflare.rs 74
- Quick Tunnel: Uses --url http://localhost:PORT src/tunnel/cloudflare.rs 84-85
- Named Tunnel: Uses --token <TOKEN> run src/tunnel/cloudflare.rs 79
- URL Extraction: Scans stderr for https://*.trycloudflare.com or *.cfargotunnel.com using the extract_cloudflare_url utility src/tunnel/cloudflare.rs 37-59

**Sources:** [src/tunnel/cloudflare.rs16-160](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L16-L160)

### Ngrok Tunnel

The `NgrokTunnel` provider uses ngrok's HTTP tunnel feature.

**Implementation Details:**

- Binary: ngrok src/tunnel/ngrok.rs 79
- Command: ngrok http <PORT> src/tunnel/ngrok.rs 80
- URL Discovery: Polls the local ngrok API at http://127.0.0.1:4040/api/tunnels via the fetch_ngrok_url function src/tunnel/ngrok.rs 37-66
- Preferences: Prioritizes https:// URLs over http:// src/tunnel/ngrok.rs 49-52

**Sources:** [src/tunnel/ngrok.rs16-140](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L16-L140)

### Tailscale Funnel

The `TailscaleTunnel` provider uses Tailscale's `funnel` (public) or `serve` (tailnet-only) feature.

**Implementation Details:**

- Binary: tailscale src/tunnel/tailscale.rs 93
- Modes: Configurable via funnel: bool in TailscaleTunnelConfig . If funnel is true, it uses the funnel subcommand; otherwise, it uses serve src/tunnel/tailscale.rs 85-89
- Hostname Discovery: Runs tailscale status --json and parses Self.DNSName via get_tailscale_hostname src/tunnel/tailscale.rs 33-70
- Cleanup: Explicitly runs tailscale funnel off or tailscale serve off on stop src/tunnel/tailscale.rs 125-135

**Sources:** [src/tunnel/tailscale.rs15-148](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L15-L148)

## Data Flow: URL Extraction

```

```

**Diagram: Tunnel URL Extraction Flow**

**Sources:** [src/tunnel/cloudflare.rs109-131](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L109-L131) [src/tunnel/ngrok.rs105-116](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L105-L116)

## Configuration

### Configuration Structures

Tunnel settings are defined in the main configuration under the `tunnel` section.

**Sources:** [src/tunnel/cloudflare.rs11](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L11-L11) [src/tunnel/ngrok.rs11](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L11-L11) [src/tunnel/tailscale.rs10](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L10-L10)

## Lifecycle Management

### Startup Sequence

The gateway orchestrator initializes the tunnel before starting communication channels.

1. Resolution: The system determines the provider from CLI flags or config.
2. Initialization: CloudflareTunnel::new(config) , NgrokTunnel::new(config) , or TailscaleTunnel::new(config) is called.
3. Execution: start(local_port) is invoked.
4. Validation: The provider waits for the public URL to be emitted by the binary (with a timeout: 30s for Cloudflare src/tunnel/cloudflare.rs 117 15s for ngrok src/tunnel/ngrok.rs 106 ).
5. Persistence: The tokio::process::Child handle is stored in the struct to manage the process lifetime.

**Sources:** [src/tunnel/cloudflare.rs117-131](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L117-L131) [src/tunnel/ngrok.rs106-116](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L106-L116)

### Graceful Shutdown

All tunnel providers implement the `Drop` trait to ensure child processes are terminated when the gateway stops.

```

```

This prevents "zombie" tunnel processes from continuing to run after ZeptoClaw exits. Tailscale specifically performs an additional cleanup step by running the `off` subcommand [src/tunnel/tailscale.rs125-135](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L125-L135)

**Sources:** [src/tunnel/cloudflare.rs162-169](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L162-L169) [src/tunnel/ngrok.rs142-149](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L142-L149) [src/tunnel/tailscale.rs150-157](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L150-L157)

## Security Considerations

### 1. Binary Dependencies

ZeptoClaw relies on external binaries being present in the system `PATH`. The system does not download or manage these binaries automatically. Failure to find the binary results in a `ZeptoError::Config` [src/tunnel/cloudflare.rs101-106](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L101-L106)

### 2. Public Exposure

When a tunnel is active, the local gateway port is reachable from the public internet. It is critical to:

- Use Channel Allowlists to restrict who can interact with the agent.
- Use Safety Layers to detect and block malicious injections.
- Monitor the health_check() status which checks if the child process ID is still present src/tunnel/cloudflare.rs 150-159

### 3. Token Security

Tokens for ngrok and Cloudflare should be stored using ZeptoClaw's encrypted configuration format (`ENC[...]`) to prevent them from being stored in plaintext.

**Sources:** [src/tunnel/cloudflare.rs101-106](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/cloudflare.rs#L101-L106) [src/tunnel/ngrok.rs98-100](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/ngrok.rs#L98-L100) [src/tunnel/tailscale.rs38-43](https://github.com/qhkm/zeptoclaw/blob/2c743d31/src/tunnel/tailscale.rs#L38-L43)
