GitHub - cosmind-rusu/smuf: Self-hosted HTTP tunnel tool — like ngrok, but yours. No quotas, no limits, on your own server.

SELF-HOSTED · OPEN SOURCE · WRITTEN IN GO

- * *
smuf exposes a local port on a public URL — like ngrok, but **yours**: no quotas, no limits, on your own server.
``` localhost:3000 ◄─────► https://a3f1c9.yourdomain.com ```

- * *
Deploy on Railway
[](https://github.com/cosmind-rusu/smuf#deploy-on-railway) One-click deploy `smuf-server` to Railway:

Once deployed, the server URL and auth token are set via Railway's environment variables (see Configuration below). Then connect with the client from any machine.
- * *
Installation
[](https://github.com/cosmind-rusu/smuf#installation)
Option A: Download a binary (recommended)
[](https://github.com/cosmind-rusu/smuf#option-a-download-a-binary-recommended) Go to Releases and download the binary for your OS.
| Binary | Where it goes | | --- | --- | | `smuf-server` | Your VPS / server | | `smuf` | Your local machine |
Option B: Docker
[](https://github.com/cosmind-rusu/smuf#option-b-docker)
docker compose up -d
Option C: Build from source
[](https://github.com/cosmind-rusu/smuf#option-c-build-from-source) You'll need Go 1.21+.
git clone https://github.com/cdrusu/smuf.git && cd smuf go build -o smuf-server ./cmd/smuf-server go build -o smuf ./cmd/smuf
- * *
Usage
[](https://github.com/cosmind-rusu/smuf#usage) **First time:** run without arguments and the wizard will set everything up:
./smuf-server # on the server ./smuf --setup # on your machine
**After that:**
./smuf 3000 # exposes localhost:3000 ./smuf 3000 4000 5000 # multiple ports at once ./smuf --sub myapp 3000 # fixed URL: myapp.yourdomain.com ./smuf --tcp 22 # pure TCP tunnel (SSH, DB, etc.)
Output:
``` Tunnel ready!
Local → http://localhost:3000 Public → https://a3f1c9.yourdomain.com
Press Ctrl+C to stop ```
- * *
Dashboard
[](https://github.com/cosmind-rusu/smuf#dashboard) While the server is running, open in your browser:
``` http://yourdomain.com:8080/ ```
It is designed in HashiCorp style: dark `#0d0e12` background, system-ui font, cards with micro-shadows and blue accent (`#1060ff`).
Shows all active tunnels with:
- Tunnel type (HTTP / TCP)
- Public URL
- Local port and client IP
- Uptime
Updates every 5 s. The JSON endpoint is at `/_smuf/tunnels`.
- * *
Configuration
[](https://github.com/cosmind-rusu/smuf#configuration) Everything goes through environment variables (or a `.env` file next to the binary).
Server (`smuf-server`)
[](https://github.com/cosmind-rusu/smuf#server-smuf-server) | Variable | Default | Description | | --- | --- | --- | | `SMUF_DOMAIN` | `localhost` | Your base domain | | `SMUF_AUTH_TOKEN` | — | Secret token (**recommended in production**) | | `SMUF_CONTROL_PORT` | `7000` | Port for clients to connect | | `SMUF_HTTP_PORT` | `8080` | Public HTTP port | | `SMUF_HTTPS` | `false` | Automatic HTTPS with Let's Encrypt | | `SMUF_HTTPS_PORT` | `443` | HTTPS port | | `SMUF_ACME_EMAIL` | — | Email for certificate notices | | `SMUF_MAX_CONNS_PER_IP` | `5` | Max tunnels per IP | | `SMUF_HANDSHAKE_TIMEOUT` | `10s` | Handshake timeout | | `SMUF_TCP_PORT_RANGE` | — | Public TCP port range (e.g. `20000-30000`) |
Client (`smuf`)
[](https://github.com/cosmind-rusu/smuf#client-smuf) | Variable | Default | Description | | --- | --- | --- | | `SMUF_SERVER` | `localhost:7000` | Server address | | `SMUF_AUTH_TOKEN` | — | Token (must match the server) | | `SMUF_SUBDOMAIN` | — | Fixed subdomain (equivalent to `--sub`) |
**Server `.env` example:**
SMUF_DOMAIN=yourdomain.com SMUF_AUTH_TOKEN=a-long-secret-token
SMUF_HTTPS=true
SMUF_ACME_EMAIL=you@email.com
**Client `.env` example:**
SMUF_SERVER=yourdomain.com:7000 SMUF_AUTH_TOKEN=a-long-secret-token
SMUF_SUBDOMAIN=myapp
> Generate a secure token with `openssl rand -hex 32`
- * *
How it works
[](https://github.com/cosmind-rusu/smuf#how-it-works)
``` smuf 3000 ──TCP──► smuf-server :7000 │ "PORT 3000 SUB myapp" → "OK myapp https://myapp.yourdomain.com" │ yamux (multiplexing) │ request → myapp.yourdomain.com → yamux stream → localhost:3000 ```
Uses `hashicorp/yamux` to multiplex multiple HTTP requests over a single TCP connection.
- * *
Roadmap
[](https://github.com/cosmind-rusu/smuf#roadmap)
- Automatic HTTPS with Let's Encrypt
- Token authentication
- Per-IP rate limiting
- Real-time web dashboard (HashiCorp style)
- Multiple tunnels per process
- Custom subdomain
- WebSockets
- TCP tunnels (not only HTTP)
- Official Docker image
- Pre-compiled binaries
- Server-Sent Events (SSE)
- * *
Project structure
[](https://github.com/cosmind-rusu/smuf#project-structure)
``` smuf/ ├── cmd/ │ ├── smuf/ # Client (your machine) │ └── smuf-server/ # Server (your VPS) └── internal/ ├── tunnel/ # Registry + BufConn ├── wizard/ # Interactive setup └── logger/ # Timestamped logging ```
- * *
Contributing
[](https://github.com/cosmind-rusu/smuf#contributing) Found a bug or have an idea? Open an issue or submit a pull request.
- * *