RepoPilotOpen in app →

rustdesk/rustdesk-server

RustDesk Server Program

Mixed

Mixed signals — read the receipts

weakest axis
Use as dependencyConcerns

copyleft license (AGPL-3.0) — review compatibility; no tests detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 4d ago
  • 24+ active contributors
  • AGPL-3.0 licensed
Show all 7 evidence items →
  • CI configured
  • Concentrated ownership — top contributor handles 60% of recent commits
  • AGPL-3.0 is copyleft — check downstream compatibility
  • No test directory detected
What would change the summary?
  • Use as dependency ConcernsMixed if: relicense under MIT/Apache-2.0 (rare for established libs)

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/rustdesk/rustdesk-server?axis=fork)](https://repopilot.app/r/rustdesk/rustdesk-server)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/rustdesk/rustdesk-server on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: rustdesk/rustdesk-server

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/rustdesk/rustdesk-server shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Mixed signals — read the receipts

  • Last commit 4d ago
  • 24+ active contributors
  • AGPL-3.0 licensed
  • CI configured
  • ⚠ Concentrated ownership — top contributor handles 60% of recent commits
  • ⚠ AGPL-3.0 is copyleft — check downstream compatibility
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live rustdesk/rustdesk-server repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/rustdesk/rustdesk-server.

What it runs against: a local clone of rustdesk/rustdesk-server — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in rustdesk/rustdesk-server | Confirms the artifact applies here, not a fork | | 2 | License is still AGPL-3.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 34 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>rustdesk/rustdesk-server</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of rustdesk/rustdesk-server. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/rustdesk/rustdesk-server.git
#   cd rustdesk-server
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of rustdesk/rustdesk-server and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "rustdesk/rustdesk-server(\\.git)?\\b" \\
  && ok "origin remote is rustdesk/rustdesk-server" \\
  || miss "origin remote is not rustdesk/rustdesk-server (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(AGPL-3\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"AGPL-3\\.0\"" package.json 2>/dev/null) \\
  && ok "license is AGPL-3.0" \\
  || miss "license drift — was AGPL-3.0 at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "src/main.rs" \\
  && ok "src/main.rs" \\
  || miss "missing critical file: src/main.rs"
test -f "src/hbbr.rs" \\
  && ok "src/hbbr.rs" \\
  || miss "missing critical file: src/hbbr.rs"
test -f "src/rendezvous_server.rs" \\
  && ok "src/rendezvous_server.rs" \\
  || miss "missing critical file: src/rendezvous_server.rs"
test -f "src/relay_server.rs" \\
  && ok "src/relay_server.rs" \\
  || miss "missing critical file: src/relay_server.rs"
test -f "src/database.rs" \\
  && ok "src/database.rs" \\
  || miss "missing critical file: src/database.rs"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 34 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~4d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/rustdesk/rustdesk-server"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

RustDesk Server is a self-hosted remote desktop relay and rendezvous infrastructure written in Rust. It provides the backend components (hbbs for ID/rendezvous, hbbr for relay) that enable peer-to-peer remote desktop connections without relying on centralized cloud services, solving the problem of secure, private remote access for organizations that need to control their own infrastructure. Monorepo structure with three binary targets defined in Cargo.toml: hbbs (src/hbbs.rs main), hbbr (src/hbbr.rs relay), and rustdesk-utils (src/utils.rs CLI). External dependency on libs/hbb_common shared library. Deployment via Docker (docker/, docker-classic/) with s6 supervision, Debian packages (debian/), and NSIS installers for Windows. Database state persists via SQLite (db_v2.sqlite3).

👥Who it's for

Systems administrators and DevOps engineers deploying self-hosted remote desktop infrastructure, as well as RustDesk client developers who need a custom server backend. Contributors are primarily Rust backend engineers building or extending the relay and rendezvous protocol implementations.

🌱Maturity & risk

Production-ready and actively maintained. The project has structured releases (v1.1.15 visible in Cargo.toml), comprehensive Docker/Debian packaging, CI/CD via GitHub Actions (build.yaml), and documented deployment paths. However, the codebase shows this is a mature OSS project rather than a startup—stable enough for self-hosting but with ongoing feature development (Pro variant exists).

