RustDesk
Lifecycle: Current. Guest state verified 2026-07-17; RustDesk services and listeners last verified 2026-07-02.
RustDesk OSS provides the local self-hosted remote-access ID and relay service.
| Field | Value |
|---|---|
| Owner | IT Operations |
| Criticality / recovery priority | High / P3 |
| Host/runtime | CT 106, rootless Podman as podsvc |
| Data | /opt/podman/volumes/rustdesk |
| Secrets | id_ed25519 private identity, mode 0600; never print or commit |
Placement Decision
Use a dedicated unprivileged LXC instead of CT 101 podman-lxc.
Reasons:
- RustDesk is remote-access infrastructure, not a normal internal application.
- It needs direct TCP and UDP listeners, where RustDesk's official container guidance favors host networking.
- It has a pre-existing redacted OPNsense reservation for hostname
rustdeskat192.168.2.70. - Keeping it out of CT
101reduces the blast radius from the shared application/data host.
Target Design
| Item | Value |
|---|---|
| Proxmox CT | 106 rustdesk |
| Guest type | Unprivileged Debian 13 LXC |
| Network | DMZ VLAN 2, static 192.168.2.70/24, gateway 192.168.2.1 |
| DNS | 192.168.2.2 |
| Runtime | Rootless Podman as podsvc |
| Data path | /opt/podman/volumes/rustdesk |
| Quadlets | /home/podsvc/.config/containers/systemd/rustdesk-hbbs.container and rustdesk-hbbr.container |
| Image | docker.io/rustdesk/rustdesk-server:latest until a tested pinned tag is selected |
Ports
Minimum RustDesk OSS ports:
| Port | Protocol | Purpose |
|---|---|---|
21115 |
TCP | NAT type test |
21116 |
TCP | TCP hole punching and connection service |
21116 |
UDP | ID registration and heartbeat |
21117 |
TCP | Relay service |
Optional web-client ports are 21118/tcp and 21119/tcp; leave them closed
unless web-client support is intentionally deployed.
Live validation on 2026-07-02 showed the upstream OSS image listens on
21118/tcp and 21119/tcp by default, and hbbs --help / hbbr --help did
not expose a disable flag. Do not add WAN/NAT rules for those ports unless web
client support is explicitly approved.
Do not expose 21114/tcp unless RustDesk Pro/API is deployed.
Implementation Scripts
scripts/rustdesk/create-rustdesk-lxc-106.shcreates or converges CT106.scripts/rustdesk/bootstrap-rustdesk-podman.shinstalls rootless Podman and deploys thehbbsandhbbrQuadlets.
The CT creation script uses CT_HOSTNAME instead of Bash's built-in HOSTNAME
variable. On the first live run, HOSTNAME inherited the Proxmox host name and
created CT 106 with hostname pve; the script now corrects that specific
transient state to rustdesk.
OPNsense had a redacted historical reservation for rustdesk at
192.168.2.70, but DHCP did not hand that address to CT 106 during the live
deployment; it offered 192.168.2.109. The CT is therefore configured with a
Proxmox static address of 192.168.2.70/24 and should be reconciled with the
OPNsense reservation during a later firewall/DHCP maintenance pass.
Use a fully qualified image reference. Debian's default Podman config did not
define unqualified registry search, so rustdesk/rustdesk-server:latest failed
with a short-name resolution error.
Podman's generated user service waits for system network-online.target, which
does not become active in this static-IP LXC even when the address is usable.
The bootstrap script installs a podsvc user drop-in that makes
podman-user-wait-network-online.service return success for this CT.
Validation
Live validation after a CT reboot on 2026-07-02:
CT config: hostname rustdesk, unprivileged, static 192.168.2.70/24
Rootless services: rustdesk-hbbs.service and rustdesk-hbbr.service active
Containers: rustdesk-hbbs and rustdesk-hbbr running
Listeners: 21115/tcp, 21116/tcp, 21116/udp, 21117/tcp
Proxmox TCP checks: 21115, 21116, and 21117 reachable
Key file modes: id_ed25519 0600, id_ed25519.pub 0644
WAN/NAT: not changed
Revalidate with:
ssh pvessh 'pct config 106'
ssh pvessh 'pct exec 106 -- hostname -I'
ssh pvessh 'pct exec 106 -- runuser -l podsvc -c "systemctl --user --no-pager status rustdesk-hbbs.service rustdesk-hbbr.service"'
ssh pvessh 'pct exec 106 -- ss -H -lntup | grep -E ":(21115|21116|21117)\b"'
ssh pvessh 'pct exec 106 -- ss -H -lnup | grep -E ":21116\b"'
WAN/NAT exposure is a separate OPNsense change and should only open the minimum ports after local listeners and client registration are verified.
Operations, upgrade, backup, and restore
Use the existing validation commands for status. Logs are available through the
rustdesk-hbbs and rustdesk-hbbr containers as podsvc. Before an approved
upgrade, back up the full RustDesk data directory and both Quadlets, record the
current image digest, and test client registration plus one direct/relayed
session. Pin a tested version instead of relying indefinitely on latest.
Restore the identity key pair and database together with owner podsvc before
starting either service. Starting with a new identity can require client
reconfiguration and is not an acceptable silent restore. Keep the previous
image and data snapshot for rollback.
Monitor both units, TCP/UDP listeners, disk usage, public reachability where approved, and a scheduled client connection test.
Troubleshooting
| Symptom | Diagnosis | Remedy |
|---|---|---|
| Client cannot register | Check hbbs, 21116/tcp+udp, NAT, and client server setting |
Repair the failed listener/policy layer |
| Relay fails | Check hbbr and 21117/tcp |
Restore relay unit or approved NAT rule |
| Identity warning | Compare public-key fingerprint through an approved channel | Restore the preserved identity; do not distribute a new key silently |
| Unit waits for network | Check the documented user drop-in and static address | Restore reviewed drop-in and reload user manager |