Skip to content

Server Quick Start

Get a server running in under 10 minutes.


  • A machine with a public IP address (Linux, macOS, or FreeBSD)
  • Port 443 open in your firewall/security group
  • Root or sudo access

The universal installer handles everything:

Terminal window
curl -fsSL https://assets.rvpn.org/install.sh | sudo bash -s -- --setup --server

It will auto-detect your platform, download the correct binary, verify the checksum, and walk you through server configuration (keys, TLS, TUN mode, etc.).

Or manually:

Terminal window
# Linux x86_64 (most VPS)
curl -LO https://assets.rvpn.org/1.3.1/rvpn-server-x86_64-linux-gnu
chmod +x rvpn-server-x86_64-linux-gnu
sudo mv rvpn-server-x86_64-linux-gnu /usr/local/bin/rvpn-server
# Linux ARM64
curl -LO https://assets.rvpn.org/1.3.1/rvpn-server-aarch64-linux-gnu
chmod +x rvpn-server-aarch64-linux-gnu
sudo mv rvpn-server-aarch64-linux-gnu /usr/local/bin/rvpn-server
# FreeBSD
fetch https://assets.rvpn.org/1.3.1/rvpn-server-x86_64-freebsd
chmod +x rvpn-server-x86_64-freebsd
sudo mv rvpn-server-x86_64-freebsd /usr/local/bin/rvpn-server

See Server Installation for all available binaries and checksum verification.

Verify it works:

Terminal window
rvpn-server --help

Both commands write to the paths configured in server.toml. Point them at /etc/rvpn/ by creating a minimal config first, then run:

Terminal window
sudo mkdir -p /etc/rvpn
sudo tee /etc/rvpn/server.toml <<'EOF' >/dev/null
[server]
identity_key_file = "/etc/rvpn/server_identity.key"
prekey_bundle_file = "/etc/rvpn/prekey-bundle.json"
EOF
sudo rvpn-server -c /etc/rvpn/server.toml keygen
sudo rvpn-server -c /etc/rvpn/server.toml prekey-bundle

This creates three files under /etc/rvpn/:

FilePurpose
server_identity.keyServer’s long-term Ed25519 identity key — keep private
prekey-bundle.jsonPublic prekey bundle — distribute to clients
prekey-bundle.private.jsonPrivate prekey material — keep private

Without the -c flag both commands write to the current working directory (server_identity.key / prekey-bundle.json), which is fine for testing but easy to lose track of.

Important: Keep server_identity.key and prekey-bundle.private.json secure. Back them up. If lost, clients will need a new prekey bundle.


rvpn-server can obtain and renew a Let’s Encrypt certificate itself using the TLS-ALPN-01 challenge. Same :443 listener, no :80 port, no certbot, no external timer — the state machine lives inside the server process.

Append this to /etc/rvpn/server.toml:

[server.acme]
enabled = true
domains = ["your-domain.com"]
contacts = ["mailto:[email protected]"]
cache_dir = "/var/lib/rvpn/acme"

Then create the cache directory (it needs to survive restarts so you don’t burn Let’s Encrypt rate limits on every reboot):

Terminal window
sudo mkdir -p /var/lib/rvpn/acme
sudo chmod 700 /var/lib/rvpn/acme

Prerequisites — check before you enable this:

  1. your-domain.com must resolve (A/AAAA) to this server’s public IP.
  2. Inbound TCP :443 must be reachable from Let’s Encrypt’s validators.
  3. Nothing else may be bound to :443 (the challenge shares the listener).

First time? Set staging = true in [server.acme] on the first run to test the whole chain against Let’s Encrypt’s rate-limit-free staging environment. If the logs show ACME event: CertCacheStore, flip to staging = false and use a fresh cache_dir for production. See reference → [server.acme] for the full workflow, the three LE rate limits that matter, and the renewal cadence.

Prefer to bring your own cert — e.g. from an existing certbot workflow or a reverse proxy — instead? Skip this section and set tls_cert_file / tls_key_file in [server] as documented in reference → server-config. ACME and static certs are mutually exclusive; the server refuses to start if both are set.


rVPN needs IP forwarding to route traffic on behalf of clients:

Terminal window
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Terminal window
sudo rvpn-server -c /etc/rvpn/server.toml

You should see output like:

INFO Starting rVPN Server on 0.0.0.0:443
INFO Server listening on wss://0.0.0.0:443
INFO WebSocket endpoint: /api/v1/ws
INFO WebSocket endpoint (desktop SOCKS): /api/v1/ws
INFO WebSocket endpoint (mobile TUN): /api/v1/ws/tun
INFO WebSocket endpoint (DNS proxy): /api/v1/ws/dns
INFO WebSocket endpoint (SOCKS5 mux): /api/v1/ws/mux

Once confirmed working, set it up as a systemd service to run on boot.


Clients need prekey-bundle.json to connect. Send it to your users securely (encrypted email, secure messenger, etc.) — this file is public and does not need to be kept secret, but it must be the real file from your server.