This guide is for sysadmins, MSP technicians and home-lab owners who like the RustDesk client but do not want sessions brokered by the project’s shared public servers. The short answer: put two small services, hbbs and hbbr, on a Linux host with Docker Compose, open TCP 21115–21117 and UDP 21116, copy the public key from id_ed25519.pub, and give every client your server address plus that key. When a setup fails, the cause is usually a closed port or a wrong key.
The open-source RustDesk Server is free under AGPL-3.0. The current release is 1.1.16 (20 July 2026).
Public servers, your own OSS server or Server Pro
| Option | Who runs it | Licence | What you get | What you do not get |
|---|---|---|---|---|
| Public RustDesk servers | The RustDesk project | Free to use with the free client | Zero setup, works out of the box | Control over the broker; shared capacity can be slow at busy times |
| RustDesk Server OSS | You | Free, open source (AGPL-3.0) | Your own ID registration, hole punching and relay; your own key pair | Web console, user accounts, device groups, audit logs |
| RustDesk Server Pro | You | Commercial | Everything in OSS plus a web console, users and groups, LDAP/OIDC sign-in, shared address books, audit logs | A free licence |
This article covers the OSS server. If you are still deciding between RustDesk and other self-hosted tools, start with our self-hosted remote access overview.
How the two services work
hbbs is the ID (rendezvous) server. Every client registers with it, and when you connect to an ID it tries to set up a direct peer-to-peer path by hole punching. hbbr is the relay: it carries the session only when a direct path fails. The official documentation notes that hole punching succeeds in most cases, so the relay often sits idle. That is why hardware needs are tiny (the smallest cloud VM or a Raspberry Pi is enough) and bandwidth matters more than CPU.
| Port | Protocol | Service | Purpose |
|---|---|---|---|
| 21115 | TCP | hbbs | NAT type test |
| 21116 | TCP and UDP | hbbs | ID registration, rendezvous, hole punching |
| 21117 | TCP | hbbr | Relay |
| 21118, 21119 | TCP | hbbs, hbbr | WebSocket, only for the web client |
| 21114 | TCP | Server Pro only | Web console and API |
Step 1: prepare the host and firewall
- Pick a Linux host with a static public IP address, and point a DNS name such as
rd.example.comat it. Clients store the address you give them, so a name avoids reconfiguring every machine if the IP changes. - Prefer a cloud VM over a box behind your office router. A server inside the LAN works from outside but often fails for clients on the same LAN (NAT loopback, see troubleshooting below).
- Open the ports. With ufw:
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
If the VM sits behind a cloud security group, add the same rules there, including UDP 21116.
Step 2: start hbbs and hbbr with Docker Compose
Docker is the method the RustDesk documentation recommends. Create a folder, save this as compose.yml, and start it:
services:
hbbs:
container_name: hbbs
image: rustdesk/rustdesk-server:latest
command: hbbs
volumes:
- ./data:/root
network_mode: "host"
depends_on:
- hbbr
restart: unless-stopped
hbbr:
container_name: hbbr
image: rustdesk/rustdesk-server:latest
command: hbbr
volumes:
- ./data:/root
network_mode: "host"
restart: unless-stopped
sudo docker compose up -d
sudo docker ps
Host networking lets the services see real client IP addresses instead of the Docker bridge address, and it only works on Linux. Both containers must mount the same ./data folder: that is where the key pair and the SQLite database live.
No Docker? The project also publishes .deb packages (rustdesk-server-hbbs and rustdesk-server-hbbr) that register systemd units and keep data in /var/lib/rustdesk-server/. On Windows, the documentation runs the unsigned x64 binaries as services with NSSM or PM2.
Step 3: find and protect the key
On first start hbbs generates an Ed25519 key pair in its working directory: id_ed25519 (private) and id_ed25519.pub (public). Read the public one:
cat ./data/id_ed25519.pub
That short string is the Key your clients need. It is a public encryption key, not a licence key, and it is required for encrypted connections to your server.
- Back up both files. If you lose them and the server generates a new pair, every client must be reconfigured.
- Never publish the private file
id_ed25519. - By default
hbbrdoes not validate keys, a deliberate choice by the developers to avoid mismatch failures. On an internet-facing server you can make the relay require the key by changing its command tohbbr -k _, which loads the same key pair from the shared data folder. Restart both containers afterwards.
Step 4: point clients at your server
- In the RustDesk client click the menu button next to your ID, open Network and unlock the settings (admin rights needed).
- Enter your DNS name in ID Server and paste the public key into Key. Leave Relay Server and API Server empty; the client derives the relay from the ID server.
- Repeat on the other side. Both the controlling and the controlled machine must use the same server and key.
For more than a handful of machines, configure one client, click Export Server Config, and use the resulting string everywhere else, either with Import Server Config or from a deployment script:
rustdesk.exe --config <config-string>
Step 5: test and troubleshoot
Connect between two machines on different networks. If something fails, test from the controlled machine first:
telnet rd.example.com 21116
telnet rd.example.com 21117
| Symptom | Likely cause | Fix |
|---|---|---|
| Connection refused on 21116 or 21117 | Nothing is listening: container stopped or service crashed | Check sudo docker ps and the logs with sudo docker logs hbbs |
| Connection times out | Firewall or security group blocks the port | Open TCP 21115–21117 and UDP 21116 |
| “Failed to connect via rendezvous server” | The controlled side cannot reach hbbs on TCP 21116 | Run the telnet test on that machine; check its ID Server value |
| “Key mismatch” or “invalid public key” | The client has an old or mistyped key | Paste the contents of id_ed25519.pub again on both sides |
| Session hangs on “Connecting” | Relay unreachable, or hbbr uses a different key than hbbs | Confirm hbbr runs on the same server, port 21117 is open and both containers share one data folder |
| Works from outside, fails inside the LAN | NAT loopback (hairpin NAT) on your router | Enable hairpin NAT, or make local DNS resolve the server name to its LAN IP |
One unrelated message shares the same words: on Linux desktops the RustDesk client itself can log an “X11 connection refused” error. The project’s FAQ lists allowing local root access to the display (xhost +local:root) as a workaround. It is not a server problem.
Back up and update
- Back up the
datafolder: the two key files anddb_v2.sqlite3. Test a restore on a spare VM once; our remote access security checklist has a fuller routine. - Update by pulling the new image and recreating the containers. Clients need no changes as long as the address and key stay the same:
sudo docker compose pull
sudo docker compose up -d
Release 1.1.16 closed an unauthenticated UDP hole-punch issue that could be abused for reflection attacks, so do not leave an old server running.
Limitations
- The OSS server has no web interface, user accounts or audit trail. If you need a console with device groups for free, look at MeshCentral.
- Anyone who knows your address and key can register devices on the server. Treat the config string as internal information.
- There is no macOS server build, and the Windows binaries are unsigned.
- Relayed sessions use your bandwidth. Setting
ALWAYS_USE_RELAY=Yon hbbs forces every session through the relay, which increases that load. - The server brokers connections but does not replace a VPN. For access to a whole office network, pair it with WireGuard.
FAQ
Is RustDesk self-hosted server free?
Yes. The OSS server is free and open source under AGPL-3.0, with no device limit. RustDesk Server Pro is a separate commercial product that adds a web console, user management and audit logs.
Which ports does a self-hosted RustDesk server need?
TCP 21115, 21116 and 21117 plus UDP 21116. TCP 21118 and 21119 are only for the web client, and TCP 21114 is only for the Server Pro console.
Where is the RustDesk key located in Docker?
In the folder you mounted into the containers. With the official compose file that is ./data/id_ed25519.pub next to compose.yml. With the .deb packages it is in /var/lib/rustdesk-server/.
Why does RustDesk show “connection refused”?
For a self-hosted server it means the host answered but nothing was listening on that port, usually because hbbs or hbbr is not running. A timeout, by contrast, points at a firewall.
Can I run RustDesk server on Windows?
Yes. An unsigned 64-bit build exists, and the documentation describes running hbbs and hbbr as services with NSSM or PM2. Open the same ports in Windows Firewall.
Do I need a relay server if hole punching works?
Run it anyway. Direct connections succeed most of the time, but when two networks cannot reach each other the session only works through hbbr. Without it those connections hang.
Comparing RustDesk with other no-cost tools? See best free remote desktop software.
Last updated: 1 October 2026 · CtrlRemote editorial team. Licence, version and platform details are checked against each developer's official documentation.