secubox-deb/packages/secubox-rustdesk
CyberMind-FR 0f184a076b feat(yacy,grafana,rustdesk): apply dual-vhost MUST pattern (MODULE-GUIDELINES §4)
Third batch after lyrion/zigbee/authelia (commit 54da8a7c). Same anti-
pattern across all three: nginx `/<module>/` was proxy_pass'ing to the
LXC, which silently broke any absolute asset URL the upstream app
served. Each module gets the same surgical fix:

- nginx/<module>.conf — /<module>/ is now `alias /usr/share/secubox/
  www/<module>/` (SecuBox admin static page) instead of `proxy_pass`.
  Both /api/v1/<module>/ and /<module>/ gated by `auth_request
  /__sbx_auth_verify` so SSO covers admin access.
- <module>ctl — config_get strips TOML inline comments;
  emit_access_json now returns the REAL upstream URLs (no /<module>/
  admin suffix); PUBLIC_HOSTNAME defaults to <module>.gk2.secubox.in.
  grafanactl also gets the `""|""` -> `""|list` case fix.
- www/<module>/index.html — "native UI" button reads its href from
  /api/v1/<module>/access at runtime (single source of truth) and
  opens in a new tab.

NEW dedicated vhost files for grafana and rustdesk (yacy already had
one): packages/{grafana,rustdesk}/nginx/<module>-vhost.conf. Both
listen 0.0.0.0:9080 server_name <module>.gk2.secubox.in, Authelia-
gated, serving the upstream app at root. Operator prerequisites (DNS
+ TLS cert + HAProxy ACL + mitmproxy route inside its LXC) documented
in each vhost header.

Side note: grafana's LMS-style absolute-path problem requires
`serve_from_sub_path = false` + `root_url = https://grafana.gk2.
secubox.in/` in /etc/grafana/grafana.ini inside the LXC. This is
flagged in the changelog as a follow-up for install-lxc.sh; for now
the live LXC config is unchanged.

Live verified on gk2 — all six modules (lyrion + zigbee + authelia +
yacy + grafana + rustdesk) now return the same /access shape:
  lan      http://<lxc_ip>:<port>/         (lan-only)
  public   https://<module>.gk2.secubox.in/ (Authelia SSO)
2026-05-24 10:24:35 +02:00
..
api feat(secubox-rustdesk): new LXC module for self-hosted remote-desktop relay (closes #234) (#235) 2026-05-20 07:56:19 +02:00
conf feat(secubox-rustdesk): new LXC module for self-hosted remote-desktop relay (closes #234) (#235) 2026-05-20 07:56:19 +02:00
debian feat(yacy,grafana,rustdesk): apply dual-vhost MUST pattern (MODULE-GUIDELINES §4) 2026-05-24 10:24:35 +02:00
haproxy feat(secubox-rustdesk): new LXC module for self-hosted remote-desktop relay (closes #234) (#235) 2026-05-20 07:56:19 +02:00
lib/rustdesk fix(lxc-modules): 9 board-deployment fixes for grafana/yacy/rustdesk install-lxc.sh + nginx wiring (#238) 2026-05-20 09:21:48 +02:00
menu.d fix(navbar): emoji icons + restore MQTT menu entry overwritten with Lyrion content 2026-05-23 18:42:51 +02:00
nginx feat(yacy,grafana,rustdesk): apply dual-vhost MUST pattern (MODULE-GUIDELINES §4) 2026-05-24 10:24:35 +02:00
sbin feat(yacy,grafana,rustdesk): apply dual-vhost MUST pattern (MODULE-GUIDELINES §4) 2026-05-24 10:24:35 +02:00
www/rustdesk feat(yacy,grafana,rustdesk): apply dual-vhost MUST pattern (MODULE-GUIDELINES §4) 2026-05-24 10:24:35 +02:00
README.md feat(secubox-rustdesk): new LXC module for self-hosted remote-desktop relay (closes #234) (#235) 2026-05-20 07:56:19 +02:00

secubox-rustdesk

RustDesk self-hosted remote-desktop signal (hbbs) and relay (hbbr) servers in a Debian LXC at 10.100.0.90 on the SecuBox br-lxc bridge.

Follows docs/MODULE-GUIDELINES.md; opens the REMOTE-ACCESS layer of the SecuBox CTL grammar.

Why this module deviates from the grafana/yacy pattern

  • Two daemons in the LXC (hbbs + hbbr), each on its own systemd unit. rustdeskctl components surfaces them as separate components, not aggregated.
  • Non-HTTP exposure — RustDesk uses raw TCP on 21115/21116/21117 and UDP on 21116. mitmproxy cannot inspect raw UDP, so:
    • HAProxy stream-mode handles the three TCP ports (config shipped at /etc/haproxy/secubox-streams/rustdesk-stream.cfg)
    • nftables DNAT handles the UDP signal port (rule installed by install-lxc.sh into the inet secubox table)
    • Only the web admin UI (port 21114) goes through nginx like the other modules.

Quickstart

apt install secubox-rustdesk
rustdeskctl install     # provisions LXC + hbbs + hbbr + nftables DNAT + PSK
rustdeskctl status

Pre-shared key for clients lives at /etc/secubox/secrets/rustdesk-key. Embed it (and relay = <your-public-ip>:21117) into RustDesk client builds or paste it into the client's Custom Server config.

CTL — rustdeskctl

rustdeskctl components   # lxc + hbbs + hbbr + host-api (4 components, not 3)
rustdeskctl status       # green only if all 4 are running
rustdeskctl access       # 4 URLs: lan-web, public-web, lan-signal, lan-relay

Module-specific nouns (v1.1.0 follow-up):

rustdeskctl peer    list|add <id> <pubkey>|remove <id>
rustdeskctl relay   status|restart|log
rustdeskctl key     show|rotate
rustdeskctl session list|kill <id>

rustdeskctl install
rustdeskctl reload      # restarts host FastAPI + hbbs + hbbr

Ports

Port Proto Daemon Exposure
21114 tcp hbbs (web admin) nginx /rustdesk/ → iframe
21115 tcp hbbs (NAT-test) HAProxy stream-mode
21116 tcp hbbs (signal) HAProxy stream-mode
21116 udp hbbs (signal) nftables DNAT (mitmproxy can't inspect UDP)
21117 tcp hbbr (relay) HAProxy stream-mode

Files

/etc/secubox/rustdesk.toml                # operator config
/etc/secubox/secrets/rustdesk-key         # pre-shared key (generated)
/etc/nginx/secubox.d/rustdesk.conf
/etc/haproxy/secubox-streams/rustdesk-stream.cfg
/usr/lib/secubox/rustdesk/api/            # host FastAPI
/usr/share/secubox/lib/rustdesk/          # install-lxc.sh
/usr/share/secubox/www/rustdesk/
/usr/share/secubox/menu.d/70-rustdesk.json
/data/lxc/rustdesk/                       # LXC rootfs (created by rustdeskctl install)

Troubleshooting

  • rustdeskctl status shows hbbs: stoppedlxc-attach -n rustdesk -- journalctl -u rustdesk-hbbs.
  • UDP not forwarding → nft list table inet secubox should show the DNAT rule for 21116/udp.
  • Client cannot connect → confirm PSK is identical on both ends; relay IP must be the host's public IP, not the LXC IP.