- Default console shell is now the classic icon rail + flyout, with UX 3.5 available via navbar switch.
- Fixed visibility issues in UX 3.5, ensuring main content is displayed correctly under branding wallpaper.
- Updated documentation to reflect changes in UI shell options and theme management.
- Enhanced language support for new UI shell switch options across multiple languages.
This update improves user experience by providing a choice between classic and modern UI shells.
Commit web-nodejs lockfile with tar override; CI uses npm ci and moderate npm audit.
Add LOG_LEVEL filtering and log redaction in Node console and Go server.
Validate WS tokens on bd-signal; require single-use token for remote-agent relay.
Limit active relay sessions per IP and block open enrollment without TLS.
Help operators reach the panel at https://domain without :5443 via installer prompts, docs, and cleaner HTTP redirects, and align fresh-install self-signed cert permissions with the #219 deploy flow.
- Resolved issues with panel tabs redirecting to the dashboard on 401 errors by allowing browser requests without Bearer tokens to fall through to panel handlers.
- Extended the rate limit whitelist for Devices/Users API endpoints to prevent 429 errors during high load.
- Introduced a new rate limiter for desktop layout preference saves, ensuring session-authenticated writes are managed effectively.
- Implemented staggered loading for API requests on the Devices page to optimize performance and reduce rate limit bursts.
- Updated relevant tests to cover new fallthrough behavior and rate limiting logic.
- Updated dashboard panel poll endpoints to utilize a higher widget quota, preventing 'Too Many Requests' errors during load/refresh.
- Introduced a new function to dynamically retrieve panel poll paths, ensuring efficient rate limiting for specific dashboard requests while preserving the general API budget.
Unify .env and systemd updates on protocol toggle, probe the correct panel
port (5443 vs 5000), and match Client API TLS in post-config tests. Use 307
redirect and skip HSTS for self-signed installs so browsers can return to HTTP.
Added a compatibility layer for MeshCentral, including a native Go implementation of key endpoints and a unified inventory for mesh agents. Enhanced the UI with new actions for mesh agents, such as terminal access and file management. Updated localization for mesh features and introduced new styles for mesh terminal overlays. Integrated interop testing for simulated and live MeshAgent connections.
Restore agent-client to git and wire agentClientBuildWorker for Tauri builds
(deb/rpm/AppImage/MSI) with branding and Go sidecar staging. Add TLS gate,
settings lock, policy sync, preflight UI, CDAP registry, and Generator
product_type split (agent-client vs support-agent vs rdclient).
- Introduced server URL validation via `GET /api/bd/server-info` and `probe_server_url`.
- Added LAN discovery capabilities using UDP and optional mDNS for local network panel detection.
- Implemented a local settings window for managing URL, TLS settings, and user preferences.
- Enhanced dashboard with a unified sidebar and improved scrolling behavior.
- Updated documentation and pre-release checklist to reflect new features and requirements.
- Introduced email notifications for help requests, allowing operators assigned to device folders or groups to receive alerts.
- Moved SMTP configuration to **Settings → Email**, including options for host, credentials, and alert email.
- Updated console layout for better usability and removed legacy SMTP automation tab.
- Added `nodemailer` as a dependency for email handling.
Updated the entire project to AGPL-3.0, including all components and documentation. The stable releases up to v3.3.x will remain under Apache 2.0 until the next major feature release. Withdrawn and recreated French and Traditional Chinese translations under the new license. Updated relevant documentation and changelog to reflect these changes.
Security update H-7 runs the console as User=betterdesk, which cannot bind
ports below 1024 without CAP_NET_BIND_SERVICE. Fall back to high ports at
startup, add the capability to systemd when .env uses :443/:80, and handle
EACCES on listen without an unhandled process crash.
Sync console file ownership before the dedicated service user starts, add
ExecStartPre permission repair on systemd, and skip in-app restart when
permissions are not verified so the panel does not die with Bad Gateway.
Node requireAuth only accepts 64-char auth.db tokens, so local /api/group
handlers returned 401 after Go JWT login. Proxy group routes to Go again,
always merge peer-tag groups, resolve auth.db path candidates, and map
console user ids for group ACL checks.
Panel groups and folders live in console auth.db, but Go /api/group only
exposed peer tags. Read auth.db (AUTH_DB_PATH), apply allowed_users and
user-group access, and mirror Node getRustDeskDeviceGroups. Keep /api/group
on the Node :21121 proxy for compatibility; document verification steps.
RustDesk clients could not log in after v3 when handlers moved to Go but
nothing listened on :21121 (API_ENABLED off) or Go bound the wrong port.
Go serves /api/login on 21114; the console proxies legacy :21121 URLs to
Go. Installers repair .env/systemd, Docker publishes both ports, and
firewall rules allow 21114 and 21121 on full installs.
Also includes betterdesk-support-agent (Fyne desktop helper) and
docs/important/ operator notes (API ports, update flow, agent roadmap).
Remove the user-mode / rootless install and privilege-separation scaffolding that was added in the previous commit — the feature needs more testing before shipping. Reverts: USER_MODE, RUN_AS_ROOT, ensure_service_user, set_service_ownership, systemd User=/Group= directives, all --user/--rootless/--run-as-root CLI flags, and related help text. Restores API_PORT default to 21114.
server.js: fix startup banner — show 'Disabled' (not 'Served by Go server') when apiEnabled is false, and correct the Go API fallback URL from port 21121 to 21114.
This commit was made possible thanks to Insolve.
Privilege separation across all installers so the long-running services no longer run with full administrative rights:
betterdesk.sh: installer keeps root but systemd units now run as a dedicated unprivileged 'betterdesk' system account by default (auto-created via ensure_service_user). Added full systemd hardening for the Go server (NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp, ReadWritePaths) and light hardening for the Node.js console. chown migrates existing root-owned data to the service account on update. Opt-out via --run-as-root / BETTERDESK_RUN_AS_ROOT=1; custom account via BETTERDESK_SERVICE_USER. Minimal mode covered too.
betterdesk.ps1: NSSM services now run under their per-service low-privilege virtual accounts (NT SERVICE\<service>) instead of LocalSystem, with scoped icacls grants on the install/data dirs (Set-ServiceLeastPrivilege helper). Applied to the Go server, Node.js console and minimal-mode service. Opt-out via -RunAsRoot / BETTERDESK_RUN_AS_ROOT=1.
Docker: verified already privilege-separated (supervisord drops both programs to user=betterdesk; multi-container images drop via su-exec).
Also bundles in-progress changes to the Go server API, Node.js console services and Docker compose/Dockerfiles.
This commit was made possible thanks to Insolve.
Node.js (no recompile required):
- H-04: RUSTDESK_API_DISABLE_TOTP now requires explicit _ACKNOWLEDGED flag
- M-03: drop Referer-based skip from apiLimiter; add dedicated widgetLimiter
- M-06: gate /api/system/info, /logs/recent, /database/stats, /docker/containers, /speed-test behind requirePermission('metrics.view')
- L-01: startup banner now warns when TRUST_PROXY is off in production / errors when TOTP bypass is set without acknowledgement
Scripts / Docker:
- M-04: betterdesk.sh migration tool invocation switched from eval(cmd-string) to bash array exec
- M-05: all admin / PostgreSQL password generators switched from openssl rand -base64+tr+head to openssl rand -hex 16 (full entropy)
- L-02: docker-compose.yml / single.yml / quick.yml services gain security_opt: no-new-privileges and cap_drop: ALL
Documentation:
- I-04: add SECURITY.md (supported versions, reporting channels, SLA, scope, hardening defaults)
Go server (requires rebuild on host: cd betterdesk-server && go build ./...):
- H-03: /metrics now gated by METRICS_IP_ALLOWLIST / METRICS_PUBLIC; per-username login + 2FA rate-limit added on top of per-IP
- M-07: enrollment (/api/devices/register*) and branding (GET /api/branding) endpoints rate-limited per IP
- I-02: bd-mgmt WebSocket gets SetReadLimit(16 MiB) to bound memory
- L-04: auth middleware skips noisy public probes and redacts /peers/{id} segments
This commit was made possible thanks to Insolve.
Adds explicit RUSTDESK_API_TLS mode so self-signed deployments can keep the web panel HTTPS while serving the RustDesk Client API on HTTP for stock client compatibility.
Refs #138
- Implemented server management service providing resource snapshots, file browser, service control, and audit logging.
- Added terminal proxy for WebSocket-backed PTY, allowing browser-based shell access with user authentication and role-based access control.
- Created server management view with tabs for overview, terminal, file management, and services, including UI elements for displaying system metrics and managing files/services.
Co-authored-by: Copilot <copilot@github.com>
Panel accounts were created only in the Node auth.db while the
Organization 'Add User -> Add Existing' dropdown queries the Go
server's users table via db.ListUsersNotInOrg(). This produced a
mismatch where only the seeded admin appeared as linkable.
Add a userSync service that mirrors create / update / delete /
password-reset operations from the Node panel to the Go server's
/api/users endpoints, plus a one-shot backfill at startup that
creates Go-side records for any pre-existing panel users (random
throwaway password; Node bcrypt remains authoritative for panel
login).
Reported-by: SterlynKong <SterlynKong@users.noreply.github.com>
Adds three small but valuable compatibility patches inspired by progloto's
PR #81 analysis, reworked to fit our codebase and security baseline:
* Stub /api/group, /api/group/get, /api/peers/list with the {total,data,msg}
envelope so RustDesk PRO Flutter clients can finish their device-list
flow and gracefully fall back to address-book mode.
* Log every unmatched route in the Go API catch-all (method, path, client
IP, User-Agent) so missing client compatibility endpoints surface in ops
logs immediately.
* Mirror the same 404 logging in the Node.js RustDesk-compatible API app
and the main panel app (limited to /api/* and /ws/* paths to avoid
static-asset noise).
The original PR #81 also bundled a docker-compose.qnap.yml with hardcoded
production secrets, a private NAS deploy script, and a VERSION bump that
collided with our release cycle, so we are not merging it as-is. The
ideas behind these three patches were sound and are credited here and
in CHANGELOG.md.
Co-authored-by: progloto <progloto@users.noreply.github.com>
- deployServerBinary: use rename(2) for atomic replace, fixes ETXTBSY
when target Go binary is busy (Linux kernel handles inode swap).
Falls back to copyFileSync on cross-device rename or non-Linux.
Windows: rename target out of the way first, then move new in.
- settings.js: mark 'server' phase as error when build succeeded but
deploy failed (was incorrectly marking 'done' from build alone).
- settings.js: completion modal now shows error title, error message
and pre-formatted stderr when serverDeploy.success === false.
- i18n: added complete_with_errors, modal_done_with_errors_title in
en/pl.
Multiple security and maintenance fixes across components:
- betterdesk-mgmt: validate peer_id format to prevent injection in connect_to_peer (reject empty/oversized/invalid chars).
- betterdesk-mgmt (tauri.conf.json): tighten CSP by removing 'unsafe-eval' from script-src.
- betterdesk-agent-client: increase device ID entropy from 4 to 8 bytes (BD- prefix) to reduce collision/brute-force risk.
- betterdesk-server: enforce RBAC (operator+) before upgrading CDAP video WebSocket to block unauthorized access.
- betterdesk-server DBs: exclude soft_deleted peers in GetPeer queries for Postgres and SQLite.
- web-nodejs: add audit log housekeeping (hourly cleanup), add indices for audit_log, and implement cleanupOldAuditLogs(days) in sqlite adapter.
- web-nodejs brandingService: validate logo/favicon URLs to allow only http(s) or relative paths, preventing javascript:/data: XSS/SSRF vectors.
- docs: add AUDIT_BETTERDESK_2026-04-17.md (security audit summary).
These changes tighten client CSP, improve input validation, increase device identifier entropy, ensure RBAC is enforced before websocket upgrades, hide soft-deleted peers from normal queries, and add audit log maintenance and DB indexes for better performance and retention management.
Replace client-side base64 logo handling with server disk uploads and update related UI/locales. Increases logo size limit to 2 MB, adds success messages and revised hints in en/pl/zh locales. Client JS now POSTs the file to /api/settings/branding/upload-logo with CSRF header and fills the image path on success. Adds an Express route using multer to store uploads under dataDir/uploads, validate types/sizes, remove previous uploaded logo, and log the action. Also serves the /uploads static directory from the persistent data dir.
Add typography support and a text-based logo option plus several TLS/connectivity improvements. Introduces a new font service (web-nodejs/services/fontService.js) to search, download and serve Google Fonts for self-hosting, new API routes for font management, and client-side font picker UI/logic (settings.js) with CSS (pages.css, main.css) and i18n entries (en/pl/zh). BrandingService now supports logo text/accent and font heading/body and includes generated font CSS. Views (login/sidebar) updated to render text logos and a new theme (themes/insolve.json) added. Server and TLS updates: API server now prefers TLS on the API port when valid certs exist, and dual-mode listener in tls.go adds a short peek timeout to avoid deadlocks with RustDesk clients.
Implement RBAC Phase 52: add server-side role & permission handlers and wire API routes, plus frontend UI, styles and translations.
Server: new role_handlers.go exposing endpoints to list roles, get effective role permissions, list/set/delete role permission overrides; routes registered in server.go with permission checks (PermUserView / PermServerConfig). Protects super-admin defaults and validates inputs.
Frontend (management & web UI): add permissions page assets (CSS, JS, view), add i18n strings for en/pl/zh, update sidebar to filter items by canView, show user role badge in topbar and empty access-denied state when no permission. Add role badges styling in users.css and small UX/i18n improvements in organizationDetail.js.
Also several route and service adjustments to support the new permissions UI. This change introduces RBAC UI/API plumbing for managing role-based permissions and overrides.
Adds a full Phase-52 RBAC implementation and multiple server/frontend fixes. Key changes: new auth/permissions.go with 28 granular permissions and DefaultRolePermissions, expanded 7-role hierarchy and helpers in auth/roles.go, JWT org context and GenerateOrgToken, requirePermission/requireOrgMembership middlewares (Go + Node.js), DB schema & adapter changes for role_permissions and is_server_admin, org role boundary checks and peer org scoping, and guards for last-admin demotion and self-demotion. Also: TCP EOF/connection-reset log filtering in signal/relay servers, improved startup banner port display, KEYS_PATH auto-detect warning, CSS hover/transition layout fixes, admin password race mitigation, ID-change ghost peer cleanup, added Tauri ACL schema files, and a new RBAC_PHASE52.md doc. Misc: numerous web-nodejs i18n, CSS, JS and route updates and an updated .github/copilot-instructions.md timestamp/summary.
- config.js: resolveKeysPath() checks for id_ed25519 in /opt/betterdesk first,
then /opt/rustdesk, respecting env var override as highest priority
- betterdesk.sh: add /opt/betterdesk to COMMON_RUSTDESK_PATHS search list,
change default for new installs from /opt/rustdesk to /opt/betterdesk
- server.js: show resolved Keys path in startup banner for easier debugging
- Existing installs with KEYS_PATH env var are unaffected
- Windows already defaults to C:\BetterDesk (no change needed)
Introduce a SessionManager for relay-based remote sessions in the Tauri MGMT client: new SessionCommand API, start/stop/session input routing, clipboard/recording/quality controls, and notification read/dismiss state. Wire AppState with new mutexes and show main window on startup. CI: add SBOM generation (anchore) and Trivy vulnerability scan steps. Misc: change console Docker DB path, large README/CHANGELOG updates (chat E2E, unattended access/WOL, i18n expansion, CDAP/SDK docs), and many web-nodejs assets/locales/routes/views/services and server-side changes.
Simplify the management app startup and UI: App.tsx now initializes auth and conditionally renders Login or Layout with a minimal Splash. Introduces an auth store and new Login/Layout components, adds DeviceList and Settings components, and updates Sidebar, Dashboard, locales and global styles. Removes the legacy chat window (HTML + entry), the tauri chat window entry, and many panel components that were unused (Activity, Automation, CDAP, ChatWindow, Connection, RemoteAgent, Management, NotificationCenter, Operator, OrgLogin, PasswordDialog, RemoteBadge, RemoteView, ServerPanel, SettingsPanel, SetupWizard, TotpDialog, Toolbar, etc.). Also adds a favicon and updates vite/server config and main entry adjustments to reflect the new streamlined, auth-driven layout.
Add multiple security hardenings across the server and web console: enforce proof-of-possession for /ws/bd-mgmt using Ed25519-signed headers with timestamp/nonce and replay protection (public key binding, canonicalization, storage, verification, and tests); remove legacy API key query param and config-table fallback in favor of scoped api_keys (migrate bootstrap key into api_keys); tighten WebSocket origin handling for relay and signal servers to allow only localhost origins by default unless an explicit allowlist is set; update auth middleware public paths and test helpers to use X-API-Key header; add ensureScopedAPIKey migration and related helpers; add a GitHub Secret Scan workflow and an audit report. Misc: propagate audit logging on bd-mgmt connect/disconnect and validate enrollment public keys during device register.
Add unit tests and test helpers (5 suites, 41 tests) and test npm scripts; introduce deviceStatusPush service and WS real-time device status push integration. Fix chatRelay to acknowledge connections (send `welcome`), and apply multiple web remote/rdclient fixes (video ack/timing, keyframe refresh, SourceBuffer trimming, input focus handling) to improve FPS and control. Add new server route file (system.routes.js), new device-status service, update server.js and package.json, and modify various frontend CSS/JS/views. Update English and Polish locale files with many new widget/i18n keys and remove the Russian locale file (ru.json). Also include assorted UI/desktop-widget dashboard tweaks and documentation status updates in .github/copilot-instructions.md.
Introduce persisted chat features and a BetterDesk desktop management WebSocket channel. Adds new REST chat handlers (history, send, read, unread, contacts, groups), bd-mgmt WebSocket and management REST endpoints, and routes in the HTTP server. Extend Database interface and models (ChatMessage, ChatGroup, ChatContact) and implement schema migrations + CRUD for PostgreSQL and SQLite. Adjust auth middleware to allow /ws/bd-mgmt/* and relax server WriteTimeout / increase IdleTimeout to accommodate long-lived WS connections. Also add a 3.0 roadmap document and minor frontend/localization/service updates related to chat and relay.
Introduce full CDAP subsystem and devices UI overhaul. Adds a new CDAP WebSocket gateway (cdap/gateway.go) with auth, connection lifecycle, message loop, heartbeat monitor and APIs (cdap/api.go, cdap/auth.go, cdap/handler.go, cdap/manifest.go, cdap/messages.go). Wire CDAP into the server (api/server.go + handlers in api/cdap_handlers.go) exposing REST endpoints for status, device list, info, manifest, state and sending commands. Enhance peer handling: CDAP-connected overlay in peer list/get, device revocation/cascade support in handleDeletePeer (blocklist, connection teardown, events + audit), and new audit action ActionPeerRevoked. Frontend updates include CDAP device page, widgets, commands, styles and services; major devices page UI redesign (responsive folder chips, toolbar, slim table, kebab menu) plus related CSS/JS/views, translations, docs and assets. Overall adds CDAP features, revocation workflow, and a responsive devices UI.
Security hardening and installer fixes across the Go API, installers and Node console.
Key changes:
- WebSocket: removed InsecureSkipVerify and added API_WS_ALLOWED_ORIGINS allowlist (parsed in config) used by the API events WS endpoint.
- Node.js console: added HOST and API_HOST envs and used apiHost in the server; docker-compose and installer templates updated accordingly.
- Admin credentials: plaintext .admin_credentials persistence is now opt-in via STORE_ADMIN_CREDENTIALS (default false); installers and reset flows no longer persist creds unless explicitly enabled.
- Installer hardening: added sql_escape_literal for safe SQL literals, PostgreSQL identifier validation, and safer CREATE/ALTER/psql invocations; API key and password updates now pass secrets via environment variables to Python/Node fallbacks to avoid unsafe shell interpolation.
- Docker compose/scripts: preserve_compose_database_config to keep DB mode during regen, escaped API key insertion into sqlite, and various compose generation formatting fixes.
- Go toolchain & checks: go.mod toolchain set to go1.26.1 and installers now reject known-vulnerable Go 1.26.0 stdlib.
- Dependency: bumped web-nodejs tar override to ^7.5.11.
These changes reduce attack surface for cross-origin WS usage, eliminate unsafe credential persistence by default, and harden installer DB operations and password reset paths.
Replace AGPL-3.0 with Apache License 2.0 across the repository and update related documentation and metadata. Remove legacy RustDesk-specific architecture docs, delete deprecated Dockerfile.hbbr, rename Dockerfile.hbbs → Dockerfile.server and update docker-compose / install scripts to use it. Add Apache license headers to protobuf defs, remove obsolete web service (hbbsApi.js), and adjust README, CONTRIBUTING and PROJECT_STRUCTURE to reflect the license and commercial/clean-room notices. Includes a small formatting tweak in client_api_handlers.go.
Ensure freshly generated admin passwords are actually applied on reinstall and make CSRF handling more robust. Install scripts (Docker, POSH, sh) now remove stale auth.db from the console_data/data volume or data dir and create a .force_password_update sentinel (Docker also sets FORCE_PASSWORD_UPDATE=true) so the Node.js console will force-update the admin password. web-nodejs/services/authService.js adds checkForcePasswordUpdate() (env var or sentinel) and will forcibly update the admin bcrypt hash when requested; sentinel files are removed after detection. CSRF middleware now only generates tokens for safe methods (GET/HEAD/OPTIONS), avoids interfering with state-changing requests, and clears corrupt cookies using consistent options (httpOnly, sameSite: 'lax', secure based on config) to prevent spurious 403s. server.js mounts rustdeskApiRoutes before CSRF so bearer-token desktop clients are not blocked by cookie-based CSRF. Also unified the health check path from /api/health to /health in diagnostics checks and added required fs/path imports.
Co-Authored-By: MrBrodacz - Design <215021251+MrBrodacz2025@users.noreply.github.com>
Co-Authored-By: boruto79 <176351662+boruto79@users.noreply.github.com>
Make TCP and WebSocket signal handling consistent with UDP by sending immediate PunchHoleResponse/RelayResponse (including signed PK, socket_addr, relay server and NAT type) to initiators; add ForceRelay/AlwaysUseRelay handling and ensure WS uses TCP handler. Sign peer PKs for E2E verification and keep TCP keep-alive behavior for later updates.
Refactor web-nodejs branding and backup/database code: introduce async branding cache (loadBranding) and async save/reset/import APIs, add branding_config table and DB adapter methods (SQLite/Postgres) plus backup helper methods (getAllUsersForBackup, getAllAddressBooks, restoreUsers, getBackupStats). Update routes/services to use new async DB APIs, warm branding cache at server startup, and adjust heartbeat/register flows to use db helpers. Minor server error page i18n fallbacks and hbbs backend compatibility guard updated.
Also update docs (.github/copilot-instructions.md) to record the TCP signaling fix and Phase 7 resolution.
Co-Authored-By: Charles Olivier Savignac <1275666+sircharlo@users.noreply.github.com>
Convert many Express route handlers and helper functions to async and await database calls (e.g. getAccessToken, touchAccessToken, getPeerById, getDevice, getPeerSysinfo, upsertPeerSysinfo, logAction, insertAudit*, getAll*/count* etc.). Also made identifyDevice and several route callbacks async, adjusted session.regenerate callback to use async logging, and replaced db.getDatabase() usage with db.getDb() where applicable. These changes ensure DB operations complete before responding and reduce race conditions/unhandled-promise behavior across numerous route files (activity, auth, automation, bd-api, devices, folders, i18n, inventory, registration, remote, rustdesk-api, and related route handlers).
Co-Authored-By: Charles Olivier Savignac <1275666+sircharlo@users.noreply.github.com>