cmd / tun

tun tunnels local services to the public internet.

It is open source.

Why

I wanted a self-hosted tunnel like ngrok for a Slack Events API integration. It needs no vendor account and keeps data in our infrastructure.

Set up the server

Deploy the server to a host such as Render:

Render provides HTTPS. A scale-to-zero plan keeps the cost low for an occasional tunnel.

Server logs:

[croaky] tunnel connected
200 POST /slack/events 147.33ms
[croaky] tunnel disconnected

Set up the client

Install:

go install github.com/croaky/tun/cmd/tun@latest

Create a .env file in the directory where you run tun:

TUN_SERVER=wss://your-service.onrender.com/tunnel
TUN_LOCAL=http://localhost:3000
TUN_ALLOW="POST /slack/events GET /health"
TUN_TOKEN=...

TUN_ALLOW accepts space-separated METHOD /path pairs (exact match, no wildcards). A request that matches no rule returns 403 Forbidden.

TUN_TOKEN authenticates the client to the server with Authorization: Bearer <token>.

Run:

tun

Client logs:

[croaky] connected to wss://your-service.onrender.com/tunnel, forwarding to http://localhost:3000
POST /slack/events

The username comes from git config github.user, or $USER. It shows who holds the tunnel when teammates share a server.

The client reconnects with exponential backoff from 500ms to 30s. Requests time out after 30 seconds. The server accepts one tunnel at a time. A new connection closes the previous one.

← All articles