MIT Open Source — v1.1.0
Webhook debugging.
Persistent history.
Your infrastructure.
Self-hosted reverse tunnel server with a persistent request inspector and replay engine. Your webhook traffic never leaves your network. The history is yours.
Quick Start
# 1. Clone and configure the server git clone https://github.com/sqoia-dev/tunnl cd tunnl cp .env.example .env # edit: set DOMAIN and JWT_SECRET docker compose up -d # 2. Install the CLI and connect curl -sSL https://tunnl.sh/install.sh | sh tunnl login --server https://your.domain.com tunnl --port 3000 # → https://abc123.your.domain.com
What you get
Everything in the debugging loop
Built for the specific problem: you changed your handler, you need the same webhook payload again.
💾
Persistent request history
Full headers and bodies in PostgreSQL. Survives process restarts, reconnects, and browser closes. Configurable retention — default 30 days.
↺
One-click replay
Re-send any captured request with its original headers, including signature headers from Stripe, GitHub, Slack, and Shopify. Diff the original vs replayed response.
🔎
TUI inspector
tunnl inspect opens a split-pane terminal UI. Live request stream, request selection, replay, and curl export. Built with Bubble Tea.🤖
MCP server for AI agents
tunnl mcp exposes 8 tools over stdio. Claude Desktop, Cursor, and Copilot Agent Mode can query live tunnel traffic and replay requests without you leaving the editor.🏠
Self-hosted
Your data stays on your network. Wildcard subdomain routing via Caddy. PostgreSQL for storage. Docker Compose for the server and database. No vendor lock-in.
📜
MIT licensed
Server and CLI are both open source under the MIT license. Read it, fork it, modify it. No usage-based restrictions. No telemetry.
Protocol
How the tunnel works
WebSocket-based reverse proxy with HTTP/2 passthrough and per-chunk back-pressure.
1
CLI connects to your server
The
tunnl CLI opens a persistent WebSocket to your self-hosted server. It registers a subdomain and waits for inbound requests.2
Webhook arrives at the subdomain
Stripe, GitHub, or any provider POSTs to
abc123.webhooks.yourdomain.com. Caddy routes it to the Go server. The full request is serialized and stored in PostgreSQL.3
Request forwarded to localhost
The server sends the request over the WebSocket to your CLI. The CLI forwards it to
localhost:3000, captures the response, and sends it back. Supports HTTP/2 and streaming.4
Inspect and replay anytime
The request lives in PostgreSQL. Kill the terminal, restart the server, reconnect from a different machine — the history is still there. Replay it with original headers from the dashboard or TUI.
Resources
Get started
📦
Self-Hosted Install Guide
Docker Compose, DNS, TLS, first tunnel
💻
CLI Reference
Every subcommand, flag, and env var
⚙️
Configuration Reference
All server .env variables
🤖
MCP Server Guide
AI agent integration via stdio
⚡
Monorepo on GitHub
Server, CLI, protocol — Go, MIT
🔧
CLI Source
cmd/tunnl — static binary, Go, MIT
🐳
Docker Image
ghcr.io/sqoia-dev/tunnl-server
📝
Changelog
Release history