Moderate risk: the monolithic Cargo.toml pulls 20+ external dependencies including cryptographic libraries (sodiumoxide, jsonwebtoken, bcrypt), async runtime (tokio via axum), and database layers (sqlx with SQLite). The dependency on a git fork of reqwest (rustdesk-org/reqwest) for TLS handling is a custom patch point that could diverge. No test directory visible in the file structure suggests limited automated test coverage.

Active areas of work

Active development visible through versioned releases and multi-platform CI workflows. The presence of docker/ with s6-overlay and health checks, plus Debian post-install scripts (postinst, postrm, prerm), indicates ongoing DevOps maturity. The migration docs reference Pro variant, suggesting commercial feature parity as an active concern.

🚀Get running

git clone https://github.com/rustdesk/rustdesk-server.git
cd rustdesk-server
cargo build --release

Three executables appear in target/release/. Alternatively, use Docker: docker-compose up (docker-compose.yml present). For Debian: follow debian/README.source.

Daily commands:

cargo build --release
./target/release/hbbs  # ID/rendezvous server
./target/release/hbbr  # Relay server (separate terminal)

Or via Docker: docker-compose up. Configuration likely via .env file and CLI flags—check hbbs --help and hbbr --help. Requires network access for peer discovery and relay traffic.

🗺️Map of the codebase

  • src/main.rs — Entry point for hbbs (ID/Rendezvous server); defines the primary server initialization and main loop logic.
  • src/hbbr.rs — Entry point for hbbr (relay server); implements the relay server binary and connection handling.
  • src/rendezvous_server.rs — Core rendezvous server implementation handling peer registration, discovery, and ID management.
  • src/relay_server.rs — Core relay server implementation managing peer-to-peer relay connections and packet forwarding.
  • src/database.rs — Database layer providing SQLite schema and persistence for server state; critical for data integrity.
  • Cargo.toml — Defines all dependencies (axum, sqlx, tokio, serde) and project metadata; changes here affect the entire build.
  • src/lib.rs — Library interface exposing shared modules and public APIs for both hbbs and hbbr binaries.

🛠️How to make changes

Add a New Server Configuration Option

  1. Define the new config field in the config struct within src/common.rs (src/common.rs)
  2. Parse the configuration option from CLI arguments in src/main.rs (for hbbs) or src/hbbr.rs (for hbbr) (src/main.rs)
  3. Update the .env file with the new default value (.env)
  4. If persisting to database, add migration in src/database.rs and update the schema (src/database.rs)

Add a New Peer Message Handler

  1. Define the message type in src/peer.rs (add variant to enum) (src/peer.rs)
  2. Implement the message handler logic in src/rendezvous_server.rs or src/relay_server.rs depending on server type (src/rendezvous_server.rs)
  3. Update the message dispatch/routing logic to call your new handler (src/rendezvous_server.rs)
  4. Add any required database updates in src/database.rs if state persistence is needed (src/database.rs)

Add a New Web UI Management Endpoint

  1. Define the HTTP route handler in src/main.rs or src/hbbr.rs (using axum framework) (src/main.rs)
  2. Implement the route logic using axum extractors and responders (src/main.rs)
  3. Add the route to the axum Router in the server setup (src/main.rs)
  4. Create the corresponding JavaScript handler in ui/html/main.js to call the endpoint (ui/html/main.js)

Add Database Migration

  1. Create a new migration function in src/database.rs following sqlx naming conventions (src/database.rs)
  2. Update the migration runner to execute your new migration during server startup (src/database.rs)
  3. Update src/common.rs or relevant data structure files to reflect the new schema (src/common.rs)

