GuidesBusiness and monitoringRustDesk remote desktop

Run your own RustDesk server for remote desktop

The open-source RustDesk server on Debian 13 in rootless Podman, so that your remote desktop and IT support sessions are brokered and relayed by your own server in Sweden, and only clients with your key can connect through it.

Tested on RustDesk Server 1.1.16 and RustDesk 1.5.0 on Debian 13 (trixie) on a Melonslab server Updated October 2, 2026

Recommended server for this guide

VC-S Micro · 2 vCPU · 8 GB Memory · 250 GB Storage

Month to month, no lock-in 7-day money-back guarantee

€7.99/mo

Deploy now
On this page

What you will set up

RustDesk is a remote desktop app, used much like TeamViewer or AnyDesk: you give someone your ID and a password, and they can see and control your screen. Out of the box, the apps find each other through RustDesk's public servers. With your own server, that job moves to a machine you control, which suits a small business, or anyone who gives IT support to colleagues and customers.

The server has two parts, which run as two containers under a user of their own called rustdesk:

  • hbbs, the ID server, keeps track of which device has which ID, and helps two devices connect straight to each other.
  • hbbr, the relay server, carries the session when the two devices cannot reach each other directly, which is common behind company firewalls.

The RustDesk apps and server are developed by Purslane Tech Pte. Ltd., a company in Singapore, as open source on GitHub. The server in this guide is open source under the GNU Affero General Public License (AGPL-3.0), and so are the apps. RustDesk also sells a closed Server Pro with a web console, user accounts, address books and audit logs. This guide uses the free server.

What still contacts RustDesk and others when the apps use your server is covered in step 8. In short: the server checks for new versions once a day, which step 3 blocks; the apps check for updates when they open, which you can switch off; and the apps ask public STUN servers for their own address.

Every step below was run on a fresh Melonslab VC-P Alloy (2 vCPU, 8 GB) with Debian 13:

  • Two RustDesk 1.5.0 apps for Linux, at another address, registered their IDs with the server. One controlled the other's screen through the relay server, and the session was end-to-end encrypted, shown by a green shield.
  • An app without the server's key was refused with Key mismatch, and the server logged the attempt.
  • The ports answered from outside over IPv4, and the ports the server does not need stayed closed.
  • With the steps in this guide, the server made no connection to RustDesk, and an app made none either once its update check was off.
  • The key, the IDs and the sessions worked again after a reboot and after a restore from the backup.

hbbs and hbbr used about 14 MB of memory together during a session, and pasta, which carries their network traffic, about 28 MB.

Before you start

You need:

  • a server set up as in the Podman guide, with ufw from the security guide. RustDesk does not need Caddy;
  • a DNS name for the server, such as desk.example.com, with an A record for its IPv4 address and an AAAA record for its IPv6 address;
  • the RustDesk app, from rustdesk.com or GitHub, on the devices you want to reach and the ones you work from.

The examples use desk.example.com for the server's name and 203.0.113.10 for its IPv4 address. Replace them throughout.

1. Open the ports

RustDesk uses its own ports, which go straight to the containers:

PortUsed byFor
21115/tcphbbsfinding out what kind of network an app is behind
21116/tcp and 21116/udphbbsregistering IDs, and setting up connections
21117/tcphbbrrelayed sessions

As root:

ufw allow 21115:21117/tcp
ufw allow 21116/udp

ufw adds each rule for IPv4 and IPv6. The server also listens on 21118 and 21119, for RustDesk's web client. The apps for computers and phones do not use them, so they stay closed. Port 21114 belongs to Server Pro's web console: the apps try it once a minute anyway, and journalctl -k shows those attempts as [UFW BLOCK] lines. That is expected.

2. Create the user

useradd -m -s /bin/bash rustdesk
loginctl enable-linger rustdesk
machinectl shell rustdesk@

Everything from now on runs as rustdesk.

3. Describe the pod

