rustunnel

io.github.joaoh82由 GitHub 帳號 joaoh82 發布v0.8.9更新於 Nov 5, 2026

Give AI agents public HTTPS/TCP/UDP URLs for any localhost service. Open source, self-hostable.

概覽

AI 產生的概覽

Rustunnel 為本機服務產生公開的 HTTPS、TCP 或 UDP 網址,讓 AI 助理把本機應用程式、資料庫或遊戲伺服器對外開放。

可以做什麼
  • 把本機連接埠以 HTTP、TCP、UDP 或點對點方式開放為公開網址
  • 自動選擇區域或指定區域,並可申請自訂子網域
  • 依設定檔啟動全部通道,或依連接埠啟動一次性通道
  • 輸出機器可讀的 JSON 事件,包含通道就緒、重新連線與錯誤資訊
  • 在自架伺服器上建立與管理 API 權杖
適用情境
當助理需要給瀏覽器、Webhook 或其他人一個可存取的網址,指向本機執行的服務(例如開發伺服器、資料庫或遊戲伺服器),又不想部署時適用。
執行需求
以本機程序執行(提供 macOS、Linux、Windows 的 MCP 安裝包)。需要 rustunnel 驗證權杖:在 rustunnel.com 註冊免費帳號並從儀表板建立權杖,或使用自架伺服器。權杖可透過 RUSTUNNEL_TOKEN 環境變數或設定檔提供。自架服務需要 Linux 伺服器、PostgreSQL、TLS 憑證與萬用字元 DNS。
安裝前請注意
通道會把本機服務發布到公開網際網路,該連接埠上可存取的內容都會對外暴露。驗證權杖只顯示一次且可開通通道,應避免寫入日誌或共用設定。託管服務免費方案有限制,付費方案依流量計費。略過 TLS 驗證的不安全選項絕不可用於正式伺服器。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 rustunnel,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

rustunnel

[CI] [License: AGPLv3] [Rust] [Listed on Skillselion]

[rustunnel logo]

The open-source tunnel that scales with you. Don't pay for idle time. Secure, Rust-fast, and Pay-as-you-go.

Expose local services through a public server over encrypted WebSocket connections with TLS termination, HTTP/TCP proxying, a live dashboard, Prometheus metrics, and audit logging.

You can self-host or use our managed service.

Using an AI agent? rustunnel ships an MCP server: one-click setup for Cursor (then add your API token):

[Add to Cursor]

For Claude Code, Claude Desktop, Windsurf, and others, see the agent integration guide or the agent manual at rustunnel.com/agents.md.


Table of Contents


Hosted service

You can use rustunnel without running your own server. We operate a global fleet of public edge servers that you can connect to immediately.

Available regions

Region IDServerLocationControl planeStatus
eueu.edge.rustunnel.comHelsinki, FI:4040Live
usus.edge.rustunnel.comHillsboro, OR:4040Live
apap.edge.rustunnel.comSingapore:4040Live

The client auto-selects the nearest region by default. Use --region <id> to connect to a specific one. The legacy address edge.rustunnel.com is a CNAME to eu.edge.rustunnel.com and will continue to work for backward compatibility.

Getting an auth token

Sign up for a free account at rustunnel.com. No waiting list, no manual approval.

  1. Create an account at rustunnel.com
  2. Go to Dashboard → API Keys and create a token
  3. Copy the token. It is shown only once

Plans:

PlanPriceTunnelsSubdomainsBandwidthTLS/HTTPS
Hobby (free)$02 concurrentRandom only1 GB/mo✓
Pay-as-you-go$3/mo minimum, credited at $0.10/GBNo capCustom$0.10/GB✓
Self-hostFree (run your own server)UnlimitedCustomUnmetered✓

The Hobby (free) plan is a great way to get started: 2 concurrent tunnels, random subdomains only, and 1 GB/mo. Upgrade to pay-as-you-go from your dashboard whenever you need custom subdomains or more tunnels. Pay-as-you-go has no tunnel cap.

Quick start with the hosted server

Once you have a token, run the setup wizard:

bash
rustunnel setup# Region [auto / eu / us / ap / self-hosted] (default: auto): (press Enter)#   Selecting nearest region… eu 12ms · us 143ms · ap 311ms · → eu (Helsinki, FI) 12ms#   Server set to: eu.edge.rustunnel.com:4040# Auth token: <paste your token>

Then expose a local service:

bash
# HTTP tunnel: auto-selects the nearest regionrustunnel http 3000
# Connect to a specific regionrustunnel http 3000 --region eu
# Custom subdomainrustunnel http 3000 --subdomain myapp
# TCP tunnel: e.g. expose a local databaserustunnel tcp 5432
# UDP tunnel: e.g. expose a game serverrustunnel udp 27015
# P2P tunnel: expose a service to another rustunnel clientrustunnel p2p 27015 --name my-game --secret "shared-secret"
# P2P tunnel: connect to a peer's servicerustunnel p2p 8000 --target my-game --secret "shared-secret"

The client prints the public URL as soon as the tunnel is established:

  Selecting nearest region… eu 12ms · us 143ms · ap 311ms → eu (Helsinki, FI) 12ms✓ tunnel open  https://abc123.eu.edge.rustunnel.com

Architecture overview

[rustunnel architecture]

                        ┌──────────────────────────────────────────┐                        │           rustunnel-server               │                        │                                          │Internet ──── :80 ─────▶│  HTTP edge (301 → HTTPS)                 │Internet ──── :443 ────▶│  HTTPS edge  ──▶ yamux stream ──▶ client │Client ───── :4040 ────▶│  Control-plane WebSocket (TLS)           │Browser ──── :8443 ────▶│  Dashboard UI + REST API                 │Prometheus ─ :9090 ────▶│  Metrics endpoint                        │Internet ── :20000+ ───▶│  TCP tunnel ports (one per TCP tunnel)   │                        └──────────────────────────────────────────┘                                          │ yamux multiplexed streams                                          ▼                              ┌─────────────────────┐                              │   rustunnel client   │                              │  (developer laptop)  │                              └──────────┬──────────┘                                         │ localhost                                         ▼                                ┌────────────────┐                                │  local service  │                                │  e.g. :3000    │                                └────────────────┘

Requirements

To build

RequirementVersionNotes
Rust toolchain1.76+Install via rustup
pkg-configanyNeeded by reqwest (TLS)
libssl-devanyOn Debian/Ubuntu: apt install libssl-dev
Node.js + npm18+Only needed to rebuild the dashboard UI

To run the server in production