🔧Why these technologies

  • Axum (async web framework) — Provides high-performance async HTTP handling for management APIs and relay protocol multiplexing; integrates seamlessly with tokio runtime.
  • SQLx + SQLite — Compile-time query verification prevents SQL injection; SQLite is embedded, eliminating external DB dependency; sufficient for peer registry and audit logs at scale <100k concurrent peers.
  • Tokio (async runtime) — Enables handling thousands of concurrent peer connections efficiently; necessary for managing multiple relay sessions and rendezvous protocol concurrency.
  • Serde (serialization) — Efficient JSON/binary serialization for peer messages and API responses; derives reduce boilerplate for config and state structs.
  • Docker + s6-overlay — s6 provides robust process supervision for running hbbs and hbbr together; enables graceful shutdown and restart without losing in-flight relay connections.

⚖️Trade-offs already made

  • Single SQLite database vs. distributed database

    • Why: Simplifies deployment (no external DB setup); avoids network latency for lookups.
    • Consequence: Scales to ~100k concurrent peers per instance; requires clustering/sharding for enterprise multi-region deployments; single disk I/O bottleneck for high-volume logging.
  • In-process relay vs. separate relay cluster

    • Why: Reduces operational complexity; relay logic stays close to registration state.
    • Consequence: hbbr instances cannot easily share relay load; each hbbr runs independently; horizontal scaling requires DNS/load-balancer round-robin.
  • Axum for both API and relay protocol

    • Why: Reuses async infrastructure; simplifies deployment (single port for management + relay).
    • Consequence: Mixes concerns (HTTP API + binary protocol); relay protocol must be manually framed over HTTP or raw TCP; complicates protocol versioning.
  • SQLite over PostgreSQL/MySQL

    • Why: Zero external dependencies; self-hosted deployments have lower operational burden.
    • Consequence: Not suitable for multi-instance write coordination; requires application-level consistency; limited concurrent write throughput (~100 writes/sec).

