One host, six ports, no phone-home
Run the rendezvous server, the relay, the auth backend and the console yourself, and the client only ever talks to machines you own. If you would rather not, the managed plans run this same stack for you.
# everything server-side, on one host
docker compose up -d
# mongo internal only, never published
# api :21114 the client's API + the console's backend
# hbbs :21116 rendezvous, tcp + udp
# hbbr :21117 relay
# web behind your TLS terminator
# seed the first administrator, then log in to the console
docker compose exec api node dist/scripts/seed-admin.js \
--email you@example.com# DNS — three names, one host is fine to start
rustdesk.example.com A 203.0.113.10 # rendezvous + relay + api
api.example.com A 203.0.113.10 # TLS, proxied to :21114
console.example.com A 203.0.113.10 # TLS, the console
# TLS terminates at your proxy, for the API and the console only.
# Rendezvous and relay are not HTTP and are not proxied.It is smaller than you expect
The rendezvous server brokers introductions; it does not carry sessions. The relay only carries the fallback path, and how much that costs depends entirely on your NAT situation.
Comfortable for a few hundred devices, including MongoDB on the same host.
Direct sessions cost the server nothing. Budget relay bandwidth for the share of peers that cannot punch a hole.
Latency that matters is peer to peer. The rendezvous round trip happens once, at the start.
What to open, and what to keep shut
| Port | Protocol | Purpose | Exposure |
|---|---|---|---|
| 21114 | TCP / HTTP | Auth API. The client derives this as rendezvous port − 2 unless api-server is set. | Public (put TLS in front of it) |
| 21115 | TCP | NAT-type test listener — and, from loopback, the runtime console. | Not for the internet |
| 21116 | TCP + UDP | Rendezvous. UDP registers and keeps alive, TCP carries punch-hole and relay signalling. | Public, both protocols |
| 21117 | TCP | Relay fallback for peers that cannot punch a hole. | Public |
| 21118 | TCP | WebSocket rendezvous; also the client's direct-access port. | Public if you need web clients |
| 21119 | TCP | WebSocket relay. | Public if you need web clients |
Four mistakes that fail silently
Every one of these produces a working-looking deployment with a broken path and no error anywhere. They are worth reading before you start, not after.
Give the relay the address clients dial
Never a container name, and never loopback. A relay reached on a loopback address answers with its runtime console instead of relaying, so you get working direct connections and every relayed session hanging — with nothing in either log.
Do not run it behind a routing mesh that source-NATs
If the rendezvous server sees one internal address for your whole fleet, it hands that address out as the punch-hole target. Hole punching stops working, everything falls back to the relay, and nothing logs an error.
Publish the API on 21114 until your builds are branded
A client that has not been told otherwise does not discover the API — it computes it from the rendezvous host, port minus two, over plain HTTP. Once you ship a branded build with the API baked in, that constraint is gone.
Keep the server key backed up
It is the single most valuable file on the host. Lose it and every client in the fleet has to be re-keyed by hand.
The checklist
Upgrades
Server images are versioned and the client protocol is upstream’s, so a newer server keeps talking to older clients. Upgrade the server first, then roll clients at your own pace.
Backups
Three things: the rendezvous server’s key, the MongoDB volume, and the private half of your configuration signing key. The first cannot be regenerated without re-keying every client; the third cannot be regenerated at all without reissuing every branded build.
Monitoring
The API exposes a health endpoint. The two signals worth alerting on are authorization decisions failing — which means connections are being refused — and any unexpired break-glass capability, which the console banners anyway.
Stand it up in an afternoon
Compose file, environment template and the deployment guide are all in the repository — including the parts that were wrong the first time and got fixed.