13 KiB
Configuration & Environment Variables
This document is the single reference for every option that the open‑source
RustDesk server binaries (hbbs, hbbr) understand: command‑line flags,
environment variables, and configuration files.
TL;DR — For most people the command‑line flags shown by
hbbs --help/hbbr --helpare all you need. Environment variables are an alternative way to set the same options, plus a handful of extra tuning knobs that have no flag.
How configuration is loaded
Both servers read their configuration from the following sources. For
hbbs the order of precedence, from highest to lowest, is:
- Command‑line flag (e.g.
-p 21116,-k mykey) --config <file>— an INI file passed with-c/--config.env— an INI file named.envin the working directory- Inherited process environment — variables exported before launch
A value set by a higher source overrides the same value from a lower one. Under the hood every source is turned into a process environment variable, and the code then reads that variable — so "flag", "config file" and "env var" are just three ways to set the same thing.
For hbbr the precedence is: flag (-p, -k) → .env →
inherited environment.
RUST_LOG is an exception to these rules. Both binaries initialize logging
before loading .env (or hbbs's --config file), so RUST_LOG must be set
in the inherited process environment.
⚠️ The .env naming gotcha (read this)
hbbs and hbbr do not parse .env the same way:
Key written in .env |
Variable the code sees | |
|---|---|---|
hbbs |
relay_servers or relay-servers |
RELAY-SERVERS (upper‑cased, _→-) |
hbbr |
downgrade_threshold |
DOWNGRADE_THRESHOLD (used verbatim) |
hbbsrewrites every.env/--configkey to UPPERCASE and replaces underscores with dashes. So a key with an underscore in.env(for exampleDB_URLorTEST_HBBS) becomesDB-URL/TEST-HBBSand will not match theDB_URL/TEST_HBBSthe code looks for. Those "direct" variables (marked 🅴 in the tables below) can therefore only be set as a real environment variable, not through thehbbs.env/--configfile.hbbruses.envkeys verbatim, so names must match the documented uppercase spelling exactly. This works for variables read after.envis loaded;RUST_LOGis the exception described above.
Recommendation:
- Set multi-word
hbbsflag options via the command line or the.envfile (using the dashed lowercase name, e.g.relay-servers). - In a
.envfile shared by both binaries, spell shared names such asKEYandPORTin uppercase.hbbsaccepts that spelling after normalization, andhbbrrequires it. - Set the 🅴 "direct" tuning variables as real environment variables
(docker‑compose
environment:, systemdEnvironment=, orexport).
Multi‑word options such as relay-servers have an internal env‑var name that
contains a dash (RELAY-SERVERS). Most shells cannot export RELAY-SERVERS=…,
so for those prefer the CLI flag or the .env file. Single‑word options
(PORT, KEY, MASK, SERIAL, RMEM) are ordinary identifiers and work fine
as exported environment variables.
hbbs — ID / rendezvous server
| Variable | CLI flag | Default | Description |
|---|---|---|---|
KEY |
-k, --key |
- |
Public key clients must use, a base64 secret key, or - / _ to load or generate a key pair (id_ed25519, id_ed25519.pub). Use _ to require encryption. An explicitly empty value disables key validation; see Keys. |
PORT |
-p, --port |
21116 |
Main TCP/UDP listening port. hbbs also binds PORT-1 (NAT type test) and PORT+2 (WebSocket). |
RELAY-SERVERS |
-r, --relay-servers |
(empty) | Default relay server(s) handed to clients, comma‑separated host or host:port. Usually your public IP / domain. |
RENDEZVOUS-SERVERS |
-R, --rendezvous-servers |
(empty) | Peer rendezvous servers to forward to, comma‑separated. For multi‑server setups; leave empty for a single server. |
MASK |
--mask |
(none) | CIDR that marks a client as "LAN", e.g. 192.168.0.0/16. When set, LAN peers get LOCAL-IP instead of their public address. |
LOCAL-IP |
(none — env/.env only) |
auto‑detected | LAN address advertised to peers matched by MASK. Defaults to the machine's primary local IP. |
SERIAL |
-s, --serial |
0 |
Config update serial. Bump it to push updated relay/rendezvous lists to clients. |
RMEM |
-M, --rmem |
0 (system default) |
UDP receive‑buffer size in bytes. Raise the OS limit first: sudo sysctl -w net.core.rmem_max=52428800. |
SOFTWARE-URL |
-u, --software-url |
(empty) | Download URL of the newest RustDesk client; the version is parsed from it and offered to clients. |
| (config file) | -c, --config |
(none) | Path to an extra INI config file (see precedence above). |
TEST_HBBS 🅴 |
(none) | (auto) | UDP self‑test target checked at start‑up. Set to no to skip the check (useful behind some NATs/proxies), or to an explicit host:port. |
ALWAYS_USE_RELAY 🅴 |
(none) | N |
Y forces every session through a relay (disables direct/hole‑punched connections). At runtime, send always-use-relay Y or always-use-relay N to the hbbs loopback console. |
DB_URL 🅴 |
(none) | ./db_v2.sqlite3 |
Path/URL of the SQLite database file. See Database. |
MAX_DATABASE_CONNECTIONS 🅴 |
(none) | 1 |
Size of the SQLite connection pool. |
🅴 = read directly from the environment; cannot be set through the hbbs
.env/--config file (see the gotcha above).
PORT_FOR_API/KEY_FOR_APIare only used by RustDesk Server Pro and its API; they have no effect in the open‑source server.
hbbr — relay server
| Variable | CLI flag | Default | Description |
|---|---|---|---|
KEY |
-k, --key |
(empty) | Must match the non-empty key hbbs uses. - / _ load or generate a key pair. The empty default disables key validation and leaves the relay unauthenticated; do not leave it empty on an exposed server. |
PORT |
-p, --port |
21117 |
Relay listening port. hbbr also binds PORT+2 for WebSocket relay. Note: when set via the PORT env var (not -p), hbbr listens on PORT + 1, so a shared PORT=21116 makes hbbs=21116 and hbbr=21117. |
Relay bandwidth / QoS (all 🅴, set as environment variables)
These have no CLI flag and can also be changed through the hbbr
loopback console (tb, sb, ls, dt, t, …; send h
for help).
| Variable | Default | Unit | Description |
|---|---|---|---|
SINGLE_BANDWIDTH |
128 |
Mb/s | Normal maximum bandwidth for each relay connection. |
TOTAL_BANDWIDTH |
1024 |
Mb/s | Aggregate bandwidth cap shared by all relay connections. |
LIMIT_SPEED |
32 |
Mb/s | Per-connection cap applied after a connection is downgraded, and to IPs in blacklist.txt. |
DOWNGRADE_THRESHOLD |
0.66 |
ratio (0–1) | Fraction of SINGLE_BANDWIDTH that a connection's lifetime-average throughput must exceed to trigger downgrade. |
DOWNGRADE_START_CHECK |
1800 |
seconds | Delay before a connection becomes eligible for the lifetime-average downgrade check. |
Downgrade is decided independently for each connection; it does not check
aggregate relay congestion. After DOWNGRADE_START_CHECK, a connection is
capped to LIMIT_SPEED once its average throughput since it started exceeds
SINGLE_BANDWIDTH * DOWNGRADE_THRESHOLD. A lone transfer can therefore be
downgraded even when the relay is otherwise idle. TOTAL_BANDWIDTH is a
separate aggregate cap.
hbbr reads its .env verbatim, so these may also be placed in .env
(e.g. SINGLE_BANDWIDTH=256).
Blocklists / blacklists (files, not env vars)
hbbr reads two optional files from its working directory at start‑up:
blacklist.txt— IPs that are bandwidth‑limited (one IP per line; anything after the first space on a line is ignored).blocklist.txt— IPs that are refused outright.
Both can also be edited live through the hbbr loopback console (ba/br,
Ba/Br).
Runtime console
The runtime consoles are TCP command transports built into the services; they
are not rustdesk-utils commands or interactive standard-input consoles. A
connection from a loopback address is treated as a single console command:
# hbbs: toggle forced relay on PORT-1 (21115 by default)
printf 'always-use-relay Y' | nc 127.0.0.1 21115
# hbbr: list commands on its relay PORT (21117 by default)
printf 'h' | nc 127.0.0.1 21117
Use the corresponding configured ports if you changed PORT.
Database
At runtime the database location comes from DB_URL (default
./db_v2.sqlite3). If unset, hbbs creates the SQLite file in its working
directory.
Do not confuse
DB_URLwithDATABASE_URL. TheDATABASE_URLentry in the repository's.envis used only at compile time bysqlxto check SQL queries; it is not read by the running server. SettingDATABASE_URLon a running server has no effect — useDB_URL.
Logging
Both binaries use flexi_logger, which honours the standard RUST_LOG
environment variable (default level info). Set it in the process environment
before launching the binary. A value in .env or hbbs's --config file is
loaded too late and has no effect on logging.
RUST_LOG=debug hbbs -r example.com
Keys and encryption
The KEY / -k value can be:
- a public key string — clients must present the matching key;
- a base64‑encoded 64‑byte secret key — the server derives the public key from it;
-or_— the server loads a key pair from the working directory or generates one on first start, writingid_ed25519(private) andid_ed25519.pub(public);- empty — key validation is disabled.
hbbsstill loads or generates key files for signing but deliberately leaves its active validation key empty;hbbrneither loads nor generates a key. Both services then accept clients without validating a key. Do not use an empty value on an exposed server.
By convention -k _ is used to run an encryption‑only server (the official
supervisor Docker image exposes this as ENCRYPTED_ONLY=1). hbbs and hbbr
must be started with the same non-empty key.
To supply your own key pair, place id_ed25519 and id_ed25519.pub in the
process's current working directory before first start. That directory may
differ from the directory containing the executable. For the supervisor Docker
image, the working directory is /data.
Docker image variables
The supervisor image (rustdesk/rustdesk-server-s6) starts both binaries with
s6 and adds a few convenience variables handled by its service scripts, not
by hbbs/hbbr directly:
| Variable | Default | Description |
|---|---|---|
RELAY |
relay.example.com |
Passed to hbbs as -r $RELAY (your public address). |
ENCRYPTED_ONLY |
0 |
1 adds -k _ to both servers, forcing encryption. |
KEY_PUB |
(unset) | If set, written to /data/id_ed25519.pub on first start. |
KEY_PRIV |
(unset) | If set, written to /data/id_ed25519 on first start. Provide both KEY_PUB and KEY_PRIV, or neither. |
Any variable from the tables above can also be passed straight through the
container's environment (e.g. -e ALWAYS_USE_RELAY=Y, -e RUST_LOG=debug).
The classic scratch image (rustdesk/rustdesk-server) contains only the
binaries and does not implement RELAY, ENCRYPTED_ONLY, KEY_PUB, or
KEY_PRIV; those variables are ignored by that image.
Examples
Command line
# ID server: relay clients to this host, LAN detection, force encryption
hbbs -r rustdesk.example.com:21117 --mask 192.168.0.0/16 -k _
# Relay server, same key
hbbr -k _
.env file (working directory)
# Shared by both binaries. hbbr requires exact uppercase KEY and PORT names.
relay-servers=rustdesk.example.com:21117
KEY=_
PORT=21116
Reminder: put the 🅴 variables (
DB_URL,TEST_HBBS,ALWAYS_USE_RELAY,MAX_DATABASE_CONNECTIONS) in the real environment, not in thehbbs.env.
docker-compose
services:
rustdesk-server:
image: rustdesk/rustdesk-server-s6:latest
environment:
- RELAY=rustdesk.example.com:21117
- ENCRYPTED_ONLY=1
- ALWAYS_USE_RELAY=Y
- RUST_LOG=info
- SINGLE_BANDWIDTH=256
ports:
- "21115:21115"
- "21116:21116"
- "21116:21116/udp"
- "21117:21117"
- "21118:21118"
- "21119:21119"
volumes: ["./data:/data"]
restart: unless-stopped
systemd
[Service]
Environment=ALWAYS_USE_RELAY=Y
Environment=RUST_LOG=info
ExecStart=/usr/bin/hbbs -r rustdesk.example.com:21117 -k _
Port reference
| Port | Proto | Server | Purpose |
|---|---|---|---|
| 21115 | TCP | hbbs | NAT type test (PORT-1) |
| 21116 | TCP + UDP | hbbs | ID registration / rendezvous / hole punching (PORT) |
| 21117 | TCP | hbbr | Relay (hbbr PORT) |
| 21118 | TCP | hbbs | WebSocket rendezvous (PORT+2) |
| 21119 | TCP | hbbr | WebSocket relay (hbbr PORT+2) |
Ports 21118/21119 are only needed for the web client; you can omit them otherwise.