cosmind-rusu/smuf

Self-hosted HTTP tunnel tool — like ngrok, but yours. No quotas, no limits, on your own server.

7

stars

30

commits

Go

primary language

Sep 1, 2026

updated

smuf.cdrusu.com
http
network
ngrok
simple
tcp
tunnel
Browse cluster: Go Tunneling and Reverse Proxy

README

smuf — self-hosted HTTP tunnel

SELF-HOSTED · OPEN SOURCE · WRITTEN IN GO

Go License: Apache 2.0 Self-hosted yamux


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

smuf demo


Deploy on Railway

One-click deploy smuf-server to Railway:

Deploy on 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

Go to Releases and download the binary for your OS.

BinaryWhere it goes
smuf-serverYour VPS / server
smufYour local machine

Option B: Docker

docker compose up -d

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

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

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

Everything goes through environment variables (or a .env file next to the binary).

Server (smuf-server)

VariableDefaultDescription
SMUF_DOMAINlocalhostYour base domain
SMUF_AUTH_TOKENSecret token (recommended in production)
SMUF_CONTROL_PORT7000Port for clients to connect
SMUF_HTTP_PORT8080Public HTTP port
SMUF_HTTPSfalseAutomatic HTTPS with Let's Encrypt
SMUF_HTTPS_PORT443HTTPS port
SMUF_ACME_EMAILEmail for certificate notices
SMUF_MAX_CONNS_PER_IP5Max tunnels per IP
SMUF_HANDSHAKE_TIMEOUT10sHandshake timeout
SMUF_TCP_PORT_RANGEPublic TCP port range (e.g. 20000-30000)

Client (smuf)

VariableDefaultDescription
SMUF_SERVERlocalhost:7000Server address
SMUF_AUTH_TOKENToken (must match the server)
SMUF_SUBDOMAINFixed 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

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

  • 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

smuf/
├── cmd/
│   ├── smuf/           # Client (your machine)
│   └── smuf-server/    # Server (your VPS)
└── internal/
    ├── tunnel/         # Registry + BufConn
    ├── wizard/         # Interactive setup
    └── logger/         # Timestamped logging

Contributing

Found a bug or have an idea? Open an issue or submit a pull request.


smuf
Built with Go · Apache 2.0

Contributors

cosmind-rusu

30 commits

cosmind-rusu/smuf

Self-hosted HTTP tunnel tool — like ngrok, but yours. No quotas, no limits, on your own server.

7

stars

30

commits

Go

primary language

Sep 1, 2026

updated

smuf.cdrusu.com
http
network
ngrok
simple
tcp
tunnel
Browse cluster: Go Tunneling and Reverse Proxy

README

smuf — self-hosted HTTP tunnel

SELF-HOSTED · OPEN SOURCE · WRITTEN IN GO

Go License: Apache 2.0 Self-hosted yamux


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

smuf demo


Deploy on Railway

One-click deploy smuf-server to Railway:

Deploy on 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

Go to Releases and download the binary for your OS.

BinaryWhere it goes
smuf-serverYour VPS / server
smufYour local machine

Option B: Docker

docker compose up -d

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

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

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

Everything goes through environment variables (or a .env file next to the binary).

Server (smuf-server)

VariableDefaultDescription
SMUF_DOMAINlocalhostYour base domain
SMUF_AUTH_TOKENSecret token (recommended in production)
SMUF_CONTROL_PORT7000Port for clients to connect
SMUF_HTTP_PORT8080Public HTTP port
SMUF_HTTPSfalseAutomatic HTTPS with Let's Encrypt
SMUF_HTTPS_PORT443HTTPS port
SMUF_ACME_EMAILEmail for certificate notices
SMUF_MAX_CONNS_PER_IP5Max tunnels per IP
SMUF_HANDSHAKE_TIMEOUT10sHandshake timeout
SMUF_TCP_PORT_RANGEPublic TCP port range (e.g. 20000-30000)

Client (smuf)

VariableDefaultDescription
SMUF_SERVERlocalhost:7000Server address
SMUF_AUTH_TOKENToken (must match the server)
SMUF_SUBDOMAINFixed 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

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

  • 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

smuf/
├── cmd/
│   ├── smuf/           # Client (your machine)
│   └── smuf-server/    # Server (your VPS)
└── internal/
    ├── tunnel/         # Registry + BufConn
    ├── wizard/         # Interactive setup
    └── logger/         # Timestamped logging

Contributing

Found a bug or have an idea? Open an issue or submit a pull request.


smuf
Built with Go · Apache 2.0

Contributors

cosmind-rusu

30 commits

Languages

Go

66.1%

HTML

28.6%

Shell

1.8%

CSS

1.7%

Python

1.5%