Quick Start
Up and running in a minute
Install the CLI, connect it to your SubTunnel server, and expose a local port on your own domain.
$ curl -sSL https://www.subtunnel.dev/install.sh | sh
$ subtunnel local 3000 --to your-server.example.com:7835 \
--token YOUR_TOKEN --subdomain myapp
Forwarding https://myapp.your-server.example.com -> localhost:3000
Installation
Install the binary
The install script detects your platform and places one static binary in /usr/local/bin. It supports macOS and Linux.
$ curl -sSL https://www.subtunnel.dev/install.sh | shManual download. Download the binary for your platform from GitHub Releases, extract it, and place it in your PATH.
Self-Hosting
Run your own server
Everything below runs on one small VPS. You need a domain and a server with ports 80, 443, and 7835 reachable.
- 01
Point DNS at your server
Create A records for the tunnel domain and its wildcard, both pointing to your server's public IP address.DNS recordsA tunnel.example.com → 203.0.113.10 A *.tunnel.example.com → 203.0.113.10 - 02
Install SubTunnel on the server
SSH into the VPS and install the same static binary used by the client.$ curl -sSL https://www.subtunnel.dev/install.sh | sh - 03
Generate a token
Create a shared secret that clients will use to authenticate with the server.$ openssl rand -hex 16 - 04
Set up nginx TLS termination
Use nginx to terminate TLS and forward HTTP traffic to SubTunnel's HTTP listener on port 8080.nginx.conf# Wildcard HTTPS routes *.tunnel.example.com to SubTunnel server { listen 443 ssl; server_name *.tunnel.example.com; ssl_certificate /etc/letsencrypt/live/tunnel.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/tunnel.example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }For wildcard certificates, use DNS-based validation with certbot:
certbot certonly --dns-cloudflare -d tunnel.example.com -d *.tunnel.example.com. - 05
Start the server
Start the control plane on port 7835 and the internal HTTP listener on port 8080.$ subtunnel server --domain tunnel.example.com --token YOUR_TOKEN --port 7835 --http-port 8080 - 06
Run as a systemd service
For production, run SubTunnel as a systemd service so it starts on boot and restarts automatically./etc/systemd/system/subtunnel.service[Unit] Description=SubTunnel Server After=network.target [Service] Type=simple User=subtunnel ExecStart=/usr/local/bin/subtunnel server \ --domain tunnel.example.com \ --token YOUR_TOKEN \ --port 7835 \ --http-port 8080 Restart=always RestartSec=5 [Install] WantedBy=multi-user.targetEnable and start$ sudo systemctl enable subtunnel $ sudo systemctl start subtunnel $ sudo systemctl status subtunnel - 07
Connect a client
From your local machine, connect a port to the server and request its public subdomain.$ subtunnel local 3000 --to tunnel.example.com:7835 --token YOUR_TOKEN --subdomain myapp
CLI Reference
Four focused command areas.
Run the public server, connect one local port directly, start configured tunnels, or manage the client as a native service.
subtunnel server
Run the public-facing server that accepts client connections and routes traffic.
| Flag | Description |
|---|---|
--port | Control-plane listen port. Default: 7835. |
--http-port | HTTP listener receiving proxied traffic from nginx. Default: 8080. |
--host | Bind address. Default: 0.0.0.0. |
--domain | Required. Domain for tunnel subdomains. |
--extra-domain | Additional accepted domain. Repeatable. |
--token | Authentication token agents must provide. Env: SUBTUNNEL_TOKEN. |
--tls-cert | TLS certificate PEM path. |
--tls-key | TLS private key PEM path. |
subtunnel local
Connect to a SubTunnel server and expose one local port.
| Flag | Description |
|---|---|
<port> | Positional local port to expose. |
--to | Server address in host:port format. |
--token | Authentication token. Env: SUBTUNNEL_TOKEN. |
--subdomain | Request a specific subdomain. |
--tls-verify | Verify the server TLS certificate. Default: true. Set false for self-signed certificates. |
--tls-ca | Custom CA certificate PEM path. |
subtunnel run
Read a TOML config and start all tunnels, or a named subset, in one process. Each tunnel has its own connection and reconnect loop. Keeping the token in the config avoids exposing it in the process list.
server = "tunnel.example.com:7835"
token = "YOUR_TOKEN"
[tunnels.myapp]
local_port = 3000
subdomain = "myapp"$ subtunnel run --all
$ subtunnel run myapp --config /absolute/path/to/config.tomlsubtunnel service
Install the configured client agent as a systemd service on Linux or a launchd service on macOS. Normal users install a user service. Running the command with sudo installs a system service. SubTunnel does not manage your application process.
$ subtunnel service install --config /absolute/path/to/config.toml
$ subtunnel service status
$ subtunnel service generate systemd --config /absolute/path/to/config.toml