hbbs and hbbr share a pod, which publishes the ports from step 1, and a directory for the server's key and database:

mkdir -p ~/data ~/.config/containers/systemd

Create ~/.config/containers/systemd/rustdesk.pod:

[Pod]
PodName=rustdesk
PublishPort=21115-21117:21115-21117/tcp
PublishPort=21116:21116/udp
AddHost=api.rustdesk.com:127.0.0.1

The ports are published on every address, for IPv4 and IPv6. The pod uses Podman's default network, pasta, which passes on each app's real IP address. hbbs needs it to connect two apps directly. AddHost stops the daily version check of step 8.

4. Describe the containers

Create ~/.config/containers/systemd/hbbs.container:

[Unit]
Description=RustDesk ID server (hbbs)

[Container]
ContainerName=hbbs
Pod=rustdesk.pod
Image=docker.io/rustdesk/rustdesk-server:1
Exec=hbbs
Volume=%h/data:/root
AutoUpdate=registry

[Service]
Restart=always

[Install]
WantedBy=default.target

And ~/.config/containers/systemd/hbbr.container:

[Unit]
Description=RustDesk relay server (hbbr)
After=hbbs.service

[Container]
ContainerName=hbbr
Pod=rustdesk.pod
Image=docker.io/rustdesk/rustdesk-server:1
Exec=hbbr -k _
Volume=%h/data:/root
AutoUpdate=registry

[Service]
Restart=always

[Install]
WantedBy=default.target

The tag 1 follows every 1.x release of the server. Start it:

systemctl --user daemon-reload
systemctl --user start rustdesk-pod
podman logs hbbs

The log starts with Private/public key written to id_ed25519/id_ed25519.pub and a line with Key: and the public key. Further down it says Listening on tcp/udp :21116.

5. The key pair

On its first start, hbbs makes a key pair in ~/data:

  • id_ed25519 is the private key. With it, the server proves to the apps that it is yours.
  • id_ed25519.pub is the public key, which every app needs. Print it:
cat ~/data/id_ed25519.pub

hbbs refuses connections from apps that do not have the public key, without any option: an app without it gets Key mismatch, and the log shows Authentication failed ... invalid key. -k _ makes hbbr read the same key and check it too. Without it, according to hbbr's source code, hbbr relays for anyone who reaches it.

Two things to know about the key:

  • It is a public key, not a password. Everyone who uses your server has it, and anyone who gets it can relay sessions through your server. Give it to your own devices only.
  • An app without the key can still register its ID with your server. What it cannot do is connect through it.

If the private key is lost, hbbs makes a new pair, and every app needs the new public key. Step 9 backs it up.

6. Set up the apps

In the RustDesk app, open Settings, then Network, choose Unlock network settings, and then ID/Relay server. Fill in:

  • ID server: desk.example.com;
  • Key: the public key from step 5.

Leave Relay server and API server empty. The app uses the same name for the relay server, which the app's log confirmed with relay_server: desk.example.com:21117, and the API server is only for Server Pro.

Do this before you use the app: until it has your server, a new app registers with RustDesk's public server. Ours did so within seconds of its first start.

On Linux, you can set the same from the command line, as root, once RustDesk is installed. The last line sets a password for unattended access, so that you can connect without someone accepting on the other side:

rustdesk --option custom-rendezvous-server desk.example.com
rustdesk --option key 'PUBLIC_KEY'
rustdesk --password 'A-LONG-PASSWORD'
rustdesk --get-id

The last command prints the device's ID. We did not test the apps for Windows, macOS, Android or iOS. RustDesk documents the same ID/Relay server settings for them, and Export Server Config and Import Server Config under Network copy the settings from one app to another.

To connect, type the other device's ID under Control Remote Desktop, choose Connect, and enter its password. The tab shows a green shield when the session is end-to-end encrypted.

7. What your server records

