Tunnel manager and client: expose a local port via a public HTTPS URL using a central server, Caddy, and SSH reverse forwarding.
burrow/
├── cmd/
│ ├── client/ # CLI to create and maintain a tunnel
│ └── server/ # Tunnel manager API + Caddy integration
├── internal/
│ ├── client/ # Client logic (API, SSH, banner)
│ ├── models/ # Shared API types (Session, requests)
│ └── server/ # Server logic (sessions, Caddy, proxy, handlers)
├── go.mod
├── Makefile
└── README.md
make build
# or
go build -o bin/burrow-client ./cmd/client
go build -o bin/burrow-server ./cmd/serverRuns the HTTP API that allocates ports and registers routes with Caddy. Caddy must be running with the admin API enabled.
./bin/burrow-server
# or with options:
./bin/burrow-server -addr :8080 -caddy http://localhost:2019 -domain tunnel.example.com -port-min 10000 -port-max 20000Flags:
-addr— listen address (default:8080)-caddy— Caddy admin API URL (defaulthttp://localhost:2019)-domain— base domain for tunnels (defaulttunnel.doubletick.dev)-port-min/-port-max— port range for tunnel backends
Registers a tunnel with the server and opens an SSH reverse tunnel so traffic to the allocated port reaches your local service.
./bin/burrow-client -port 3000 -key ./key.pem
# Named tunnel (stable subdomain):
./bin/burrow-client -port 3000 -key ./key.pem -named user1Flags:
-port— local port to expose (required)-key— path to SSH private key (required)-named— optional stable subdomain-server— tunnel server hostname-api-port— API port on server (default8080)-ssh-user— SSH user on server (defaultubuntu)
POST /tunnels— create tunnel ({"client_port": 3000, "named": "user1"}optional)GET /tunnels— list tunnelsGET /tunnels/{id}— get tunnelDELETE /tunnels/{id}— remove tunnelDELETE /tunnels— remove all tunnels