Skip to content

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 rustdesk at 192.168.2.70.
  • Keeping it out of CT 101 reduces 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.sh creates or converges CT 106.
  • scripts/rustdesk/bootstrap-rustdesk-podman.sh installs rootless Podman and deploys the hbbs and hbbr Quadlets.

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

Official reference