docs: refresh CONFIGURATION.md — TOTP self-service, new routes, bind flags

Caught up the docs to match what the dashboard actually does. Four spots
were stale enough to be misleading.

- TOTP / 2FA section rewritten. The doc still claimed admins enrolled
  TOTP from the Users action menu, but that button was removed when
  TOTP enrollment moved to the self-service profile page (two-step
  with QR + 6-digit confirmation; nothing written to user_totp_secrets
  until the user proves they have a working authenticator). Admins can
  disable a user's TOTP but can no longer enroll on someone's behalf.
  Also called out that OIDC-linked users skip local TOTP — their MFA
  lives at the IdP.

- Admin dashboard URLs table was missing nine routes that exist
  today: /admin/assets/{tailwindcss,htmx.min}.js (vendored CDN
  assets), /admin/pages/profile + four sub-routes (self-service
  profile flow), /admin/connect/:peer_id, and the two web-client SPA
  asset routes. Updated the Users-page row to mention the inline
  edit-profile + TOTP-disable controls.

- CLI flags / HTTP API & dashboard table now lists --http-listen and
  --ws-listen (they previously only appeared inside the nginx
  subsection — discoverability matters when an operator scans the
  flag tables looking for what's available). Added a one-liner about
  hbbr's matching --ws-listen flag.

- Security checklist gained a bind-flags hardening tip
  (--http-listen=127.0.0.1, --ws-listen=127.0.0.1 on both daemons
  when fronted by nginx) and a note about forwarding
  X-Forwarded-Proto: https so the dashboard generates wss:// URLs.

Sections cross-checked and confirmed accurate as-is: OIDC walk-through
+ role sync + troubleshooting, strategies, address books, recordings,
audit retention, SMTP, web client (routes / browser reqs / codec /
HUD diagnostics / build), database / backup notes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 21:27:32 +02:00
parent aa40784dc6
commit 7e2c7a7e4c
+37 -8
View File
@@ -31,9 +31,13 @@ hbbs itself (only the optional `oidc.toml` referenced from a flag).
| Flag | Default | Purpose |
|---|---|---|
| `--http-port=<NUM>` | `21114` | HTTP API port (`/api/*`) and admin dashboard (`/admin/*`). `0` disables both. |
| `--http-listen=<HOST>` | wildcard | Bind address for `--http-port`. Set to `127.0.0.1` (or `::1`) when nginx/Caddy fronts this port for TLS so the reverse proxy can claim the public port without colliding. See "TLS deployment with nginx" below. |
| `--ws-listen=<HOST>` | wildcard | Bind address for the browser-facing WebSocket rendezvous port (`port + 2`, default 21118). Same usage pattern as `--http-listen`. The plain TCP/UDP rendezvous ports (21115/21116) intentionally stay on the wildcard — desktop clients don't go through the reverse proxy. |
| `--admin-ui-dir=<PATH>` | `./admin_ui` | Hint at where the dashboard's static HTML lives. The HTML is *embedded* in the binary; this flag is informational. Setting it to empty (`--admin-ui-dir=`) disables the dashboard entirely. |
| `--public-base-url=<URL>` | unset | The externally-reachable HTTP base of this server, e.g. `https://rustdesk.example.com:21114`. **Required when OIDC is enabled** — used to build `/oidc/callback` redirect URIs. |
The matching flag on **hbbr** is `--ws-listen=<HOST>` (binds the relay's WS port, default 21119). hbbr's plain TCP relay port (21117) stays on the wildcard for desktop clients. See `./hbbr --help` for the full list.
### Bootstrap admin
| Flag | Purpose |
@@ -249,11 +253,27 @@ name (Zitadel) or omit it to default to `"roles"` (generic).
## TOTP / 2FA
Per-user TOTP is enrolled from the dashboard:
TOTP enrollment is **self-service**: each user enables it for their own
account from the dashboard's "My profile" page. The flow is two-step
with QR confirmation, so no secret is stored until the user proves they
have a working authenticator:
1. Sign in as an admin → **Users** page.
2. Pick a user → action menu → **Enroll TOTP**.
3. Scan the QR code into an authenticator (1Password, Authy, Google Authenticator, etc.). The secret is shown once and stored in `user_totp_secrets`.
1. Sign in to the dashboard → **My profile** (sidebar) → **Enroll TOTP**.
2. Server generates a fresh secret and renders an inline SVG QR code +
the base32 secret for manual entry. Nothing is written to
`user_totp_secrets` at this point.
3. User scans the QR into an authenticator (1Password, Authy, Google
Authenticator, etc.) and submits the 6-digit code shown.
4. Server verifies the code against the pending secret. On match, the
secret lands in `user_totp_secrets`. Wrong code re-renders the same
QR with an error notice — no need to re-scan.
5. Removing TOTP requires the user's current password.
Admins can disable a user's TOTP from the **Users** page action menu
(useful when a user lost their authenticator), but **cannot enroll it
on someone else's behalf** — the user has to do that themselves so the
secret never travels through admin hands. OIDC-linked accounts skip
local TOTP entirely; their MFA lives at the IdP.
After enrollment, the next desktop-client login flow is:
@@ -298,9 +318,11 @@ If you set `--ab-legacy-mode=on`, `/api/ab/personal` 404s and clients fall back
| `/admin/login` | none (POST form) | Password+TOTP submit → sets `rd_admin_session` cookie |
| `/admin/logout` | cookie | Clears cookie |
| `/admin/me` | cookie | Sidebar's logged-in-as widget |
| `/admin/assets/tailwindcss.js` | none | Vendored Tailwind 3.4.16 Play CDN. Long-cache. |
| `/admin/assets/htmx.min.js` | none | Vendored htmx.org 1.9.10. Long-cache. |
| `/admin/oidc/providers` | none | JSON list of enabled providers, used by login.html |
| `/admin/login/oidc/:name` | none | Starts admin OIDC flow (302s to IdP) |
| `/admin/pages/users` | cookie + admin | Users page fragment |
| `/admin/pages/users` | cookie + admin | Users page fragment (incl. inline edit-profile / password-reset / TOTP-disable per row) |
| `/admin/pages/devices` | cookie + admin | Devices (incl. delete) |
| `/admin/pages/groups` | cookie + admin | Device groups |
| `/admin/pages/strategies` | cookie + admin | Strategy management |
@@ -309,6 +331,12 @@ If you set `--ab-legacy-mode=on`, `/api/ab/personal` 404s and clients fall back
| `/admin/pages/audit` | cookie + admin | Audit log browser |
| `/admin/pages/recordings` | cookie + admin | Recording file listing |
| `/admin/pages/deploy` | cookie + admin | `--config` blob + renamed-installer generator |
| `/admin/pages/profile` | cookie | Self-service profile (display name, email, password, TOTP enroll/remove). Available to all signed-in users — no admin gate. |
| `/admin/pages/profile/update-info` | cookie (POST) | Display name + email update |
| `/admin/pages/profile/change-password` | cookie (POST) | Requires current password; refused for OIDC-linked accounts |
| `/admin/pages/profile/totp/{start,confirm,remove}` | cookie (POST) | Two-step QR enroll, plus password-gated removal |
| `/admin/connect/:peer_id` | cookie + admin | Web-client SPA shell — opens a browser-based remote-control session in a new tab |
| `/admin/connect/assets/bundle.{js,css}` | cookie + admin | Compiled web-client SPA bundle |
The session cookie (`rd_admin_session`) is HttpOnly + SameSite=Strict.
The middleware accepts the same cookie *or* `Authorization: Bearer …`,
@@ -599,9 +627,10 @@ multi-instance HA; run a single hbbs against a single SQLite file.
## Security checklist before exposing to the internet
- TLS in front of `--http-port` (Caddy / nginx / Traefik). Required for OIDC redirect URIs in production.
- TLS in front of `--http-port` and the WebSocket ports (Caddy / nginx / Traefik). Required for OIDC redirect URIs and for the web client (browsers block mixed `ws://`). See "TLS deployment with nginx" for a worked config.
- Pin browser-facing ports to localhost when a reverse proxy is in front: `--http-listen=127.0.0.1` on hbbs, `--ws-listen=127.0.0.1` on both hbbs and hbbr. Keeps the plain-HTTP / plain-ws surface unreachable from the public internet — the proxy is the only path in.
- `--public-base-url` set to the *externally* reachable URL, including the scheme.
- `--bootstrap-admin-password` rotated immediately after first login (Users page → reset password).
- `--bootstrap-admin-password` rotated immediately after first login (Users page → reset password, or via the admin's own "My profile" page).
- `--key` / `id_ed25519` not committed to source control. Treat the private key as a deploy secret.
- Audit retention (`--audit-retention-days`) set to a value that matches your data-retention policy.
- If running behind a reverse proxy: forward the original `Host:` header so OIDC redirect-URI validation matches.
- If running behind a reverse proxy: forward the original `Host:` header so OIDC redirect-URI validation matches, and forward `X-Forwarded-Proto: https` so the dashboard generates `wss://` URLs.