How to self-host RustDesk with Docker for China remote support
On July 13, 2026, the Sunlogin client quoted us ¥188 per month for cross-border remote control from Japan into mainland China. That ¥188 figure was an in-client, point-in-time quote. Sunlogin’s public pricing page did not list it when we checked, so it should not be read as a universal public price.
We needed occasional support sessions, not a subscription. We therefore self-hosted RustDesk Server OSS on an existing Riven Cloud Tokyo VPS while keeping the familiar remote-support workflow for the person receiving help.
Why self-host RustDesk?
Self-hosting gives the operator control of the server identity and relay path. RustDesk generates an Ed25519 key pair when hbbs first starts. The public key identifies and authenticates the self-hosted server to clients configured with that key. It is not a password, secret, or access-control list. Give clients only the public key and never expose the private id_ed25519 file.
RustDesk sessions are end-to-end encrypted. A relay carries encrypted session traffic rather than an unencrypted desktop stream. With self-hosting, even that encrypted relay traffic stays on infrastructure we control instead of passing through a third-party relay.
RustDesk Server OSS also has no membership tiers, device-count limits, or per-feature paywalls. It provides the core ID and relay services without the web console, account management, and other administrative features offered by RustDesk Server Pro.
Relay placement is another practical benefit. We can choose the location and carrier path instead of accepting whichever relay the vendor assigns. This matters when a direct peer-to-peer connection cannot be established and the desktop session must cross the relay in both directions.
SSH, WireGuard, and Tailscale are excellent tools for machines and users we administer. They were wrong for this case because the remote party was a non-technical third party. The workflow needed to remain: install the client, share the ID, and approve the session. Requiring a tunnel would have created a second support job before we could address the first one.
How do you install RustDesk Server OSS with Docker?
The official RustDesk Server OSS installation guide recommends Docker for most deployments. The method below follows that guide and the current Docker documentation for a portable Compose deployment.
Check the prerequisites
Use a Linux VPS with a public IPv4 address. Dual-stack IPv4 and IPv6 is preferred when both client networks support it. You also need sudo or root access and enough firewall control to expose the RustDesk ports.
A DNS hostname is optional but recommended. The examples use rustdesk.example.com; replace it with your own hostname. A public IP address also works, but a hostname is easier to move to another server later.
Install Docker and start the services
Create a working directory so that the Compose file and persistent server data stay together:
mkdir -p ~/rustdesk-server
cd ~/rustdesk-server
Install Docker with the convenience installer used by the official documentation. Operators who already have a working Docker Engine and Compose plugin can skip this command:
bash <(wget -qO- https://get.docker.com)
Download the official Compose file, then start both services:
wget https://rustdesk.com/oss.yml -O compose.yml
sudo docker compose up -d
At the time of writing, the live oss.yml starts hbbs and hbbr from rustdesk/rustdesk-server:latest. Both containers mount ./data:/root, use host networking, and restart with the unless-stopped policy.
| Service | Role |
|---|---|
hbbs | ID registration, rendezvous, signaling, and NAT traversal |
hbbr | Encrypted session relay when direct hole punching fails |
Host networking means the processes listen directly on the VPS network stack. Check that both containers are running and inspect the hbbs startup output:
sudo docker compose ps
sudo docker compose logs --tail=100 hbbs
Open the firewall
The official guide gives this simple UFW example:
sudo ufw allow 21114:21119/tcp
sudo ufw allow 21116/udp
The range is broader than the minimum RustDesk Server OSS set. Port 21114/tcp serves the Pro web console and is not required by OSS. Port 21115/tcp is used for the NAT type test. Port 21116/tcp handles connections and TCP hole punching, while 21116/udp handles ID registration and heartbeat traffic. Port 21117/tcp carries relay sessions. Ports 21118/tcp and 21119/tcp support web clients and are optional when web-client access is unused.
Port 21116 must be allowed over both TCP and UDP. A tighter OSS policy can omit 21114/tcp and, when appropriate, the two web-client ports. Mirror the chosen rules in any cloud firewall or security group outside the VPS. If the service is reachable over IPv6, verify that UFW created matching IPv6 rules rather than checking only the IPv4 table.
Retrieve the public key safely
The downloaded Compose file mounts the host’s ./data directory at /root inside both containers. After the first start, the host-side public key is therefore normally ./data/id_ed25519.pub.
File layout can vary with the server version or deployment method. Find public-key files in the persistent directory if the expected path is absent:
sudo find ./data -maxdepth 2 -name '*.pub' -type f -print
Read the expected public key with:
sudo cat ./data/id_ed25519.pub
The hbbs log can also show the generated key and help diagnose a different data layout:
sudo docker compose logs hbbs
Copy only the content of id_ed25519.pub into client configuration. Never share, publish, or paste id_ed25519, which is the server’s private key. Back up the persistent data directory securely because replacing the private key changes the server identity expected by configured clients.
Configure the clients
On each RustDesk client, open Settings > Network and set:
- ID Server:
rustdesk.example.comor your public IP address - Key: the content of
id_ed25519.pub - Relay Server: leave blank
- API Server: leave blank
Both ends of the session need the self-hosted ID server and public key. hbbs advertises the associated hbbr relay automatically, so a separate relay value is unnecessary. The API field is for Pro features and remains blank for this OSS setup.
Verify a real client-to-client session
Test between two clients on different networks rather than stopping after the containers report healthy. Confirm that both clients receive IDs through the new server, connect, and can exchange screen updates, keyboard and mouse input, and clipboard content.
In our actual test, Linux and Windows clients completed a real relayed session. Screen, keyboard and mouse input, and clipboard all worked. Direct hole punching failed for that test, so hbbr relayed the session. One successful session is an operational check, not a controlled network benchmark, and we are not using it to claim a latency figure.
The official installation guide says CPU and memory requirements are minimal. It estimates roughly 30 KB/s to 3 MB/s for a relayed 1920×1080 session, depending on resolution and screen activity, with office work around 100 KB/s. These are broad upstream estimates, not capacity or performance guarantees. Size transfer allowance and monitoring for your own concurrency and usage pattern.
Why use a Tokyo VPS for support into mainland China?
A RustDesk relay is more of a network workload than a compute workload. Once the small CPU and memory requirement is met, adding vCPU does not repair a poor return path. Relay placement matters because a failed direct connection sends the interactive session through hbbr.
This is Riven Cloud’s own blog, and we sell the VPS used for this deployment. Our Tokyo network has carrier-specific paths for the three major mainland China access networks:
- China Telecom: CTGNet, formerly China Telecom CN2 GIA, AS23764 / AS4809
- China Unicom: CUP, China Unicom Premium, AS9929 / AS10099
- China Mobile: CMIN2, China Mobile International N2, AS58807
Our China-optimized routes explainer describes what those names mean and how to inspect the path. Operators should test from the networks that will actually use the service. The Tokyo Looking Glass provides a starting point for ping and traceroute checks, but testing from the client access network remains important.
Performance depends on the access carrier, province, last mile, time of day, and whether RustDesk establishes a direct connection. A direct connection may bypass the relay workload entirely. A relayed session takes the server path, but no single Tokyo test proves how every mainland China access line will behave.
When is self-hosting not worth it?
One-off users and operators unwilling to maintain updates, firewall policy, keys, and monitoring should use a hosted remote-support vendor. That fee buys less operational responsibility.
Self-hosting fits better when a suitable VPS already exists, support sessions recur, infrastructure control matters, or the workload needs a specific location and carrier path. The calculation should include server cost, transfer, and operator time rather than comparing only two monthly prices.
Test the Tokyo route from the networks that matter, then compare Riven Cloud VPS pricing with the subscription cost and maintenance burden being replaced.
Share