🚫Non-goals (don't propose these)

  • Real-time streaming media codec (relay only forwards encrypted packets; video/audio codec is in client)
  • Built-in TLS/encryption (relies on clients to encrypt; hbbr is transparent byte forwarder)
  • Multi-region data replication (each hbbs/hbbr is independent; no federation protocol)
  • User authentication/authorization (no user database; identification is by peer ID only)
  • Load balancing or failover (must be managed extern

🪤Traps & gotchas

Dependency on git fork: reqwest is pulled from rustdesk-org/reqwest instead of upstream, with platform-specific TLS backends (native-tls vs rustls-tls)—updates may lag. Database assumption: SQLite path hardcoded; migration scripts may not exist in repo despite db_v2.sqlite3 version suffix. Network binding: hbbs and hbbr must listen on different ports (typically 21115, 21116, 21117)—default config not visible, may require env vars or CLI args. Cryptographic keys: sodiumoxide generates keys; initial key setup ritual unknown from file list—check docs. Async runtime: Tokio is implicit through axum/sqlx; blocking I/O will panic. s6-overlay in Docker: health checks and supervision are delegated to s6, not Rust—debug must account for this. No lock file committed: Cargo.lock is gitignored by default, reproducibility depends on registry snapshot.

🏗️Architecture

💡Concepts to learn

  • Rendezvous protocol — hbbs implements the rendezvous role—helping two peers discover and negotiate connection parameters before relay; core to RustDesk's NAT traversal
  • Relay architecture (data plane) — hbbr acts as a transparent L4 relay, forwarding encrypted traffic between peers when P2P is impossible; understanding packet buffering and bidir streams is critical
  • Curve25519 key exchange — sodiumoxide library implements Curve25519 for ECDH key negotiation; contributors modifying auth flow must understand elliptic curve cryptography
  • WebSocket for real-time signaling — tokio-tungstenite provides WebSocket server for control messages (registration, heartbeat, relay negotiation); critical for connection state management
  • Connection pooling with deadpool — sqlx uses deadpool to manage SQLite connections in async context; understanding pool exhaustion and timeout tuning is essential for production deployments
  • s6 service supervision — Docker image uses s6-overlay for process supervision and logging—hbbs and hbbr are managed as s6 services, not raw PID 1
  • NAT traversal / hole punching — Rendezvous + relay architecture together solve NAT traversal; understanding STUN, connection type detection, and fallback to relay is implicit in the design
  • rustdesk/rustdesk — The client application that connects to this server—understanding the wire protocol and feature set requires reading the client's network code
  • rustdesk/rustdesk-server-pro — Commercial variant with additional features (admin dashboard, LDAP, 2FA, etc.)—shows reference implementation for enterprise extensions
  • rustdesk/rustdesk-server-demo — Simpler starter codebase for custom server implementations—useful for learning the protocol without the full production complexity
  • rustdesk/hbb_common — Extracted as a separate crate in practice; contains serialization, crypto, and protocol definitions shared with the client
  • open-trade/async-speed-limit — Dependency (via git) for rate-limiting relay traffic—understanding bandwidth throttling requires this crate's token bucket algorithm

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add integration tests for database operations in src/database.rs

The repo uses sqlx with SQLite (db_v2.sqlite3) but there are no visible test files for database layer. Integration tests would validate schema migrations, connection pooling via deadpool, and CRUD operations for core entities (users, devices, sessions). This is critical for a server that relies heavily on database integrity.

  • [ ] Create tests/integration/database.rs with test fixtures using sqlx::test macro
  • [ ] Test connection pool initialization with deadpool configuration
  • [ ] Add tests for common queries referenced in src/database.rs and src/hbbr.rs
  • [ ] Update Cargo.toml with dev-dependencies: sqlx with sqlite feature and test-case for parametrized tests
  • [ ] Document test database setup in README or CONTRIBUTING guide

Add GitHub Actions workflow for security audit and dependency scanning

The repo has .github/workflows/build.yaml but no security-focused CI. Given the security-critical nature of RustDesk (relay server, ID server, encrypted connections), adding cargo-audit and dependabot alerts validation would catch vulnerabilities in dependencies like sodiumoxide, bcrypt, and jsonwebtoken before release.

  • [ ] Create .github/workflows/security.yaml with cargo-audit job
  • [ ] Add job to validate Dependabot alerts are resolved (check .github/dependabot.yml exists)
  • [ ] Include cargo-deny for license compliance checks (relevant for GPL/Apache mixed dependencies)
  • [ ] Run on: pull_request and schedule (weekly) for continuous monitoring
  • [ ] Add badges to README.md for security scan status

Extract platform-specific TLS configuration into dedicated modules

Cargo.toml has duplicated conditional dependency logic for reqwest (native-tls on macOS/Windows vs rustls on Linux). This creates maintenance burden and potential for drift. Extracting into src/http.rs or src/tls.rs module would centralize TLS strategy, improve testability, and make platform requirements explicit.

  • [ ] Create src/http.rs module with platform-conditional HTTP client initialization
  • [ ] Move reqwest configuration from Cargo.toml conditionals into runtime/compile-time feature flags
  • [ ] Update Cargo.toml to reference new features (e.g., tls-native, tls-rustls)
  • [ ] Add documentation comments explaining why different TLS backends are used per platform
  • [ ] Add unit tests in src/http.rs to verify correct client is initialized per target_os

🌿Good first issues

  • Add unit tests for relay packet handling in src/hbbr.rs—currently no tests/ directory visible; test a few protocol message types (e.g., ping, data forward, connection close) to improve confidence in relay logic.
  • Document the exact database schema and migration path for db_v2.sqlite3—add a SQL schema dump or migration .sql files to docs/ so contributors understand the peer registration and relay stats tables without reverse-engineering.
  • Implement a simple CLI for key generation and initial setup (rustdesk-utils expansion)—add subcommands like rustdesk-utils genkey and rustdesk-utils init-server so new self-hosters don't need to hand-craft config files.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 815c728 — fix(security): update mio from 0.8.5 to 0.8.11 (#633) (WC3D)
  • bd7bc52 — Update build.yaml (rustdesk)
  • 34cbd57 — bump version (rustdesk)
  • 46e9ecd — fix pr (rustdesk)
  • d0770e6 — high rustc (rustdesk)
  • f87372e — GHCR manifest (rustdesk)
  • 04efb70 — Update README.md (rustdesk)
  • 9bae9f2 — Update build.yaml (rustdesk)
  • 7c2057c — remove annoying fmt check (rustdesk)
  • f61b31f — 1.1.15 debain log (rustdesk)

🔒Security observations

  • High · Outdated and Vulnerable Dependencies — Cargo.toml - dependencies section. Multiple dependencies are pinned to outdated versions with known vulnerabilities. Notable issues include: clap v2 (EOL since 2021), lazy_static (superseded by once_cell which is already in use), tokio-tungstenite v0.17 and tungstenite v0.17 (outdated WebSocket libraries), and axum v0.5 (deprecated in favor of v0.7+). These versions have known CVEs and security patches. Fix: Update all dependencies to their latest stable versions. Specifically: upgrade clap to v4.x, remove lazy_static in favor of once_cell, upgrade tokio-tungstenite and tungstenite to v0.20+, and upgrade axum to v0.7+. Run 'cargo audit' to identify specific CVEs.
  • High · Use of Custom Git Forks for Critical Dependencies — Cargo.toml - reqwest dependency (both platform-specific variants). The project uses a custom fork of reqwest from 'https://github.com/rustdesk-org/reqwest' instead of the official crate. This custom fork may lag behind security updates from the official repository and increases maintenance burden. It's unclear what modifications are made in this fork. Fix: Migrate back to the official reqwest crate (https://crates.io/crates/reqwest) unless there are specific, documented reasons for the fork. If modifications are necessary, maintain a public fork with clear documentation of changes and ensure it receives timely security updates.
  • High · Exposed Sensitive Ports in Docker Configuration — docker-compose.yml - ports configuration. The docker-compose.yml exposes multiple ports without authentication or rate limiting. Ports 21115-21118 for hbbs and 21117, 21119 for hbbr are publicly accessible. The hardcoded relay server address 'rustdesk.example.com' should be parameterized. Fix: Implement network segmentation using firewall rules or reverse proxy authentication. Consider exposing only necessary ports, implement rate limiting and DDoS protection, and externalize the relay server configuration using environment variables instead of hardcoded values.
  • High · Shared Data Volume Between Services Without Isolation — docker-compose.yml - volumes configuration for both hbbs and hbbr. Both hbbs and hbbr containers share the same volume mounted at '/root' (mapped to ./data) with no explicit access controls or permission restrictions. This could allow privilege escalation or lateral movement between services. Fix: Use separate volumes for each service or implement proper file permission restrictions (chmod, chown). Use named volumes with explicit access controls rather than bind mounts to ./data. Implement read-only mounts where applicable.
  • High · Use of Outdated Cryptographic Library — Cargo.toml - sodiumoxide dependency. The project uses sodiumoxide v0.2, which has not been actively maintained since 2019. Newer versions like libsodium-sys or sodium-oxide may have better security support. This is a foundational cryptographic library used for sensitive operations. Fix: Evaluate migration to maintained alternatives such as the latest version of sodium oxide or consider using the rust-crypto ecosystem (blake2, chacha20poly1305, ed25519-dalek). Verify that all cryptographic operations are correctly implemented.
  • Medium · Potential SQL Injection via SQLx without Parameterization Verification — src/database.rs - sqlx query execution. The project uses sqlx with macros for compile-time query verification, which is good. However, without examining the actual query code in database.rs and other files, there's a risk of raw SQL query construction elsewhere in the codebase. The macro feature alone doesn't guarantee all queries are protected. Fix: Audit all SQL queries to ensure parameterized queries are used exclusively. Verify that user input is never directly interpolated into SQL strings. Use sqlx macros (sql!, query!, etc.) consistently throughout the codebase. Run static analysis tools like cargo-sqlx-cli for compile-time verification.
  • Medium · Missing HTTPS/TLS Configuration in Docker — docker-compose.yml and docker/. The docker-compose configuration shows no explicit TLS/HTTPS setup. The services expose ports for relay operations without visible TLS termination or certificate management in the provided configuration. Fix: undefined

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · rustdesk/rustdesk-server — RepoPilot