Skip to main content
Tunnels expose your local NullClaw gateway to the internet without port forwarding or firewall configuration.

Why Tunnels?

Webhook-based channels (Telegram, Discord, Slack) require a public HTTPS URL to receive events. Tunnels provide this by:
  1. Establishing an outbound connection from your gateway to a tunnel server
  2. The tunnel server provides a public HTTPS URL
  3. Incoming webhook requests are forwarded through the tunnel to your local gateway

Supported Providers

NullClaw supports multiple tunnel providers:

Cloudflare Tunnel

Free, unlimited bandwidth, zero-trust security

ngrok

Popular, reliable, generous free tier

Tailscale Funnel

Tailnet-based, secure, funnel mode for public access

Custom

Bring your own tunnel (bore, localtunnel, etc.)

Configuration

Add tunnel configuration to ~/.nullclaw/config.json:

Cloudflare Tunnel

Cloudflare Tunnel (formerly Argo Tunnel) provides free, unlimited bandwidth with zero-trust security.

Prerequisites

  1. Cloudflare account (free)
  2. Install cloudflared CLI:

Setup

1

Login to Cloudflare

This opens a browser to authenticate with Cloudflare.
2

Create tunnel

This generates a tunnel token.
3

Get tunnel token

Copy the token (starts with eyJ...).
4

Add to config

How It Works

NullClaw spawns cloudflared as a child process:
The tunnel URL is extracted from stderr output:

Implementation

From src/tunnel.zig:

ngrok

ngrok is a popular tunnel service with a generous free tier.

Prerequisites

  1. ngrok account (free): https://ngrok.com/signup
  2. Install ngrok CLI:

Setup

1

Get auth token

Login to ngrok dashboard and copy your auth token from: https://dashboard.ngrok.com/get-started/your-authtoken
2

Add to config

How It Works

NullClaw spawns ngrok:
The tunnel URL is extracted from stdout:

Custom Domain

With a paid ngrok plan, you can use a custom domain:

Tailscale Funnel

Tailscale Funnel exposes a service on your tailnet to the public internet.

Prerequisites

  1. Tailscale account (free): https://tailscale.com/
  2. Install Tailscale:
  1. Login to Tailscale:

Setup

1

Enable funnel mode

Funnel vs Serve

  • tailscale serve: Exposes to your tailnet only (private)
  • tailscale funnel: Exposes to public internet (requires funnel mode)
Set "funnel": true for public webhooks.

How It Works

NullClaw spawns:
The URL is constructed from your Tailscale hostname:

Custom Tunnels

Bring your own tunnel provider (bore, localtunnel, etc.).

Configuration

Placeholders

  • {port}: Replaced with gateway port (e.g., 3000)
  • {host}: Replaced with localhost

How It Works

NullClaw:
  1. Replaces placeholders in start_command
  2. Spawns the command as a child process
  3. Reads stdout for a URL matching https://...
Example with bore:
Output:
NullClaw extracts https://abc123.bore.pub.

No Tunnel (Local Only)

Set provider to "none" to disable tunnels:
The gateway only accepts connections on localhost. Webhooks will not work.

Tunnel State

NullClaw tracks tunnel state:
Check tunnel status:

Security Considerations

Tunnels expose your gateway to the internet. Ensure you:
  • Use webhook secret tokens (Telegram, Discord, Slack)
  • Enable pairing mode for interactive sessions
  • Review security policies in ~/.nullclaw/config.json
  • Monitor tunnel logs for unauthorized access

Webhook Secrets

Always configure webhook secret tokens: Telegram:
Discord:

Tunnel Lifecycle

Start

Stop

This kills the child process and cleans up resources.

URL Extraction

NullClaw scans tunnel process output for HTTPS URLs:

Troubleshooting

Tunnel binary not found

Ensure the tunnel CLI is in your PATH:
Install the missing binary:

URL not extracted

NullClaw reads tunnel process output to find the URL. If extraction fails:
  1. Check tunnel process logs
  2. Verify the tunnel is actually starting
  3. Ensure output contains https:// URL

Tunnel disconnects

Free tunnel plans may have:
  • Idle timeouts
  • Bandwidth limits
  • Connection limits
Consider upgrading to a paid plan for production use.

Port already in use

If the gateway port is already bound:
Or change the gateway port:

Implementation Reference

The tunnel system is implemented in src/tunnel.zig with a vtable-based architecture:
Each provider implements this interface:
  • NoneTunnel (no-op)
  • CloudflareTunnel
  • NgrokTunnel
  • TailscaleTunnel
  • CustomTunnel
See ~/workspace/source/src/tunnel.zig for full implementation.