Skip to main content
This is the complete reference for the rustunnel CLI — every flag, command, and config option. New to rustunnel? Start with the Quickstart for a three-step walkthrough, or the self-hosting guide if you want to run your own server.

Installation

Requires Rust 1.75 or later.
Or use the Makefile shortcut:

Verify


Quick Start

After connecting, the terminal displays the public URL:

Configuration File

The client reads ~/.rustunnel/config.yml automatically. CLI flags always override file values.

Full example

Field reference


Commands

setup — Interactive config wizard

Create (or overwrite) ~/.rustunnel/config.yml through a guided prompt sequence.
Prompts: Region behavior: Behaviour:
  • Creates ~/.rustunnel/ if the directory doesn’t exist.
  • If a config file already exists it is overwritten — a backup is not kept, so copy the old file first if you want to preserve it.
  • Writes a commented tunnels: block with HTTP and TCP examples so you can see the structure right away.
  • Prints Created: or Updated: with the full path when done.
Example session (auto region):
Example session (self-hosted):
Generated file (managed):
Generated file (self-hosted):
After running setup, uncomment and fill in the tunnels: section then run rustunnel start, or use rustunnel http <port> / rustunnel tcp <port> directly.

http — HTTP tunnel

Expose a local HTTP/HTTPS service through the tunnel server.
Arguments: Options: Examples:

tcp — TCP tunnel

Expose any raw TCP service (database, SSH, game server, etc.).
Arguments: Options: Same as http except --subdomain has no effect for TCP tunnels. --region still works. Examples:
The server assigns a random public port from its configured TCP port range. The public address is displayed in the startup box.

start — Multi-tunnel mode

Start all tunnels defined in a config file simultaneously.
Options: Example:
start always reconnects automatically (equivalent to running each tunnel without --no-reconnect). At least one tunnel must be defined in the config file or the command exits with an error.

Multiple backends (load balancing)

When start is given two or more tunnels with the same (group, group_key), the server treats them as one logical pool — inbound traffic is dispatched to a healthy member at random. This is the path for running a hot-spare backend, scaling out a service horizontally behind a single subdomain, or doing zero-downtime rollouts. Add the load-balancing fields to each pool member’s tunnel definition:
Run a second client (on the same or a different host) with local_port: 3001, the same subdomain, and the same (group, group_key). Both clients register as members of the same pool; public connections to pool.tunnel.example.com are dispatched at random across them.
Load balancing requires [load_balancing] enabled = true in the server’s server.toml. When the flag is false (the default), the client’s group / group_key / health_check fields are accepted but ignored — both clients try to register as solo tunnels and the second one fails with subdomain '...' is already in use.

Quick smoke test

End-to-end validation with two backends sharing one subdomain.
1

Build the client from source

2

Drop a config that opts into a group

3

Start backend A and client A

4

Start backend B and client B

Use a second config file that’s identical except for local_port: 3001.
5

Hammer the public URL

Both backends should see roughly half of the requests.
6

Validate failover

Kill one of the local backends (Ctrl-C on its python3 process). The probe loop on that client marks it unhealthy after max_failed × interval_secs seconds; subsequent requests all land on the survivor. Restart the backend — the probe re-registers it as healthy and dispatch distributes again.
For the full reference (config field meanings, behaviour rules, observability series, limitations) see Load Balancing & Health Checks.

token create — API token management

Create a new API token via the server’s dashboard REST API. Requires admin credentials.
Options: Example:
Output:
Copy the token value — it is shown only once. Add it to your config file as auth_token.

Flags Reference

setup takes no flags — all input is collected interactively.

Region Selection

rustunnel can connect to multiple edge servers in different geographic regions. The region selection logic follows this priority order:
  1. --server <host:port> — explicit server address always wins; region logic is skipped entirely.
  2. --region <id> — connect directly to the named region without probing.
  3. region: auto (config file or --region auto) — probe all regions in parallel and pick the nearest.
  4. No region preference — use server: from config as-is (backward compatible with self-hosted setups).

Available regions (hosted service)

Auto-select output

When region: auto is active, the client probes all regions by TCP connect time and prints:
Unreachable regions time out after 3 seconds and are assigned a 10-second penalty so they never win the selection.

Region list refresh

The region list is cached at ~/.rustunnel/regions.json for 24 hours. On expiry the client fetches a fresh list from GET https://<host>:8443/api/regions; if that fails it falls back to the hardcoded list compiled into the binary.

Reconnection Behavior

By default, rustunnel reconnects automatically when the connection drops. The retry delay follows an exponential backoff schedule: Each delay has ±20% random jitter to prevent thundering-herd reconnects when a server restarts.

Fatal errors (no reconnect)

The following errors cause an immediate exit — retrying would not help:
  • Auth failed — invalid or revoked token. Fix: create a new token at rustunnel.com (Dashboard → API Keys) and update your config.
  • Config error — missing required fields. Fix: check your ~/.rustunnel/config.yml.

Disabling reconnect

Use --no-reconnect for scripting, CI, or when you want manual control:

Terminal Output

Connecting spinner

While establishing the connection a spinner is shown:

Startup box

Once all tunnels are registered, a bordered box appears:
Color coding:
  • Protocol label — bold yellow
  • Tunnel name — dim
  • Public URL — bold green
  • Border — cyan

Graceful shutdown

Press Ctrl-C to cleanly close the tunnel and exit. The control WebSocket is closed before the process exits.

Environment Variables

Examples:
Log output goes to stderr. Normal tunnel output (startup box, reconnect messages) goes to stdout.

Error Reference


Troubleshooting

Tunnel connects but requests don’t arrive

  • Verify your local service is running and listening: curl http://localhost:<port>
  • Check --local-host if forwarding to a non-localhost address

Certificate verification failed

If your server uses a self-signed certificate (common for local/staging environments), use --insecure:
Never use --insecure in production — it disables all TLS certificate checks.

Subdomain already taken

The server returns tunnel error: subdomain already in use. Either:
  • Omit --subdomain to get an auto-assigned subdomain, or
  • Choose a different name: --subdomain myapp-dev

Debugging connection issues

Enable verbose logging to see full protocol traces:
Key log messages to look for:

Multiple tunnels on the same server

Use rustunnel start with a config file to open all tunnels over a single control connection:

Quickstart

Expose your first local port in three steps with the hosted service.

Self-Hosting Guide

Run your own rustunnel server with systemd, TLS, and PostgreSQL.

Load Balancing & Health Checks

Pool multiple backends behind one subdomain with automatic failover.

UDP Tunnels

Forward UDP traffic for game servers, DNS, and other datagram services.