Surang

tunnels you own.

Surang is a self-hostable tunnel server. Expose anything running on your machine through a public URL, the same idea as ngrok, except the server is yours.

Works behind NAT Many tunnels, one connection Auto TLS via Let's Encrypt
A green warp pipe. localhost enters the open mouth on the left, a public URL comes out the right end
// Enter the warp pipe

Install the client

One command, no dependencies. Grabs the right surang-client binary for your OS and arch from GitHub releases (Linux and macOS; on Windows, grab a binary from the releases page).

terminal
$ curl https://surang.eulerbutcooler.xyz/install.sh | sh
$ surang-client login
$ surang-client -tunnel web=localhost:3000

Prefer to read before piping? The script is plain POSIX sh, read it here, or pin a version with curl -fsSL https://surang.eulerbutcooler.xyz/install.sh | sh -s -- v0.2.1. Run surang-client login with server address https://api.surang.eulerbutcooler.xyz, pick “Create an account”, then open a tunnel from any local port. Running your own server instead? The self-host section below covers that.

// World 1-1

What is surang?

surang-server runs on a VPS with a wildcard domain. surang-client runs on your machine, dials out to the server, and every request to your assigned subdomain gets routed down the tunnel to your local port.

NAT? No problem

The client dials out and keeps one persistent connection open. No port forwarding, no public IP needed on your side.

Many tunnels, one wire

Multiple tunnels per client ride a single outbound connection. -tunnel api=localhost:4000 is just another flag away.

3-word subdomains

Random hyphenated names like crown-cycle-dimmed, so one wildcard certificate covers every tunnel.

Accounts & tokens

Email + password accounts, API tokens with selectable expiry (1h, 1d, 1w, never). A TUI login saves the token locally.

Auto TLS

One wildcard cert for the domain and *.domain, issued and renewed automatically via Let's Encrypt DNS-01.

Bytes in, bytes out

The tunnel never inspects HTTP. It relays raw bytes both directions over multiplexed streams. Fast and dumb, on purpose.

// The warp zone

How it works

A visitor hits your subdomain, the server finds your client's session, opens a new stream, and pipes bytes end to end.

Browservisitor
Server :443wildcard TLS
Yamux streamone TCP conn
surang-clientyour machine
localhost:3000your service

The client dials the server's control port and keeps the connection open. It's an outbound connection, so NAT never gets in the way. That connection is a yamux session: one TCP connection carrying many streams. The server maps each public subdomain to a session in an in-memory registry. When a visitor hits a subdomain, the server opens a new stream, writes a dial frame naming the tunnel label, and relays raw bytes. The client reads the label, dials the local service, and pipes both directions. The registry dies with the process, so tunnels are ephemeral by design. Users and tokens live in SQLite on disk, stored as hashes.

// Build your own level

Self-host it

A VPS, a domain on Cloudflare DNS, and one Docker command.

1

Run the server

Add a CF_DNS_API_TOKEN (Zone:DNS:Edit) so Let's Encrypt can do DNS-01 for the wildcard cert.

docker run -d --name surang \
  -e CF_DNS_API_TOKEN=your_cloudflare_token \
  -p 443:443 -p 80:80 -p 5555:5555 -p 9000:9000 \
  -v surang-data:/data \
  ghcr.io/eulerbutcooler/surang-server:latest \
  -domain surang.xyz -tls-domain surang.xyz \
  -tls-email you@example.com -db /data/surang.db

No Docker? Grab a server binary from releases and run it under systemd. Plaintext dev mode is just surang-server -domain surang.xyz -db surang.db.

2

Point DNS at it

Two A records, DNS-only (grey cloud, since the CF proxy would break TLS termination and the control port):

# type   name    content
A        @       your.server.ip
A        *       your.server.ip

Open ports 443, 80 and 5555 in the host firewall and cloud security list.

3

Log in & tunnel

Install the client, then:

surang-client login          # server = https://api.your.domain
surang-client -tunnel web=localhost:3000
✓ web → https://crown-cycle-dimmed.surang.xyz
// Press start

Drop your localhost
into the pipe.

curl https://surang.eulerbutcooler.xyz/install.sh | sh
Copied!