- Add menu option T (Toggle HTTP/HTTPS) to betterdesk.sh and betterdesk.ps1
- Add --protocol http|https CLI flag (bash) and -Protocol param (PS1)
- Toggle updates .env, systemd/NSSM services, and Go server TLS flags
- Auto-generate self-signed cert when switching to HTTPS if none exists
- Go API (:21114) always stays HTTP (internal Node.js<->Go communication)
- Fix betterdeskApi.js: conditional httpsAgent/httpAgent based on URL scheme
- Fix deviceStatusPush.js: TLS options only applied for wss:// connections
This commit was made possible thanks to Insolve.
- Updated Polish and Chinese language files to reflect changes in update descriptions and confirmations.
- Modified settings.js to automatically include server updates in the update process.
- Simplified the update installation API to automatically handle server updates without user intervention.
- Improved updateService.js to ensure all supported components are updated together, enhancing reliability.
- Added logic to check and install the Go toolchain as needed during updates, ensuring compatibility.
- Enhanced error handling and logging during the update process for better visibility of issues.
- Added user group membership functionality, allowing users to be assigned to groups.
- Introduced validation for group GUIDs and enhanced error handling in user routes.
- Updated device group routes to support allowed user groups, enabling better access control for devices.
- Enhanced database schema to include user group memberships and device group user group access.
- Updated services and database adapters to handle user group data and relationships.
- Modified front-end views to display and manage user groups effectively.
- Added tests to ensure proper functionality of user group assignments and device access control.
- 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>
Render language choices dynamically from loaded locale files instead of hardcoding EN/PL. Add selectors on the navbar, login screen, and desktop login screen so users can choose a language before or after authentication.
Persist the selected language in the browser via cookie/localStorage and on authenticated accounts via users.preferred_language. Merge client translations with the default locale fallback so incomplete language files do not surface raw keys in the UI.
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>
Three independent bug fixes bundled together; none of the issues are
auto-closed by this commit so the reporters can confirm on a tagged build.
#121 — NAT hairpin: same-public-IP detection forces relay path
The signal handler now distinguishes 'same /24 private subnet' (genuine
LAN, keep direct path) from 'same public IP' (NAT hairpin scenario).
When both peers register from the same public IP, both the UDP and
TCP/WS punch-hole handlers skip the LAN-address exchange and steer the
client straight to the relay — matching upstream RustDesk behavior.
Most consumer routers and cellular gateways drop hairpinned UDP, which
was causing same-Wi-Fi connections to silently time out.
- new helper isSamePublicIP() in signal/handler.go
- new config flag SameNATRelay (default: enabled)
- env: SAME_NAT_RELAY=N to opt out
- cli: --same-nat-relay=false to opt out
Reported-by: @eternalliving (#121)
#122 — Rate limit configurable, 0 disables
The 20 registrations/min/IP cap was unworkable for any deployment with
real NAT/CGNAT in front of it. Made it tunable without recompiling and
hardened the limiter to short-circuit when disabled.
- new config field SignalRateLimitPerIP (default: 20, unchanged)
- env: SIGNAL_RATE_LIMIT_PER_IP=<n> (0 = unlimited)
- cli: --signal-rate-limit-per-ip=<n>
- ratelimit.IPLimiter.Allow() now returns true early when limit<=0
Reported-by: @Henry-739 (#122)
#123 — Updater corrupting live SQLite WAL files
A previous gitleaks-fix commit accidentally tracked live SQLite sidecar
files (auth.db-shm/wal, betterdesk.db-shm/wal, .session_secret,
.update_sha). The in-app updater's diff-against-GitHub logic then
'restored' those tracked-by-mistake files on user installs, which is
exactly how SQLite database corruption gets manufactured.
Layered defense:
- .gitignore now covers *.db-shm, *.db-wal, *.sqlite3-{shm,wal,journal},
web-nodejs/data/, .session_secret, .update_sha, .api_key,
.admin_credentials, .force_password_update, .env*
- removed the offending files from the index (data/.gitkeep retained)
- updateService.js EXCLUDE_PATTERNS extended to match the new gitignore
- new write-time guard isProtectedRuntimePath() wired into all four
write sites in updateService.js so even a stale GitHub diff cannot
overwrite a runtime state file on disk
Reported-by: @SterlynKong (#123)
- 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.
- updateService: enhanced checkGoAvailable() to scan well-known paths
(/usr/local/go, /snap, vendored data/go-toolchain, /usr/lib/go-1.x)
and return absolute binary path so spawned exec works without PATH.
- New installGoToolchain(): dynamically fetches go.dev/dl/?mode=json,
picks newest stable >= 1.23.0 for current OS/arch, downloads archive,
verifies SHA-256 from manifest, extracts to data/go-toolchain/.
- buildGoServer() now uses absolute go path, 600s timeout.
- New 'install-go' update strategy + auto-fallback in 'auto' mode:
when host has neither Go nor a prebuilt release, the toolchain is
installed automatically and compilation proceeds.
- New POST /api/settings/updates/install-go endpoint for explicit
install (audit-logged, server.config permission gated).
- Settings UI: third 'Auto-install Go and compile' radio. Update
checkbox is no longer disabled when Go is missing — auto-install
is always offered as a fallback.
- installUpdate() rewritten as Modal-based phased dialog:
Confirmation -> Backup -> Console -> Server -> Restart -> Done.
Live phase icons (pending/active/done/error/skipped), progress bar,
log pane, completion modal with reload CTA, auto-reload after
successful console restart.
- New i18n keys (EN+PL): strategy_install_go, auto_strategy,
toolchain_*, modal_*, phase_*, confirm_*, etc.
- New CSS (.update-progress-modal, .update-phase, .update-progress-log).
Expose an update strategy UI and support downloading pre-built server binaries as an alternative to compiling from source.
- Add new translation keys (en/pl/zh) for strategy labels, badges, download/build messages and install Go hint.
- Update settings UI: show strategy selection (download / compile), badges with availability/release/size, auto-select best strategy, and adjust status/info messages and progress text.
- settings.routes: make server-info handler async and include prebuilt info; accept serverStrategy in updates/install request and forward to updateService.
- updateService: add helpers getReleaseBinaryName, checkPrebuiltAvailable, downloadPrebuiltBinary and getPrebuiltInfo; extend getServerUpdateInfo to include expected binary/platform/arch. Implement server update flow to support compile or download strategies (auto fallback), download/prep binary, validate size, deploy binary, and record method/size in results.
This enables faster updates on platforms with prebuilt releases while preserving the compile-from-source path and providing clear UI feedback and fallbacks.
Add OS-level admin detection and use it to gate sensitive agent UI and tray actions. Introduce privileges.rs (Windows TokenElevation / Unix geteuid) and expose is_os_admin as a Tauri command; wire it into tray setup to hide admin-only menu items (Settings, Quit) and re-check privileges before executing those actions. Add show_window helper and emit navigate events from the tray; frontend listens for navigate and conditionally renders /settings (shows AdminRequired component for non-admins). Update App.tsx to query is_os_admin on startup and include navigation listener; add AdminRequired component, styles, and i18n keys. Update Cargo.toml with platform deps (windows features + libc for unix). Also add UI/locale assets and CSS for agent lazy-loaded device tabs and a notifications dropdown, plus several web-nodejs route/view/style updates and new task docs describing phase work.
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.
Enable optional compilation and deployment of the Go server as part of the self-update flow. UI: add checkbox/status/info area in settings.js, check /api/settings/updates/server-info, include server component when selected, adjust progress/messages and longer timeouts. API/Server: add server-info endpoint and extend install request timeouts. Service: updateService now sets server localRoot and implements functions to detect Go, fetch server source (git or GitHub API), build the binary, and deploy it. i18n: add related translation keys across many locale files. Misc: improve input validation and error logging in desktop.routes, and return graceful defaults for missing policy routes in policies.routes.
Add warnings for TLS API misconfiguration and enrollment restrictions. The Go server now logs a clear warning when TLS on the API port is enabled (explaining it breaks HTTP consumers and how to fix) and logs active enrollment restriction when restored from DB. The Node.js API client (betterdeskApi.js) and event bus handler (deviceStatusPush.js) now detect TLS/HTTP mismatches and surface actionable console/error messages to help operators debug the issue (references issue #104). Files changed: betterdesk-server/main.go, web-nodejs/services/betterdeskApi.js, web-nodejs/services/deviceStatusPush.js.
Several cross-cutting fixes and refactors:
- API routing: Consolidated multiple org policy PUT endpoints into a single parameterized route (/api/org/{id}/policy/{category}) to simplify handlers (api/server.go).
- Relay/LAN handling: Prefer server LAN IP for LAN relay addresses (with proper port detection from configured relay), added strconv import and fallback to configured relay when LAN IP unknown; improves reliability with NAT hairpin issues (signal/handler.go).
- Web security: Allow inline event handlers (scriptSrcAttr: 'unsafe-inline') while still requiring nonced <script> tags for scripts used by admin pages (web-nodejs/middleware/security.js).
- CSRF: Include x-csrf-token header when POSTing language fix requests from the UI (web-nodejs/public/js/languages.js).
- Admin roles: Broaden admin checks to accept multiple admin role names via ADMIN_ROLES and update requireAdmin and RustDesk payload is_admin logic (web-nodejs/routes/rustdesk-api.routes.js).
- Admin credentials & startup resilience: authService now searches additional candidate dirs (config.dataDir, extra Windows/RustDesk paths, /app/data in Docker), skips empty candidates, and increases retries/delays when waiting for .admin_credentials (web-nodejs/services/authService.js).
- Chat API paths: Updated chat-related API calls to use /chat/* (instead of /api/chat/*) across persistence, history, contacts, groups, read and other operations (web-nodejs/services/chatRelay.js).
These changes improve compatibility (LAN relay, admin detection), robustness (longer retries, Docker/Windows path checks), and frontend behavior (CSRF token, inline handlers, updated chat endpoints).
DB: Use current_schema() when checking columns for deferred index creation and add exception handling to skip index creation if column is absent (avoids cross-schema false positives and race errors).
Signal: Harden isSameNetwork by normalizing IPv4, handling mapped addresses, adding detailed debug logs for loopback/private/subnet checks, and logging LAN detection failures in the RequestRelay handler.
Auth/API: Add tighter debug logging and trimming for /api/login (redacting passwords), and reject empty/invalid usernames early in authenticate() to address Issue #104.
UI: Add save button feedback (spinner, disable/restore), extra logging and error handling when saving org settings, and make logo image URL input editable by removing readonly.
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.
- Fix critical SQLite migration bug: auth.db column migrations (last_login,
totp_*, settings.updated_at) were in ensureInventoryTables() which receives
main DB handle — PRAGMA table_info(users) returned empty on main DB, so
ALTER TABLE never executed. Moved to ensureAuthTables() (auth DB handle).
- Add migration logging (console.log for each added column)
- Add branding_config.updated_at migration
- Fix bd-api.routes.js: session cookie fallback auth for desktop client
- Fix auth.routes.js: rate limiter improvements
- MGMT client: add logging module, improve auth store with TOTP + token
acquisition, enhance RemoteView with session logging, improve relay
connection handling in bd_relay.rs
- ensureDefaultAdmin() now reads Go server's .admin_credentials file as
fallback when DEFAULT_ADMIN_PASSWORD env var is not set
- Searches multiple candidate dirs: keysPath, keysPath/data, /opt/betterdesk,
/opt/betterdesk/data, /opt/rustdesk, /opt/rustdesk/data
- Parses 'Admin Password: <value>' line from the file
- Fixes password mismatch on manual installs without ALL-IN-ONE scripts
- Existing installs with .env DEFAULT_ADMIN_PASSWORD are unaffected (env wins)
- Replace release-based check (always 404) with commit-SHA tracking
- Track deployed state via data/.update_sha file
- Detect changes across all components (console, server, agent, scripts)
- Show recent commits, component breakdown, and file counts
- Auto-update console + script files, manual badge for Go server
- Pre-update backup with SHA-tracked restore
- Support npm install when package.json changes
- Service restart for console (auto) and Go server (on demand)
- 15 new i18n keys in EN/PL/ZH for update UI
- CSS for commit list, component rows, rebuild warning
- Change default GITHUB_REPO from 'Rustdesk-FreeConsole' to 'BetterDesk'
(repo was renamed, causing 404 on releases/latest API call)
- Handle 404 gracefully when no GitHub releases exist yet: return
'up to date' response instead of throwing error
- Add 'updateAvailable' and 'releaseNotes' fields to response object
(frontend settings.js expects these field names)
- users.js: Change parseInt(userId, 10) to Number() on both sides of
comparison to handle BigInt/string/number ID types correctly
- dbAdapter.js: Wrap all lastInsertRowid with Number() to prevent
BigInt leak from better-sqlite3 v9+ (BigInt === Number is always false)
Root cause: better-sqlite3 v9+ returns lastInsertRowid as BigInt.
If user objects with BigInt IDs ended up in the users array, strict
equality (===) with parseInt result (Number) always fails silently,
making edit/reset-password/delete buttons appear unresponsive.
- Add zh-TW translations for web console, agent client, and MGMT client
- Update VALID_LANG_CODE regex to support BCP 47 tags (e.g. zh-TW)
- Add zh-TW to LANGUAGE_META in i18nService
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.
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.
Update client links to open the remote-desktop UI (replace /remote/ with /remote-desktop/). In remoteRelay: transform viewer 'input' frames into the agent's expected InputEvent shape (map event_type -> type) before forwarding, and decode+validate the agent device ID on WebSocket upgrade (reject malformed IDs) to reduce path-traversal/abuse risk. In bdRelay: simplify upgrade handling so this handler only processes /ws/bd-relay and /ws/bd-signal paths and otherwise yields to other upgrade handlers, avoiding manual delegation. These changes improve compatibility, security, and routing correctness.
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.
Introduce peer metrics persistence and partial peer updates, plus relay UUID recovery and soft-delete protections.
- DB: add PeerMetric type and new Database methods (SavePeerMetric, GetPeerMetrics, GetLatestPeerMetric, CleanupOldMetrics, UpdatePeerFields, IsPeerSoftDeleted). Add peer_metrics table and indexes in SQLite and PostgreSQL migrations; implement all methods for both backends.
- API: handleClientHeartbeat now parses cpu/memory/disk and saves metrics; new endpoints PATCH /api/peers/{id} to update note/user/tags and GET /api/peers/{id}/metrics for historical metrics. handleSetPeerTags now accepts either string or array JSON payloads. Added audit.ActionPeerUpdated.
- Signal server: add pendingRelayUUIDs store (with TTL cleanup, store/get helpers) to recover missing UUIDs from old clients when RelayResponse contains empty uuid; store pending UUIDs when forwarding RequestRelay/PunchHole. Add IsPeerSoftDeleted checks to reject re-registration of soft-deleted devices.
- Node.js panel: betterdeskApi.setPeerTags now sends tags as array and exposes updatePeer() for PATCH; serverBackend.updateDevice routes note/user updates through Go PATCH endpoint and preserves local auth.db writes as fallback; devices.routes deletes now call cleanupDeletedPeerData.
- dbAdapter: add cleanupDeletedPeerData implementations for SQLite and Postgres to remove related auth.db rows when a peer is deleted.
These changes fix zombie device re-registration, ensure metrics are stored & retrievable, centralize peer metadata updates through the Go API, and recover relay pairing failures with legacy clients.
Co-Authored-By: boruto79 <176351662+boruto79@users.noreply.github.com>
Co-Authored-By: БлагоЯр <3672314+blagoyar@users.noreply.github.com>
Fix Docker single-container auth gap by ensuring an API key exists and is discoverable by both the Go server and Node.js console. Changes:
- betterdesk-server/main.go: loadAPIKey() now checks the server_config DB entry and, if absent, auto-generates a 32-byte hex API key, writes it to .api_key (with logging) and continues to sync to the DB.
- docker/entrypoint.sh: generates/persists a 32-byte hex API key at container startup (uses openssl with /dev/urandom fallback) and writes API_KEY env to file if provided.
- web-nodejs/services/betterdeskApi.js: adds fs import and an Axios 401 interceptor that reloads .api_key from disk once and retries the failed request to handle race conditions where the Go server generates the key after Node cached an empty value.
- .github/copilot-instructions.md: documents the Docker API key auto-generation (Phase 16) and related fixes.
- tasks/lessons.md and tasks/todo.md: add lightweight triage notes and actions.
This resolves the issue where the Devices page returned empty results due to missing X-API-Key in the single-container Docker setup and improves resilience during first-run key generation.
Make the installer enable and propagate HTTPS settings to the Node.js console and systemd services when self-signed TLS certs are generated. Adds Update-EnvForTLS (PowerShell) and .env updates (bash) to set HTTPS_ENABLED, SSL_CERT_PATH, SSL_KEY_PATH, NODE_EXTRA_CA_CERTS and switch local API URLs to https. Systemd unit generation and do_configure_ssl now inject/sync HTTPS and cert paths (and NODE_EXTRA_CA_CERTS for self-signed CAs). Also fix a bug in web-nodejs/dbAdapter.getPeerStats by computing the total peer count so offline is calculated correctly.
Add .dockerignore to trim Docker build context and exclude local artifacts (node_modules, dev files, secrets, runtime DBs, etc.). Simplify Dockerfiles: remove unnecessary sqlite-dev and rely on better-sqlite3's bundled SQLite; use npm install --production in build stages; copy application files first then overlay compiled node_modules from the builder to avoid local node_modules clobbering Alpine-compiled native modules. Update Docker console image similarly. Change supervisord to log to /dev/stdout and /dev/stderr so logs appear in docker logs. Remove explicit compose 'version' keys. Also set SQLite busy_timeout for main and auth DBs to reduce locking errors during concurrent access.
Convert recovery code arrays to JSON strings before storing in the database to ensure consistent storage across adapters. Updates enableTotp and useRecoveryCode in both SQLite and Postgres adapters (web-nodejs/services/dbAdapter.js) to stringify arrays while leaving existing strings untouched.
Preserve existing DB config during update/repair and add PostgreSQL compatibility and reliability fixes. Added preserve_database_config()/Preserve-DatabaseConfig and invoked them before console reinstall in betterdesk.sh and betterdesk.ps1 to avoid unintentionally switching PostgreSQL → SQLite. Fixed folder/user route responses to use result.id (Postgres-compatible) in web-nodejs routes. Added automatic TOTP column migrations for both SQLite and Postgres in web-nodejs/services/dbAdapter.js. Improved relay error logging and write-error handling in betterdesk-server/relay (server.go, ws.go). Updated docs and tooling: added SELinux troubleshooting (DOCKER_TROUBLESHOOTING.md), Windows build/usage notes for the migrate tool (README.md), and updated changelog/instructions (.github/copilot-instructions.md) and last-updated date.