RequirementNotes
Linux (Ubuntu 22.04+)systemd service included
TLS certificate + private keyPEM format (Let's Encrypt recommended)
Public IP / DNSWildcard DNS *.tunnel.yourdomain.com → server IP required for HTTP tunnels

Local development setup

Build

bash
# Clone the repositorygit clone https://github.com/joaoh82/rustunnel.gitcd rustunnel
# Compile all workspace crates (debug mode)cargo build --workspace
# Or use the Makefile shortcutmake build

Run tests

The integration test suite spins up a real server on random ports and exercises auth, HTTP tunnels, TCP tunnels, and reconnection logic. It requires a running PostgreSQL instance.

bash
# Start the local PostgreSQL container (once per machine, persists across reboots)make db-start
# Full suite (unit + integration)make test
# With output visibleTEST_DATABASE_URL=postgres://rustunnel:test@localhost:5432/rustunnel_test \  cargo test --workspace -- --nocapture
# Stop PostgreSQL when you no longer need itmake db-stop

make db-start runs deploy/docker-compose.dev-deps.yml which starts a Postgres 16 container on localhost:5432. The make test target injects TEST_DATABASE_URL automatically. If you run cargo test directly, export the variable first:

bash
export TEST_DATABASE_URL=postgres://rustunnel:test@localhost:5432/rustunnel_test

Run the server locally

Generate a self-signed certificate for local testing:

bash
mkdir -p /tmp/rustunnel-dev
openssl req -x509 -newkey rsa:2048 -keyout /tmp/rustunnel-dev/key.pem \  -out /tmp/rustunnel-dev/cert.pem -days 365 -nodes \  -subj "/CN=localhost"

A ready-made local config is checked into the repository at deploy/local/server.toml. It points to the self-signed cert paths above and has auth disabled for convenience. Start the server with it directly:

bash
cargo run -p rustunnel-server -- --config deploy/local/server.toml

Key settings in deploy/local/server.toml:

SettingValue
Domainlocalhost
HTTP edge:8080
HTTPS edge:8443
Control plane:4040
Dashboard:4041
Auth tokendev-secret-change-me
Auth requiredfalse
TLS cert/tmp/rustunnel-dev/cert.pem
TLS key/tmp/rustunnel-dev/key.pem
Database/tmp/rustunnel-dev/rustunnel.db

Run the client locally

With the server running, expose a local service (e.g. something on port 3000):

bash
# HTTP tunnelcargo run -p rustunnel-client -- http 3000 \  --server localhost:4040 \  --token dev-secret-change-me \  --insecure
# TCP tunnelcargo run -p rustunnel-client -- tcp 5432 \  --server localhost:4040 \  --token dev-secret-change-me \  --insecure

--insecure skips TLS certificate verification. Required when using a self-signed certificate locally. Never use this flag against a production server.

The client will print a public URL, for example:

http tunnel  →  http://abc123.localhost:8080tcp  tunnel  →  tcp://localhost:20000

Testing the HTTP tunnel locally

The tunnel URL uses a subdomain (e.g. http://abc123.localhost:8080). Browsers won't resolve *.localhost subdomains by default, so you have two options:

Option A: curl with a Host header (no setup required)

bash
curl -v -H "Host: abc123.localhost" http://localhost:8080/

Option B: wildcard DNS via dnsmasq (enables browser access)

bash
# Install and configure dnsmasq to resolve *.localhost → 127.0.0.1brew install dnsmasqecho "address=/.localhost/127.0.0.1" | sudo tee -a $(brew --prefix)/etc/dnsmasq.confsudo brew services start dnsmasq
# Tell macOS to use dnsmasq for .localhost queriessudo mkdir -p /etc/resolverecho "nameserver 127.0.0.1" | sudo tee /etc/resolver/localhost

Then visit http://abc123.localhost:8080 in the browser (include :8080 since the local config uses port 8080, not port 80).

Git hooks

A pre-push hook is included in .githooks/ that mirrors the CI check step (format check + Clippy). Run this once after cloning to activate it:

bash
make install-hooks

From that point on, every git push will automatically run:

bash
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warnings

If either check fails the push is aborted, keeping the remote branch green.


Production deployment (Ubuntu / systemd)

The steps below match a deployment where:

  • Domain: edge.rustunnel.com
  • Wildcard DNS: *.edge.rustunnel.com → <server IP>
  • TLS certs: Let's Encrypt via Certbot + Cloudflare DNS challenge

1: Install dependencies

bash
apt update && apt install -y \  pkg-config libssl-dev curl git \  certbot python3-certbot-dns-cloudflare

Install Rust (as the build user, not root):

bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shsource "$HOME/.cargo/env"

2: Build release binaries

bash
git clone https://github.com/joaoh82/rustunnel.gitcd rustunnelcargo build --release -p rustunnel-server -p rustunnel-client

Binaries will be at:

  • target/release/rustunnel-server
  • target/release/rustunnel

3: Create system user and directories

bash
useradd --system --no-create-home --shell /usr/sbin/nologin rustunnel
mkdir -p /etc/rustunnel /var/lib/rustunnelchown rustunnel:rustunnel /var/lib/rustunnelchmod 750 /var/lib/rustunnel

4: Install the server binary

bash
install -Dm755 target/release/rustunnel-server /usr/local/bin/rustunnel-server
# Optionally install the client system-wideinstall -Dm755 target/release/rustunnel /usr/local/bin/rustunnel

Or use the Makefile target (runs build + install + systemd setup):

bash
sudo make deploy

5: Set up PostgreSQL

rustunnel requires PostgreSQL for shared state (tokens, tunnel history, audit log).

bash
apt install -y postgresql postgresql-contrib
# Start and enable the servicesystemctl enable --now postgresql

Create a dedicated database and user:

bash
sudo -u postgres psql <<'SQL'CREATE USER rustunnel WITH PASSWORD 'CHANGE_ME';CREATE DATABASE rustunnel OWNER rustunnel;GRANT ALL PRIVILEGES ON DATABASE rustunnel TO rustunnel;SQL

Tip: For managed PostgreSQL (e.g. AWS RDS, DigitalOcean Managed Database, Supabase) skip the apt install step above and just note the connection URL for the config in the next step.

Schema migrations run automatically when the server starts. No manual SQL needed.

6: Create the server config file

Create /etc/rustunnel/server.toml with the content below. Replace your-admin-token-here with a strong random secret (e.g. openssl rand -hex 32).

toml
# /etc/rustunnel/server.toml
[server]# Primary domain: must match your wildcard DNS record.domain       = "edge.rustunnel.com"
# Ports for incoming tunnel traffic (requires CAP_NET_BIND_SERVICE or root).http_port    = 80https_port   = 443
# Control-plane WebSocket port: clients connect here.control_port = 4040
# Dashboard UI and REST API port.dashboard_port = 8443
# Allowed CORS origin for the dashboard UI.# Set to the URL where you serve the dashboard-ui (e.g. http://localhost:3000 for local dev).dashboard_origin = "http://localhost:3000"
# ── TLS ─────────────────────────────────────────────────────────────────────[tls]# Paths written by Certbot (see step 6).cert_path = "/etc/letsencrypt/live/edge.rustunnel.com/fullchain.pem"key_path  = "/etc/letsencrypt/live/edge.rustunnel.com/privkey.pem"
# Set acme_enabled = true only if you want rustunnel to manage certs itself# via the ACME protocol (requires Cloudflare credentials below).# When using Certbot (recommended), leave this false.acme_enabled = false
# ── Auth ─────────────────────────────────────────────────────────────────────[auth]# Strong random secret: used both as the admin token and for client auth.# Generate: openssl rand -hex 32admin_token  = "your-admin-token-here"require_auth = true# Failed auth attempts per source IP per minute before rejection (0 = off).max_failed_auth_per_minute = 10
# ── Database ─────────────────────────────────────────────────────────────────[database]# PostgreSQL connection URL: the database and user must exist before starting# the server (see the PostgreSQL setup step above).  Schema migrations run# automatically on first start.url = "postgresql://rustunnel:CHANGE_ME@localhost:5432/rustunnel"
# Per-region SQLite file for captured HTTP request bodies.# The directory must be writable by the rustunnel user.captured_path = "/var/lib/rustunnel/captured.db"
# ── Logging ──────────────────────────────────────────────────────────────────[logging]level  = "info"format = "json"
# Optional: write an append-only audit log (JSON-lines) for auth attempts,# tunnel registrations, token creation/deletion, and admin actions.# Omit or comment out to disable.audit_log_path = "/var/lib/rustunnel/audit.log"
# ── Limits ───────────────────────────────────────────────────────────────────[limits]# Maximum tunnels a single authenticated session may register.max_tunnels_per_session = 10
# Maximum simultaneous proxied connections per tunnel (semaphore).max_connections_per_tunnel = 100
# Per-tunnel request rate limit (requests/second).rate_limit_rps = 100
# Per-source-IP rate limit (requests/second). Set to 0 to disable.ip_rate_limit_rps = 100
# Maximum size of a proxied HTTP request body (bytes). Default: 10 MB.request_body_max_bytes = 10485760
# Inclusive port range reserved for TCP tunnels.# Each active TCP tunnel consumes one port from this range.tcp_port_range = [20000, 20099]
# Inclusive port range reserved for UDP tunnels.# Each active UDP tunnel consumes one port from this range.# Must not overlap with tcp_port_range. Set to [0, 0] to disable UDP tunnels.udp_port_range = [20100, 20199]

Secure the file:

bash
chown root:rustunnel /etc/rustunnel/server.tomlchmod 640 /etc/rustunnel/server.toml

7: TLS certificates (Let's Encrypt + Cloudflare)

Create the Cloudflare credentials file:

bash
cat > /etc/letsencrypt/cloudflare.ini <<'EOF'# Cloudflare API token with DNS:Edit permission for the zone.dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKENEOF
chmod 600 /etc/letsencrypt/cloudflare.ini

Request a certificate covering the bare domain and the wildcard (required for HTTP subdomain tunnels):

bash
certbot certonly \  --dns-cloudflare \  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \  -d "edge.rustunnel.com" \  -d "*.edge.rustunnel.com" \  --agree-tos \  --email [email protected]

Certbot writes the certificate to:

/etc/letsencrypt/live/edge.rustunnel.com/fullchain.pem/etc/letsencrypt/live/edge.rustunnel.com/privkey.pem

These paths are already set in the config above. Certbot sets up automatic renewal via a systemd timer.

rustunnel reads TLS certificates from disk at startup, so it must be restarted after each renewal. Add a Certbot deploy hook to do this automatically:

bash
cat > /etc/letsencrypt/renewal-hooks/deploy/restart-rustunnel.sh <<'EOF'#!/bin/shsystemctl restart rustunnel.serviceEOFchmod +x /etc/letsencrypt/renewal-hooks/deploy/restart-rustunnel.sh

Allow the rustunnel service user to read the certificates:

bash
# Grant read access to the live/ and archive/ directorieschmod 755 /etc/letsencrypt/{live,archive}chmod 640 /etc/letsencrypt/live/edge.rustunnel.com/*.pemchgrp rustunnel /etc/letsencrypt/live/edge.rustunnel.com/*.pemchgrp rustunnel /etc/letsencrypt/archive/edge.rustunnel.com/*.pemchmod 640 /etc/letsencrypt/archive/edge.rustunnel.com/*.pem

8: Set up systemd service

bash
# Copy the unit file from the repositoryinstall -Dm644 deploy/rustunnel.service /etc/systemd/system/rustunnel.service
systemctl daemon-reloadsystemctl enable --now rustunnel.service
# Check it startedsystemctl status rustunnel.servicejournalctl -u rustunnel.service -f

9: Open firewall ports

bash
ufw allow 80/tcp   comment "rustunnel HTTP edge"ufw allow 443/tcp  comment "rustunnel HTTPS edge"ufw allow 4040/tcp comment "rustunnel control plane"ufw allow 8443/tcp comment "rustunnel dashboard"ufw allow 9090/tcp comment "rustunnel Prometheus metrics"
# TCP tunnel port range (must match tcp_port_range in server.toml)ufw allow 20000:20099/tcp comment "rustunnel TCP tunnels"
# UDP tunnel port range (must match udp_port_range in server.toml)ufw allow 20100:20199/udp comment "rustunnel UDP tunnels"

10: Verify the server is running

bash
# Health check: use dashboard_port from server.toml (default 8443 in production)curl http://localhost:8443/api/status
# Confirm which ports the process is actually bound toss -tlnp | grep rustunnel-serve
# Startup banner is visible in the logsjournalctl -u rustunnel.service --no-pager | tail -30
# Prometheus metricscurl -s http://localhost:9090/metrics

Port reminder: port 4040 is the control-plane WebSocket (clients connect here), not the dashboard. Hitting it with plain HTTP returns HTTP/0.9 which is expected. The dashboard is on dashboard_port. Check your server.toml if unsure.

Updating the server

Pull the latest code, rebuild, install, and restart in one command:

bash
cd ~/rustunnel && sudo make update-server

This runs git pull → cargo build --release → install → systemctl restart → systemctl status.


Docker deployment

A full Docker guide covering both local development (self-signed cert) and production VPS (Let's Encrypt) is available in docs/docker-deployment.md.

Pull the published image

Multi-arch images (linux/amd64 + linux/arm64) are published to GitHub Container Registry on every stable release. No build required:

bash
# Latest stable, or pin a version (e.g. :0.8.1)docker pull ghcr.io/joaoh82/rustunnel-server:latest
# Run it with your server config mounted at /etc/rustunnel/server.tomldocker run --rm \  -p 80:80 -p 443:443 -p 4040:4040 -p 8443:8443 \  -v "$PWD/deploy/server.toml:/etc/rustunnel/server.toml:ro" \  ghcr.io/joaoh82/rustunnel-server:latest

Quick reference (build from source)

bash
# Build the image locally (includes Next.js dashboard + Rust server)make docker-build
# Build and push a multi-arch image to GHCR (maintainers; needs buildx + ghcr login)make docker-push
# Local development (self-signed cert, no auth required)docker compose -f deploy/docker-compose.local.yml up
# Production VPS (requires deploy/server.toml to be configured first)make docker-run
# Production + Prometheus + Grafana monitoring stackmake docker-run-monitoring
# Tail server logsmake docker-logs
# Stop everythingmake docker-stop

Files

FilePurpose
deploy/DockerfileMulti-stage build: Node.js UI → Rust server → slim runtime
deploy/docker-compose.ymlProduction compose file
deploy/docker-compose.local.ymlLocal development compose file
deploy/server.tomlProduction server config template
deploy/server.local.tomlLocal development server config
deploy/prometheus.ymlPrometheus scrape config

Client configuration

Installation

Option 1: Homebrew (macOS and Linux, recommended)

bash
brew tap joaoh82/rustunnelbrew install rustunnel

Homebrew installs pre-built binaries. No Rust toolchain required. The formula is updated automatically on every release. This installs both rustunnel (the CLI client) and rustunnel-mcp (the MCP server for AI agent integration).

Option 2: Pre-built binary

Download the archive for your platform from the latest GitHub Release, extract it, and move the rustunnel binary to a directory on your $PATH:

bash
# Example for macOS Apple Siliconcurl -L https://github.com/joaoh82/rustunnel/releases/latest/download/rustunnel-<version>-aarch64-apple-darwin.tar.gz \  | tar xzsudo install -Dm755 rustunnel /usr/local/bin/rustunnel

Available targets:

PlatformArchive
macOS Apple Siliconrustunnel-<version>-aarch64-apple-darwin.tar.gz
macOS Intelrustunnel-<version>-x86_64-apple-darwin.tar.gz
Linux x86_64 (glibc)rustunnel-<version>-x86_64-unknown-linux-gnu.tar.gz
Linux x86_64 (musl, static)rustunnel-<version>-x86_64-unknown-linux-musl.tar.gz
Linux arm64rustunnel-<version>-aarch64-unknown-linux-gnu.tar.gz
Windows x86_64rustunnel-<version>-x86_64-pc-windows-msvc.zip

Option 3: Build from source

Requires Rust 1.76+.

bash
git clone https://github.com/joaoh82/rustunnel.gitcd rustunnelcargo build --release -p rustunnel-clientsudo install -Dm755 target/release/rustunnel /usr/local/bin/rustunnel
# Or via makemake deploy-client

Setup wizard

The easiest way to create your config file is the interactive setup wizard:

bash
rustunnel setup

It prompts for your region and auth token, then writes ~/.rustunnel/config.yml with the correct server address and a commented tunnels: example section.

rustunnel setup: create ~/.rustunnel/config.yml
Region [auto / eu / us / ap / self-hosted] (default: auto):  Selecting nearest region… eu 12ms · us 143ms · ap 311ms · → eu (Helsinki, FI) 12ms  Server set to: eu.edge.rustunnel.com:4040
Auth token (leave blank to skip): rt_live_abc123...
Created: /Users/you/.rustunnel/config.ymlRun `rustunnel start` to connect using this config.

Pick a specific region (eu, us, ap) to connect directly, or auto (the default) to let the client probe all regions and pick the nearest. Choose self-hosted if you run your own server. The wizard will then prompt for your server address.

After running setup, use rustunnel start to connect with all tunnels defined in the config, or use rustunnel http <port> / rustunnel tcp <port> for one-off tunnels.

Quick start (CLI flags)

bash
# Expose a local HTTP service on port 3000 (auto-selects nearest region)rustunnel http 3000 \  --token YOUR_AUTH_TOKEN
# Connect to a specific regionrustunnel http 3000 --region eu --token YOUR_AUTH_TOKEN
# Use an explicit server address (bypasses region selection)rustunnel http 3000 \  --server edge.rustunnel.com:4040 \  --token YOUR_AUTH_TOKEN
# Expose a local service with a custom subdomainrustunnel http 3000 \  --token YOUR_AUTH_TOKEN \  --subdomain myapp
# Expose a local TCP service (e.g. a PostgreSQL database)rustunnel tcp 5432 \  --token YOUR_AUTH_TOKEN
# Disable automatic reconnectionrustunnel http 3000 --no-reconnect

Machine-readable output (--json)

All tunnel-running commands (http, tcp, udp, p2p, start) and token create accept a --json flag. With it, stdout emits NDJSON, one JSON event object per line, instead of the human-readable startup box, which makes the CLI easy to drive from scripts and AI agents:

bash
rustunnel http 3000 --json --token YOUR_AUTH_TOKEN
json
{"event":"tunnel_ready","protocol":"http","public_url":"https://myapp.eu.edge.rustunnel.com","local_port":3000,"local_host":"localhost","tunnel_id":"6f9a…","name":"myapp"}

Events:

EventWhenFields
tunnel_readyTunnel registered and accepting trafficprotocol, public_url, public_addr (host:port, tcp/udp only), local_port, local_host, tunnel_id, name
reconnectingConnection dropped, retry scheduledattempt, reason, delay_secs
reconnectedReconnect succeeded (fresh tunnel_ready events follow)None
errorFatal error; process exits with code 1code (config/auth/tunnel/connection/protocol/io), message, hint
token_createdtoken create --json succeededtoken, name, id

Diagnostics still go to stderr, so stdout stays valid NDJSON. For the http, tcp, udp, and p2p commands the auth token can also be supplied via the RUSTUNNEL_TOKEN environment variable instead of --token (start reads tokens from the config file).

Config file

Default location: ~/.rustunnel/config.yml

yaml
# ~/.rustunnel/config.yml
# Tunnel server address (host:control_port)server: edge.rustunnel.com:4040
# Auth token (from server admin_token or a token created via the dashboard)auth_token: YOUR_AUTH_TOKEN
# Region preference: auto (probe & pick nearest), or eu / us / ap.# Omit for self-hosted / single-server setups.region: auto
# Named tunnels started with `rustunnel start`tunnels:  web:    proto: http    local_port: 3000    subdomain: myapp      # optional: server assigns one if omitted
  db:    proto: tcp    local_port: 5432

Start all tunnels from the config file:

bash
rustunnel start# or with an explicit pathrustunnel start --config /path/to/config.yml

Token management

Hosted service: manage tokens from the rustunnel.com dashboard under Dashboard → API Keys. You can create, label, and revoke tokens without any CLI commands.

Self-hosted: create additional tokens via the dashboard API:

bash
rustunnel token create \  --name "ci-deploy" \  --server your-server:8443 \  --admin-token YOUR_ADMIN_TOKEN

Or via curl:

bash
curl -s -X POST https://your-server:8443/api/tokens \  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \  -H "Content-Type: application/json" \  -d '{"label": "ci-deploy"}'

Port reference

PortProtocolPurpose
80TCPHTTP edge: redirects to HTTPS; also ACME HTTP-01 challenge
443TCPHTTPS edge: TLS-terminated tunnel ingress
4040TCPControl-plane WebSocket: clients connect here
8443TCPDashboard UI and REST API
9090TCPPrometheus metrics (/metrics)
20000–20099TCPTCP tunnel range (configurable via tcp_port_range)
20100–20199UDPUDP tunnel range (configurable via udp_port_range)

Config file reference (server)

KeyTypeDefaultDescription
server.domainstringNoneBase domain for tunnel URLs
server.http_portu16NoneHTTP edge port
server.https_portu16NoneHTTPS edge port
server.control_portu16NoneWebSocket control-plane port
server.dashboard_portu164040Dashboard port
tls.cert_pathstringNonePath to TLS certificate (PEM)
tls.key_pathstringNonePath to TLS private key (PEM)
tls.acme_enabledboolfalseEnable built-in ACME renewal
tls.acme_emailstring""Contact email for ACME
tls.acme_stagingboolfalseUse Let's Encrypt staging CA
tls.acme_account_dirstring/var/lib/rustunnelACME state directory
tls.cloudflare_api_tokenstring""Cloudflare DNS API token (prefer env var CLOUDFLARE_API_TOKEN)
tls.cloudflare_zone_idstring""Cloudflare Zone ID (prefer env var CLOUDFLARE_ZONE_ID)
auth.admin_tokenstringNoneMaster auth token
auth.require_authboolNoneReject unauthenticated clients
auth.max_failed_auth_per_minuteint10Failed auth attempts allowed per source IP per minute before further attempts are rejected (control-plane handshake and dashboard API); 0 disables
database.urlstringNonePostgreSQL connection URL (required)
database.captured_pathstring/var/lib/rustunnel/captured.dbPer-region SQLite file for captured HTTP request bodies
server.dashboard_originstring""Allowed CORS origin for the dashboard UI (e.g. http://localhost:3000)
logging.levelstringNonetrace / debug / info / warn / error
logging.formatstringNonejson or pretty
logging.audit_log_pathstringnullPath for audit log (JSON-lines); omit to disable
limits.max_tunnels_per_sessionusizeNoneMax tunnels per connected client
limits.max_connections_per_tunnelusizeNoneMax concurrent connections per tunnel
limits.rate_limit_rpsu32NonePer-tunnel request rate cap (req/s)
limits.ip_rate_limit_rpsu32100Per-source-IP rate cap (req/s); 0 = disabled
limits.request_body_max_bytesusizeNoneMax proxied request body size (bytes)
limits.tcp_port_range[u16, u16]NoneInclusive [low, high] TCP tunnel port range
limits.udp_port_range[u16, u16][0, 0]Inclusive [low, high] UDP tunnel port range; [0, 0] disables UDP tunnels
region.idstring"default"Region identifier recorded in tunnel history (e.g. "eu", "us", "ap")
region.namestring"Default"Human-readable region name shown in the dashboard
region.locationstring""Physical location label (e.g. "Helsinki, FI")

Monitoring

A Prometheus metrics endpoint is available at :9090/metrics:

rustunnel_active_sessions      # gauge: connected clientsrustunnel_active_tunnels_http  # gauge: active HTTP tunnelsrustunnel_active_tunnels_tcp   # gauge: active TCP tunnels

Start with the full monitoring stack (Prometheus + Grafana):

bash
make docker-run-monitoring# Grafana:    http://localhost:3000  (admin / changeme)# Prometheus: http://localhost:9090

Production note: The default Grafana password is changeme. Set the GRAFANA_PASSWORD environment variable before starting the stack in production:

bash
export GRAFANA_PASSWORD=your-strong-passwordmake docker-run-monitoring

REST API

The dashboard port exposes a REST API for programmatic access to tunnels, tokens, captured requests, and tunnel history. All endpoints (except the health check) require an Authorization: Bearer <token> header.

/api/tunnels, /api/groups, and their per-tunnel sub-resources are scoped by caller: the admin token sees everything; a user-scoped API token sees only its own tunnels and groups; tunnels the caller can't see return 404, never 403. See docs/api-reference.md § Visibility scope for the full rules.

Quick reference

MethodPathDescription
GET/api/statusHealth check (no auth)
GET/api/tunnelsList active tunnels
GET/api/tunnels/:idGet a single tunnel
DELETE/api/tunnels/:idForce-close a tunnel
GET/api/tunnels/:id/requestsCaptured HTTP requests
POST/api/tunnels/:id/replay/:req_idFetch stored request for replay
GET/api/tokensList API tokens
POST/api/tokensCreate an API token
DELETE/api/tokens/:idDelete an API token
GET/api/historyPaginated tunnel history

Full request/response schemas, query parameters, and examples are in docs/api-reference.md.

A machine-readable OpenAPI 3.0 spec is served at GET /api/openapi.json (no auth required).


AI agent integration (MCP server)

rustunnel ships a rustunnel-mcp binary that implements the Model Context Protocol over stdio, letting AI agents (Claude, GPT-4o, custom agents) open and manage tunnels without any manual intervention.

Works with any MCP harness. For copy-paste config for Claude Code, Claude Desktop, Codex, Cursor, Windsurf, Cline, and custom agents, plus a one-command installer, see the Agent Integration Guide:

bash
./integrations/install.sh        # prompts for your token, writes the config

Quick setup (Claude Desktop, hosted server)

json
{  "mcpServers": {    "rustunnel": {      "command": "rustunnel-mcp",      "args": [        "--server", "edge.rustunnel.com:4040",        "--api",    "https://edge.rustunnel.com:8443"      ],      "env": { "RUSTUNNEL_TOKEN": "<your-token>" }    }  }}

Set RUSTUNNEL_TOKEN once and the agent never has to pass a token on a tool call.

Available tools

ToolDescription
create_tunnelOpen a tunnel and return the public URL: HTTP/TCP/UDP, P2P, and load-balanced pools with health checks
list_tunnelsList all active tunnels
close_tunnelForce-close a tunnel by ID
list_regionsList available server regions
get_connection_infoReturn the CLI command for cloud/sandbox agents
get_tunnel_historyRetrieve past tunnel activity

Installation

Homebrew (macOS and Linux): installs rustunnel-mcp alongside the CLI:

bash
brew tap joaoh82/rustunnelbrew install rustunnel

Build from source:

bash
make release-mcpsudo install -m755 target/release/rustunnel-mcp /usr/local/bin/rustunnel-mcp

Full setup guide, configuration options, and workflow examples are in docs/mcp-server.md.

Claude Code plugin

The easiest way to use rustunnel with Claude Code. Install the plugin and it handles all MCP configuration automatically. Just enter your token once and start asking Claude to expose ports.

/plugin install rustunnel

The plugin prompts for your server address and API token at enable time, stores them securely, and starts the MCP server in the background. No .mcp.json editing or manual setup needed.

Plugin directory: plugins/claude-code/ Documentation: docs/claude-plugin.md

OpenClaw skill

rustunnel ships an OpenClaw skill that gives any OpenClaw-compatible AI agent first-class knowledge of rustunnel: config file format, authentication, tool signatures, and common workflows, without you having to explain it.

Skill file: skills/rustunnel/SKILL.md

What it covers:

TopicDetails
Config fileLocation (~/.rustunnel/config.yml), format, named tunnels
First-time setuprustunnel setup wizard or manual config creation
MCP toolscreate_tunnel, list_tunnels, close_tunnel, get_connection_info, get_tunnel_history
WorkflowsWebhook testing, demo sharing, cloud sandbox (no subprocess), named tunnels
SecurityToken handling, file permissions, HTTPS-only transport

To load the skill in Claude Code:

bash
/skills load skills/rustunnel/SKILL.md

Once loaded, you can ask the agent things like:

"Expose my local port 3000 as an HTTPS tunnel using rustunnel."

"List my active tunnels and close the one forwarding port 5432."

"Set up my rustunnel config file with my token."

The skill instructs the agent to read credentials from ~/.rustunnel/config.yml automatically, so you won't be prompted for your token on every invocation.


Roadmap

A detailed list of shipped features and planned future work is maintained in docs/ROADMAP.md.


Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository and create a feature branch from main.
  2. Run make install-hooks once after cloning to activate the pre-push quality gate.
  3. Make your changes. Ensure make check (fmt + Clippy) and make test pass locally.
  4. Open a Pull Request with a clear description of what changed and why.
  5. A maintainer will review and merge once CI is green.

Guidelines

  • Keep PRs focused: one logical change per PR.
  • Add or update tests for any new behaviour.
  • Follow the existing code style; cargo fmt is enforced by CI.
  • For larger changes or new features, open an issue first to discuss the approach.

License

This project is licensed under the GNU AGPLv3 License. See the LICENSE file for details.


Contact

João Henrique Machado Silva

來源:README.md,提交 bdf559c

工具

0
SourceWeft 曾在隔離沙箱中以無憑證方式啟動該軟體包一次,以列出其工具,但未能完成:該軟體包類型無法在沙箱中執行。

版本歷史

4
  1. v0.8.9最新Nov 5, 2026
  2. v0.8.8Nov 3, 2026
  3. v0.8.6Nov 3, 2026
  4. v0.8.5Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分