hbbs keeps one row for each ID that registers, in the SQLite database ~/data/db_v2.sqlite3: the ID, a device identifier, the device's public key, when it first registered, and the IP address it last used. It keeps no history of sessions.

hbbs and hbbr log to the journal of the rustdesk user:

journalctl --user -u hbbs -u hbbr
  • hbbs logs a line with the ID, IP address and port when a device registers or its key changes, and a line with the IP address and ID when an app is refused for the wrong key.
  • hbbr logs each relayed session, with the IP addresses of both sides, but not their IDs. The session it forwards is encrypted between the two apps.

IP addresses linked to a person are personal data under the GDPR. The journal keeps them until it is rotated.

8. What RustDesk and others still see

We watched the network traffic of the server and of two apps that used it:

  • The server asks api.rustdesk.com for the latest version when it starts and once a day. It sends the operating system, its version, the processor type and a device ID, a hash of the server's hardware. The service ran at Hetzner in Germany when we tested. It only writes new version is available to the log, and does not update anything. The AddHost line in step 3 points the name at the container itself: with it, the server made no connection to RustDesk, and it worked as before.
  • The apps send the same kind of version check to api.rustdesk.com when their main window opens. To stop it, turn off Check for software update on startup under Settings, then General. With it off, we saw no connection to RustDesk.
  • The apps also ask four public STUN servers, from Cloudflare, Google, Nextcloud and Antisip, for their own public IPv6 address when they start. Those services see the device's IP address. We found no setting that turns this off.
  • With your server set, we saw no connection from the apps to RustDesk's public ID and relay servers. Sessions go directly between the devices, or through your hbbr.

RustDesk's privacy policy describes what the company collects through its websites and public servers, and names providers that process data in the United States and other countries.

9. Back up

The two files that matter are the private key and the database. As rustdesk, stop the pod for a moment, so that the database is written out, and pack the directory:

mkdir -p ~/backup
systemctl --user stop rustdesk-pod
tar -czf ~/backup/rustdesk-$(date +%F).tar.gz -C ~ data
systemctl --user start rustdesk-pod

Sessions that are running end when the pod stops, and the apps reconnect to the server by themselves when it starts. Copy ~/backup to another machine, and store it securely: with the private key, anyone can run a server your apps trust. To restore, stop the pod, unpack the file in the home directory with tar -xzf ~/backup/rustdesk-DATE.tar.gz -C ~, and start the pod. The log shows the same Key: as before, and the apps connect again without any change.

10. Keep it up to date

Turn on Podman's daily updates:

systemctl --user enable --now podman-auto-update.timer
podman auto-update --dry-run

The last command lists hbbs and hbbr, and shows whether an update is waiting. Podman restarts the pod when the image changes. Keep the apps up to date too. If you turned off their update check in step 8, watch the releases on GitHub.

Troubleshooting

The app says Key mismatch. The app's Key differs from ~/data/id_ed25519.pub, or is empty. Copy the key again, without spaces.

systemctl --user restart hbbs hbbr fails with "A dependency job for hbbr.service failed". Restarting both containers at once stops their pod. Restart the pod instead, with systemctl --user restart rustdesk-pod.

The apps register, but the log shows lines with [UFW BLOCK] and port 21114. The apps look for Server Pro's web console on that port. The free server has none, so nothing is missing: leave the port closed.

The app says "Failed to connect to desk.example.com:21116: Please try later". The app cannot reach hbbs. Check that podman ps lists hbbs and hbbr, that the ports from step 1 are open, and that the app's ID server is your server's name.

Run it on your own server

VC-S Micro

€7.99/mo

vCPU
2
Memory
8 GB
Storage
250 GB
Transfer
10 TB
Standard
HDD · RAID 10
  • Full root access
  • Native /64 IPv6
  • RAID-protected storage
  • Malmö, Sweden
  • Month to month, no lock-in
  • 7-day money-back guarantee
All guides