Skip to main content
This guide walks through how to self-host the rustunnel tunnel server in production. rustunnel is open-source under AGPL, so you can run the same server we run on the managed cloud — on any VPS with a public IP and a wildcard DNS record. The example commands use Ubuntu 22.04, systemd, Let’s Encrypt TLS via Certbot, and PostgreSQL, but the same recipe works on any major cloud provider including Hetzner, DigitalOcean, Linode, and AWS Lightsail. For a Docker-based deployment, see the Docker Deployment guide instead.

Requirements

To build

To run


Step 1 — Install dependencies

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

Step 2 — Build release binaries

Binaries will be at:
  • target/release/rustunnel-server
  • target/release/rustunnel

Step 3 — Create system user and directories


Step 4 — Install the server binary

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

Step 5 — Set up PostgreSQL

rustunnel requires PostgreSQL for shared state (tokens, tunnel history, audit log).
Create a dedicated database and user:
For managed PostgreSQL (e.g. AWS RDS, DigitalOcean Managed Databases, Supabase) skip the apt install step and just note down your connection URL for the config in the next step.
Schema migrations run automatically when the server starts — no manual SQL needed.

Step 6 — Create the server config file

Create /etc/rustunnel/server.toml. Generate a strong admin token first:
Secure the file:

Step 7 — TLS certificates (Let’s Encrypt + Cloudflare)

Both the bare domain and the wildcard are required. The wildcard (*.edge.rustunnel.com) is what makes HTTP subdomain tunnels work. Create the Cloudflare credentials file:
Request the certificate:
Certbot writes the PEM files to:
Certbot installs a systemd timer for automatic renewal. rustunnel reads TLS certificates from disk at startup, so it must be restarted after each renewal. Add a deploy hook to do this automatically:
Allow the rustunnel service user to read the certificates:

Step 8 — Set up the systemd service


Step 9 — Open firewall ports

Port 9090 only needs to be open if you have an external Prometheus scraper. If Prometheus runs on the same host it reaches the metrics endpoint over the loopback network.

Step 10 — Verify the server is running

Port 4040 is the control-plane WebSocket — clients connect here. Hitting it with plain HTTP returns HTTP/0.9, which is expected. The dashboard REST API is on dashboard_port (8443 in the config above).

Connecting a client


Updating the server

Pull the latest code, rebuild, install, and restart in one command:
This runs: git pullcargo build --releaseinstallsystemctl restartsystemctl status.

Port reference


Config file reference


Monitoring

A Prometheus metrics endpoint is available at :9090/metrics:
Start the full monitoring stack (Prometheus + Grafana):
The default Grafana password is changeme. Set GRAFANA_PASSWORD before starting the stack in production.

Next steps

Client Guide

Configure the rustunnel CLI to connect to your self-hosted server.

Architecture

Understand the control plane, data plane, and yamux multiplexing under the hood.

Load Balancing & Health Checks

Run multiple backends behind one subdomain with automatic failover.

MCP Server

Let AI agents manage tunnels on your self-hosted server via MCP.