RustDesk 1.1.16 日常运维手册
RustDesk 1.1.16 服务端运维全流程实测手册:日常巡检清单与脚本、停机冷备与校验和一致性验证、恢复演练、探活告警设计、中继扩容缩容、1.1.16↔1.1.15 升降级与回滚、故障排查速查表。
RustDesk 1.1.16 日常运维手册
目标:给已按同专栏部署篇跑起 RustDesk 1.1.16 自建服务端(hbbs ID/Rendezvous 服务器 + hbbr Relay 中继服务器)的运维人员一份可照着执行的日常手册——巡检项与判读标准、停机冷备与一致性校验、恢复演练、探活与告警设计、中继扩容缩容、版本升级与回滚、故障排查速查表。本文全部命令与回显已在 Ubuntu 22.04 + RustDesk 服务端 1.1.16 环境实测通过(实测日期 2026-10-25),参数语义以官方仓库
docs/environment-variables.md为准。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- RustDesk 服务端版本:1.1.16(2026-07-20 发布,官方最新稳定版,发布信息查询日期 2026-10-25)
- 部署形态:hbbs + hbbr 双服务分离,编排项目名
rustdesk-1.1.16-stack,部署目录/opt/rustdesk/(部署过程见同专栏《RustDesk 1.1.16 服务端 Docker Compose 部署指南》) - 工作目录与落盘路径(运维重点):
- hbbs 数据目录:
/opt/rustdesk/data/hbbs/(挂载到服务工作目录,含密钥对与 SQLite 数据库) - hbbr 数据目录:
/opt/rustdesk/data/hbbr/(含密钥文件,未配置 KEY 时为空目录)
- hbbs 数据目录:
- 端口矩阵:21115/TCP(hbbs NAT 测试)、21116/TCP+UDP(hbbs 注册心跳打洞)、21117/TCP(hbbr 中继)、21118/TCP(hbbs WebSocket)、21119/TCP(hbbr WebSocket)
- 当前服务端公钥(客户端接入用):
tIOS6+HyV3YtZbGh57aTlN5cKrAF2Kg0w2gjWgm2dYY= - 参数语义与优先级规则见同专栏《RustDesk 1.1.16 配置参数详解》
二、日常巡检
巡检目标是回答四个问题:服务在不在、端口通不通、密钥还是不是原来那个、数据有没有在长。以下八项按建议执行顺序排列,全部为只读操作,不影响在线会话。
2.1 服务状态
cd /opt/rustdesk
docker compose ps --format 'table {{.Name}}\t{{.Status}}\t{{.Ports}}'
实测输出:
NAME STATUS PORTS
rustdesk-1.1.16-hbbr Up 18 minutes 0.0.0.0:21117->21117/tcp, [::]:21117->21117/tcp, 0.0.0.0:21119->21119/tcp, [::]:21119->21119/tcp
rustdesk-1.1.16-hbbs Up 18 minutes 0.0.0.0:21115-21116->21115-21116/tcp, [::]:21115-21116->21115-21116/tcp, 0.0.0.0:21118->21118/tcp, [::]:21118->21118/tcp, 0.0.0.0:21116->21116/udp, [::]:21116->21116/udp
判读标准:
- 两个服务都应为
Up;STATUS出现Restarting、或已重启次数不断增长,说明进程在崩溃重启循环,直接查 2.3 日志 PORTS必须完整覆盖 21115–21119,且 21116 的 UDP 映射单独存在(21116->21116/udp)——缺 UDP 是客户端显示离线的头号原因Up时长短期骤降说明发生过重启,需对照 2.3 日志确认原因
2.2 端口矩阵
ss -ltn | grep -E '2111[5-9]'
实测输出(TCP):
LISTEN 0 4096 0.0.0.0:21115 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:21116 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:21117 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:21118 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:21119 0.0.0.0:*
LISTEN 0 4096 [::]:21115 [::]:*
LISTEN 0 4096 [::]:21116 [::]:*
LISTEN 0 4096 [::]:21117 [::]:*
LISTEN 0 4096 [::]:21118 [::]:*
LISTEN 0 4096 [::]:21119 [::]:*
ss -lun | grep 21116
实测输出(UDP):
UNCONN 0 0 0.0.0.0:21116 0.0.0.0:*
UNCONN 0 0 [::]:21116 [::]:*
判读标准:五个 TCP 端口必须全部 LISTEN;UDP 21116 必须 UNCONN 存在。少任何一个都定位到具体服务——缺 21115/21116/21118 是 hbbs 问题,缺 21117/21119 是 hbbr 问题。
2.3 启动日志关键行
hbbs 正常启动会打出一组固定关键行,逐条对应配置生效情况:
docker logs --tail 8 rustdesk-1.1.16-hbbs
实测输出:
[2026-10-25 04:34:43.255880 +00:00] INFO [src/rendezvous_server.rs:109] Listening on tcp/udp :21116
[2026-10-25 04:34:43.255882 +00:00] INFO [src/rendezvous_server.rs:110] Listening on tcp :21115, extra port for NAT test
[2026-10-25 04:34:43.255883 +00:00] INFO [src/rendezvous_server.rs:111] Listening on websocket :21118
[2026-10-25 04:34:43.256076 +00:00] INFO [src/rendezvous_server.rs:146] mask: None
[2026-10-25 04:34:43.256092 +00:00] INFO [src/rendezvous_server.rs:147] local-ip: ""
[2026-10-25 04:34:43.256099 +00:00] INFO [src/common.rs:45] relay-servers=[]
[2026-10-25 04:34:43.256177 +00:00] INFO [src/rendezvous_server.rs:161] ALWAYS_USE_RELAY=N
[2026-10-25 04:34:43.256190 +00:00] INFO [src/rendezvous_server.rs:193] Start
| 关键行 | 正常值 | 异常含义 |
|---|---|---|
Listening on tcp/udp :21116 | 端口与规划一致 | 端口被改写/被占用,客户端将连不上 |
Listening on tcp :21115, extra port for NAT test | 存在 | 缺此行说明派生端口未绑定 |
Listening on websocket :21118 | 存在(除非裁掉 Web 客户端) | 浏览器端无法接入 |
relay-servers=[] | 空(同机标准端口)、或期望的地址列表 | 列表非预期说明被 -r/RELAY-SERVERS 覆盖 |
ALWAYS_USE_RELAY=N | N | 为 Y 表示强制全走中继(带宽成本飙升) |
Start | 末行出现 | 未出现说明启动未完成 |
hbbr 侧对照启动行(默认 QoS 五项在启动时即打印,可用来核对是否被环境变量改过):
[2026-10-25 03:55:24.692107 +00:00] INFO [src/relay_server.rs:82] Listening on tcp :21117
[2026-10-25 03:55:24.692109 +00:00] INFO [src/relay_server.rs:84] Listening on websocket :21119
[2026-10-25 03:55:24.692114 +00:00] INFO [src/relay_server.rs:87] Start
[2026-10-25 03:55:24.692185 +00:00] INFO [src/relay_server.rs:105] DOWNGRADE_THRESHOLD: 0.66
[2026-10-25 03:55:24.692192 +00:00] INFO [src/relay_server.rs:115] DOWNGRADE_START_CHECK: 1800s
[2026-10-25 03:55:24.692196 +00:00] INFO [src/relay_server.rs:125] LIMIT_SPEED: 32Mb/s
[2026-10-25 03:55:24.692200 +00:00] INFO [src/relay_server.rs:136] TOTAL_BANDWIDTH: 1024Mb/s
[2026-10-25 03:55:24.692201 +00:00] INFO [src/relay_server.rs:146] SINGLE_BANDWIDTH: 128Mb/s
排障可临时提高日志级别(RUST_LOG=debug 必须放在进程环境,写 .env 无效):
cd /opt/rustdesk
RUST_LOG=debug docker compose up -d --force-recreate hbbs
2.4 密钥一致性(最容易踩的巡检项)
密钥对就是这套服务端的身份。巡检两件事:文件内容没变、进程实际加载的是它。
cat /opt/rustdesk/data/hbbs/id_ed25519.pub
实测输出:
tIOS6+HyV3YtZbGh57aTlN5cKrAF2Kg0w2gjWgm2dYY=
docker logs rustdesk-1.1.16-hbbs 2>&1 | grep -m1 'Key:'
实测输出:
[2026-10-25 04:34:43.252673 +00:00] INFO [src/rendezvous_server.rs:1243] Key: tIOS6+HyV3YtZbGh57aTlN5cKrAF2Kg0w2gjWgm2dYY=
判读标准:文件末行(公钥)与日志 Key: 后字符串逐字符一致(含尾部 =)。不一致说明进程用的是另一份密钥(工作目录被换、或数据目录被删后重新生成),此时所有客户端都会连不上。
2.5 数据目录
du -sh /opt/rustdesk/data/hbbs /opt/rustdesk/data/hbbr
实测输出:
88K /opt/rustdesk/data/hbbs
4.0K /opt/rustdesk/data/hbbr
ls -l /opt/rustdesk/data/hbbs
实测输出:
total 72
-rw-r--r-- 1 root root 24576 Oct 25 11:54 db_v2.sqlite3
-rw-r--r-- 1 root root 32768 Oct 25 12:34 db_v2.sqlite3-shm
-rw-r--r-- 1 root root 0 Oct 25 12:34 db_v2.sqlite3-wal
-rw-r--r-- 1 root root 88 Oct 25 11:54 id_ed25519
-rw-r--r-- 1 root root 88 Oct 25 11:53 id_ed25519.bak
-rw-r--r-- 1 root root 44 Oct 25 11:54 id_ed25519.pub
-rw-r--r-- 1 root root 44 Oct 25 11:53 id_ed25519.pub.bak
判读标准:
id_ed25519(88 字节)、id_ed25519.pub(44 字节)必须存在且大小稳定;.bak是历史留存副本,保留无妨db_v2.sqlite3随客户端注册数增长;-wal、-shm是 SQLite 的 WAL 附属文件,必须与主库一起备份(见第三章)- 目录突然变小(特别是
id_ed25519消失、只剩新生成的)说明数据目录被重建,客户端 Key 全部失效
2.6 数据库健康
数据库为单文件 SQLite(DB_URL 默认 ./db_v2.sqlite3),表结构只有一张 peer 表:
sqlite3 /opt/rustdesk/data/hbbs/db_v2.sqlite3 '.tables'
实测输出:
peer
sqlite3 /opt/rustdesk/data/hbbs/db_v2.sqlite3 'pragma journal_mode;'
实测输出:
wal
sqlite3 /opt/rustdesk/data/hbbs/db_v2.sqlite3 'select count(*) from peer;'
实测输出(新装未接入客户端时):
0
peer 表结构(实测 .schema 输出):
CREATE TABLE peer (
guid blob primary key not null,
id varchar(100) not null,
uuid blob not null,
pk blob not null,
created_at datetime not null default(current_timestamp),
user blob,
status tinyint,
note varchar(300),
info text not null
) without rowid;
CREATE UNIQUE INDEX index_peer_id on peer (id);
CREATE INDEX index_peer_user on peer (user);
CREATE INDEX index_peer_created_at on peer (created_at);
CREATE INDEX index_peer_status on peer (status);
⚠️ 注意:巡检只做只读查询。不要在服务运行时用外部 sqlite3 执行
VACUUM、ALTER、DELETE等写操作,会与进程的连接池(MAX_DATABASE_CONNECTIONS默认 1)争用并可能触发锁等待。
2.7 运行时控制台状态查询
hbbs / hbbr 内置 loopback 控制台:来自 127.0.0.1 的 TCP 连接被当作一条命令执行。服务运行在独立网络命名空间里,宿主机直接 nc 127.0.0.1 打不到,需要加入该服务的网络命名空间再发命令:
docker run --rm --network container:rustdesk-1.1.16-hbbr alpine:3 sh -c "printf 'tb' | nc 127.0.0.1 21117"
实测输出:
1024Mb/s
hbbs 控制台在 PORT-1(默认 21115):
docker run --rm --network container:rustdesk-1.1.16-hbbs alpine:3 sh -c "printf 'aur' | nc 127.0.0.1 21115"
实测输出:
ALWAYS_USE_RELAY: false
docker run --rm --network container:rustdesk-1.1.16-hbbs alpine:3 sh -c "printf 'rs' | nc 127.0.0.1 21115"
实测输出(未配置 -r、中继与 ID 服务器同机同标准端口时为空,属于正常):
2.8 每日巡检清单与脚本
| # | 巡检项 | 命令/位置 | 正常判据 | 频率 |
|---|---|---|---|---|
| 1 | 服务状态 | docker compose ps | 双服务 Up,PORTS 含 UDP 21116 | 每日 |
| 2 | TCP 端口 | ss -ltn | grep -E '2111[5-9]' | 5 个端口全 LISTEN | 每日 |
| 3 | UDP 端口 | ss -lun | grep 21116 | 存在 UNCONN | 每日 |
| 4 | 启动关键行 | docker logs --tail 8 rustdesk-1.1.16-hbbs | 见 2.3 表 | 每日 |
| 5 | 密钥一致 | cat id_ed25519.pub + 日志 Key: | 逐字符一致 | 每日(变更后立即) |
| 6 | 数据目录 | du -sh、ls -l | 主库在增长、密钥文件大小稳定 | 每周 |
| 7 | 数据库 | count(*) from peer | 与客户端实际接入量趋势一致 | 每周 |
| 8 | 控制台态 | tb/aur/rs | 与配置期望一致 | 每周 |
| 9 | 磁盘水位 | df -h /opt/rustdesk | 剩余 > 20% | 每周 |
| 10 | 备份产物 | 备份目录 ls -lh | 当日备份存在且大小合理 | 每日(看备份任务结果) |
可直接落成脚本(只读、不改任何状态):
#!/usr/bin/env bash
# /opt/rustdesk/bin/check.sh —— RustDesk 服务端每日巡检
set -uo pipefail
cd /opt/rustdesk || exit 1
fail=0
echo "== 1. 服务状态 =="
docker compose ps --format 'table {{.Name}}\t{{.Status}}' | grep -q 'Up' || { echo "FAIL: 服务未运行"; fail=1; }
echo "== 2/3. 端口 =="
for p in 21115 21116 21117 21118 21119; do
ss -ltn | grep -q ":$p " || { echo "FAIL: TCP $p 未监听"; fail=1; }
done
ss -lun | grep -q ':21116 ' || { echo "FAIL: UDP 21116 未监听"; fail=1; }
echo "== 5. 密钥一致 =="
pub=$(tail -n1 /opt/rustdesk/data/hbbs/id_ed25519.pub)
log=$(docker logs rustdesk-1.1.16-hbbs 2>&1 | grep -m1 'Key:' | awk '{print $NF}')
[ "$pub" = "$log" ] || { echo "FAIL: 公钥与进程加载密钥不一致 pub=$pub log=$log"; fail=1; }
echo "== 9. 磁盘 =="
df -h /opt/rustdesk | awk 'NR==2 {print "used="$5" avail="$4}'
[ $fail -eq 0 ] && echo "RESULT: OK" || echo "RESULT: FAIL"
exit $fail
三、备份
3.1 备份对象
hbbs 数据目录是全部有状态内容,hbbr 数据目录在未配置 KEY 时几乎为空:
| 文件 | 作用 | 丢失后果 |
|---|---|---|
id_ed25519 | 私钥,用于签名 | 无法恢复服务端身份 |
id_ed25519.pub | 公钥,客户端接入要填的 Key | 同上 |
db_v2.sqlite3 | peer 表主库(客户端 ID 注册记录) | 已注册客户端需重新注册 |
db_v2.sqlite3-wal / -shm | WAL 附属文件 | 单备份主库可能丢失最新写入 |
.config/rustdesk/RustDesk.toml | 运行期配置残留 | 一般无影响,一并备份最稳 |
⚠️ 结论:密钥对是第一优先级,数据库是第二优先级。密钥丢失等于整套服务端身份丢失,所有客户端必须改 Key。
3.2 停机冷备流程(实测)
WAL 模式数据库在服务运行时直接 tar 有拿到半写状态的风险,最稳的是短暂停服后整体打包。停机窗口通常 1 秒内完成,对在线会话影响极小(已建立的会话在恢复后需重连)。
cd /opt/rustdesk
docker compose stop hbbs
mkdir -p /opt/rustdesk-backup
tar -czf /opt/rustdesk-backup/rustdesk-hbbs-$(date +%Y%m%d).tgz -C data/hbbs .
docker compose start hbbs
实测输出(tar 静默成功无输出,仅停/启有回显):
Container rustdesk-1.1.16-hbbs Stopping
Container rustdesk-1.1.16-hbbs Stopped
Container rustdesk-1.1.16-hbbs Starting
Container rustdesk-1.1.16-hbbs Started
备份产物(实测):
ls -lh /opt/rustdesk-backup/
total 4.0K
-rw-r--r-- 1 root root 1.5K Oct 25 12:53 rustdesk-hbbs-20261025.tgz
归档内容(实测 tar -tzf):
./
./id_ed25519.bak
./id_ed25519.pub
./db_v2.sqlite3-shm
./db_v2.sqlite3
./id_ed25519
./id_ed25519.pub.bak
./.config/
./.config/rustdesk/
./.config/rustdesk/RustDesk.toml
./db_v2.sqlite3-wal
确认打包后服务已恢复监听:
docker logs --tail 3 rustdesk-1.1.16-hbbs
3.3 备份一致性校验
每个备份生成后立刻比对校验和,确认归档与现网数据同源:
sha256sum /opt/rustdesk-backup/rustdesk-hbbs-20261025.tgz
实测输出:
27d52d061dbbb3ba4bf4302d3aa8f45f978d4bb35aba2dab653bdb3c5448e33a /opt/rustdesk-backup/rustdesk-hbbs-20261025.tgz
解包后与现网主库比对:
mkdir -p /tmp/verify && tar -xzf /opt/rustdesk-backup/rustdesk-hbbs-20261025.tgz -C /tmp/verify
sha256sum /tmp/verify/db_v2.sqlite3 /opt/rustdesk/data/hbbs/db_v2.sqlite3
实测输出(两者一致,说明备份取的是干净快照):
7b8fd91b4b21e380687d60c2905258f47086d85e1e45889c7e8757ab22ef901e /tmp/verify/db_v2.sqlite3
7b8fd91b4b21e380687d60c2905258f47086d85e1e45889c7e8757ab22ef901e /opt/rustdesk/data/hbbs/db_v2.sqlite3
💡 说明:hBbs 启动后
db_v2.sqlite3-wal会被重新创建(实测复启后-wal变为 0 字节),比对主库哈希即可;确认键值以 主库哈希一致 + 密钥文件哈希一致 为准。
3.4 备份策略建议
| 项 | 建议 | 理由 |
|---|---|---|
| 频率 | 每日一次 + 变更前必做(升级、改端口、换密钥、迁机) | 数据库增量小(本例 24 KB),成本可忽略;变更前备份是回滚底线 |
| 保留 | 本地 7 份 + 异地/对象存储 30 份 | 覆盖误删与宿主机故障两种场景 |
| 异地 | 推送到另一台机器或对象存储 | 密钥与数据库必须能脱离宿主恢复 |
| 校验 | 每次生成后记录 sha256;每月抽一份做恢复演练 | 无演练的备份不可信 |
| 权限 | chmod 600 备份产物(含私钥) | 私钥泄露等于服务端身份泄露 |
chmod 600 /opt/rustdesk-backup/*.tgz
3.5 不停机备份(无停机窗口时)
单靠 cp 主库仍可能拿到不一致快照;SQLite 官方推荐的在线备份方式是在同目录执行 .backup(或 VACUUM INTO),由 SQLite 自身保证一致性:
sqlite3 /opt/rustdesk/data/hbbs/db_v2.sqlite3 ".backup '/opt/rustdesk-backup/db_v2-$(date +%Y%m%d).sqlite3'"
tar -czf /opt/rustdesk-backup/rustdesk-keys-$(date +%Y%m%d).tgz -C /opt/rustdesk/data/hbbs id_ed25519 id_ed25519.pub
备份产物分成「库」与「密钥」两个文件,恢复时分别放回数据目录即可。
四、恢复
4.1 恢复场景
| 场景 | 恢复目标 | 需要的备份 |
|---|---|---|
| 误删数据目录 / 换盘 | 原位恢复 | 密钥对 + 数据库 |
| 宿主机宕机重建 | 换机恢复 | 密钥对 + 数据库 |
| 升级/改配置后出错 | 回滚到变更前状态 | 变更前全量备份 |
| 定期演练 | 验证备份可用 | 任意最近一份 |
4.2 恢复演练(实测,不影响现网)
演练原则:先在与现网隔离的非标准端口上验证,再动现网。以下用 22116 作为演练端口(现网 hbbs 占用 21116)。
第一步,解包到独立目录:
mkdir -p /opt/rustdesk-restore-test
tar -xzf /opt/rustdesk-backup/rustdesk-hbbs-20261025.tgz -C /opt/rustdesk-restore-test
ls -l /opt/rustdesk-restore-test
实测输出:
total 72
-rw-r--r-- 1 root root 24576 Oct 25 11:54 db_v2.sqlite3
-rw-r--r-- 1 root root 32768 Oct 25 12:53 db_v2.sqlite3-shm
-rw-r--r-- 1 root root 0 Oct 25 12:53 db_v2.sqlite3-wal
-rw-r--r-- 1 root root 88 Oct 25 11:54 id_ed25519
-rw-r--r-- 1 root root 88 Oct 25 11:53 id_ed25519.bak
-rw-r--r-- 1 root root 44 Oct 25 11:54 id_ed25519.pub
-rw-r--r-- 1 root root 44 Oct 25 11:53 id_ed25519.pub.bak
第二步,用恢复数据在 22116 起一个临时实例验证:
docker run -d --name rustdesk-restore-test \
-p 22116:22116 -p 22116:22116/udp -p 22118:22118 \
-v /opt/rustdesk-restore-test:/root \
rustdesk/rustdesk-server:1.1.16 hbbs -p 22116
实测输出:
542b14954739b31396fe77017653208b0bae03a08a2abe7caf56f8f444008b86
第三步,校验日志(关键看 Private key comes from id_ed25519、Key: 与监听端口):
docker logs rustdesk-restore-test
实测输出:
[2026-10-25 04:54:11.767023 +00:00] INFO [src/common.rs:121] Private key comes from id_ed25519
[2026-10-25 04:54:11.767044 +00:00] INFO [src/rendezvous_server.rs:1243] Key: tIOS6+HyV3YtZbGh57aTlN5cKrAF2Kg0w2gjWgm2dYY=
[2026-10-25 04:54:11.767048 +00:00] INFO [src/peer.rs:84] DB_URL=./db_v2.sqlite3
[2026-10-25 04:54:11.769031 +00:00] INFO [src/rendezvous_server.rs:107] serial=0
[2026-10-25 04:54:11.769050 +00:00] INFO [src/common.rs:45] rendezvous-servers=[]
[2026-10-25 04:54:11.769052 +00:00] INFO [src/rendezvous_server.rs:109] Listening on tcp/udp :22116
[2026-10-25 04:54:11.769053 +00:00] INFO [src/rendezvous_server.rs:110] Listening on tcp :22115, extra port for NAT test
[2026-10-25 04:54:11.769054 +00:00] INFO [src/rendezvous_server.rs:111] Listening on websocket :22118
[2026-10-25 04:54:11.769093 +00:00] INFO [src/rendezvous_server.rs:146] mask: None
[2026-10-25 04:54:11.769094 +00:00] INFO [src/rendezvous_server.rs:147] local-ip: ""
[2026-10-25 04:54:11.769097 +00:00] INFO [src/common.rs:45] relay-servers=[]
[2026-10-25 04:54:11.769126 +00:00] INFO [src/rendezvous_server.rs:161] ALWAYS_USE_RELAY=N
[2026-10-25 04:54:11.769133 +00:00] INFO [src/rendezvous_server.rs:193] Start
关键判读:
Private key comes from id_ed25519:用的是备份里的私钥文件,不是新生成的Key: tIOS6+HyV3YtZbGh57aTlN5cKrAF2Kg0w2gjWgm2dYY=:与现网公钥一致 → 客户端无需改任何配置DB_URL=./db_v2.sqlite3后无建库报错:数据库可被正常打开
第四步,恢复数据库完整性校验:
sqlite3 /opt/rustdesk-restore-test/db_v2.sqlite3 '.tables'
sqlite3 /opt/rustdesk-restore-test/db_v2.sqlite3 'select count(*) from peer;'
sqlite3 /opt/rustdesk-restore-test/db_v2.sqlite3 'pragma journal_mode;'
实测输出:
peer
0
wal
第五步,控制台连通性验证(临时实例的 hbbs 控制台在 PORT-1 = 22115):
docker run --rm --network container:rustdesk-restore-test alpine:3 sh -c "printf 'aur' | nc 127.0.0.1 22115"
实测输出:
ALWAYS_USE_RELAY: false
第六步,清理演练实例:
docker rm -f rustdesk-restore-test
rm -rf /opt/rustdesk-restore-test
4.3 恢复检查清单
| # | 检查项 | 通过标准 |
|---|---|---|
| 1 | 私钥来源 | 日志出现 Private key comes from id_ed25519 |
| 2 | 公钥一致 | 日志 Key: 与变更前公钥逐字符一致 |
| 3 | 数据库可读 | .tables 输出 peer,count(*) 与预期量级一致(行为 0 也属正常,表示尚未有客户端注册) |
| 4 | 端口监听 | Listening on tcp/udp :<端口> 与规划一致 |
| 5 | 控制台可用 | aur 返回 ALWAYS_USE_RELAY: false(或配置值) |
| 6 | 客户端实测 | 用一台客户端填「ID 服务器 + 公钥」接入,ID 能获取、能发起会话 |
4.4 正式恢复步骤(原位 / 换机)
原位恢复(数据目录被误删、宿主机仍在):
cd /opt/rustdesk
docker compose stop hbbs
rm -rf data/hbbs
mkdir -p data/hbbs
tar -xzf /opt/rustdesk-backup/rustdesk-hbbs-20261025.tgz -C data/hbbs
docker compose start hbbs
docker logs --tail 5 rustdesk-1.1.16-hbbs
换机恢复(新宿主机重建):
- 新机按部署篇装好运行环境与编排文件,创建同一网络与端口映射
- 把最新的
*.tgz拷到新机,解包进data/hbbs - 起服务后按 4.3 清单逐项核验
- 若服务端地址变化,客户端「ID 服务器」需改成新地址;Key 不用改(密钥对来自备份)
⚠️ 注意:恢复时切勿"先起服务再放数据"。hbbs 首次启动若发现工作目录没有密钥对会立即生成新的(日志
Private/public key written to id_ed25519/id_ed25519.pub),此时再拷入旧密钥可能导致进程已按新密钥对外服务,客户端批量失联。正确顺序永远是先放数据、后起服务。
五、监控与告警
5.1 没有内置指标端点
实测 1.1.16 两个进程只监听 21115–21119 这五个业务端口(见 2.2),没有 Prometheus /metrics 之类的指标接口:开源版服务端不提供结构化监控端点(PORT_FOR_API / KEY_FOR_API 只属于商业版 Pro)。因此监控体系由三块拼成:
- 端口探活(外部主动探测,判断进程是否在)
- 日志关键字(判断启动是否正常、有无异常)
- 控制台查询(判断运行期业务状态:带宽、中继列表、强制中继开关)
5.2 端口探活
for port in 21115 21116 21117 21118; do
nc -z -w 2 127.0.0.1 $port && echo "OK $port/tcp" || echo "FAIL $port/tcp"
done
💡 说明:UDP 端口无法用 TCP 探活判断。UDP 21116 的可用性只能通过「服务端
ss -lun有监听 + 客户端实际能注册」两段验证;外部监控不要对 UDP 21116 做盲目探活,否则容易误报。
告警建议:
| 探测项 | 阈值 | 级别 |
|---|---|---|
| TCP 21115 / 21116 / 21117 / 21118 | 连续 2 次失败 | P1(服务不可用) |
| TCP 21119(若启用 Web 客户端) | 连续 3 次失败 | P2 |
| 宿主机磁盘剩余 | < 20% | P2 |
| 服务重启次数增长 | 1 小时内 ≥ 2 次 | P1(崩溃循环) |
5.3 日志关键字告警
采集服务日志并按关键字告警,可覆盖「端口通但服务异常」这类探活发现不了的情况:
docker logs --since 10m rustdesk-1.1.16-hbbs 2>&1 | grep -cE 'Listening on tcp/udp'
docker logs --since 10m rustdesk-1.1.16-hbbr 2>&1 | grep -cE 'Start'
| 关键字 | 含义 | 处置 |
|---|---|---|
Private/public key written to id_ed25519/id_ed25519.pub | 密钥被重新生成(数据目录丢过) | 立即 P1 告警 + 按 4.4 恢复备份 |
signal terminate | 进程收到终止信号 | 属正常停机;非计划内的出现需查上游 |
Address already in use 之类绑定失败 | 端口冲突 | 查 ss -ltn 占用方 |
ERROR | 任何 ERROR 行 | 逐条排查,配合 RUST_LOG=debug 复现 |
5.4 控制台业务指标
控制台能查到的运行期状态(hbbr 在 21117,hbbs 在 21115):
| 命令 | 端口 | 返回值含义 | 采集建议 |
|---|---|---|---|
tb | 21117 | 当前总带宽上限 | 5 分钟一次,与配置期望值比对(可发现配置漂移) |
sb | 21117 | 单连接带宽上限 | 同上 |
ls | 21117 | 降级限速值 | 同上 |
dt / t | 21117 | 降级阈值 / 起始检查秒数 | 同上 |
u | 21117 | 中继用量(无流量时空) | 观察趋势 |
rs | 21115 | 当前下发的中继列表 | 与期望列表比对(可发现中继漏配) |
aur | 21115 | 强制中继开关 | 期望 false,变 true 需告警 |
采集示例(写入时序库或落盘留痕):
docker run --rm --network container:rustdesk-1.1.16-hbbr alpine:3 sh -c "
printf 'tb' | nc 127.0.0.1 21117; echo
printf 'sb' | nc 127.0.0.1 21117; echo
printf 'ls' | nc 127.0.0.1 21117; echo
"
实测输出:
1024Mb/s
128Mb/s
32Mb/s
六、扩容与缩容
6.1 垂直扩容:调中继带宽(优先做)
中继带宽不够时,先调 hbbr 的 QoS 上限,不必加机器。两项可调:
# docker-compose.yml 的 hbbr 服务 environment 段
environment:
- SINGLE_BANDWIDTH=256
- TOTAL_BANDWIDTH=2048
改完重建生效:
cd /opt/rustdesk
docker compose up -d hbbr
docker logs --tail 6 rustdesk-1.1.16-hbbr
生效判据:启动日志的 SINGLE_BANDWIDTH / TOTAL_BANDWIDTH 变为新值(默认值见 2.3)。
临时调整(不停服) 用控制台热改,实测:
docker run --rm --network container:rustdesk-1.1.16-hbbr alpine:3 sh -c "
echo -n 'before: '; printf 'sb' | nc 127.0.0.1 21117; echo
printf 'sb 256' | nc 127.0.0.1 21117
echo -n 'after : '; printf 'sb' | nc 127.0.0.1 21117; echo
printf 'sb 128' | nc 127.0.0.1 21117
"
实测输出:
before: 128Mb/s
after : 256Mb/s
⚠️ 注意:控制台改动只存在于当前进程内存,重启即回到编排/环境变量的值。要固化必须改配置,控制台只用于临时救急。改写命令本身无回显,需再查一次确认。
6.2 水平扩容:增加中继实例
单个 hbbr 的总带宽受 TOTAL_BANDWIDTH 与出口带宽限制时,加第二个中继实例分摊。这里最容易踩的坑是端口与下发列表——新实例必须用不同宿主端口,并显式加入 hbbs 的 relay-servers,否则客户端永远推不到它。
实测:在原栈之外再起一个中继实例,宿主 21217(对应服务内 21117):
docker run -d --name rustdesk-1.1.16-hbbr2 \
-p 21217:21117 -p 21219:21119 \
-v /opt/rustdesk/data/hbbr2:/root \
rustdesk/rustdesk-server:1.1.16 hbbr
实测启动日志(新实例默认 QoS 与主实例一致):
[2026-10-25 04:54:37.780176 +00:00] INFO [src/relay_server.rs:61] #blacklist(blacklist.txt): 0
[2026-10-25 04:54:37.780186 +00:00] INFO [src/relay_server.rs:76] #blocklist(blocklist.txt): 0
[2026-10-25 04:54:37.780188 +00:00] INFO [src/relay_server.rs:82] Listening on tcp :21117
[2026-10-25 04:54:37.780190 +00:00] INFO [src/relay_server.rs:84] Listening on websocket :21119
把两个中继写进 hbbs 的下发列表——运行期可先用控制台 rs 热验证(实测):
docker run --rm --network container:rustdesk-1.1.16-hbbs alpine:3 sh -c "
printf 'rs 192.168.146.128:21117,192.168.146.128:21217' | nc 127.0.0.1 21115
printf 'rs' | nc 127.0.0.1 21115
"
实测输出(下发列表已生效为两条):
192.168.146.128:21117
192.168.146.128:21217
两个中继端口连通性实测:
relay1 21117 reachable
relay2 21217 reachable
固化写法(hbbs 启动参数):
# docker-compose.yml 的 hbbs 服务
command: hbbs -r 192.168.146.128:21117,192.168.146.128:21217
要点:
- 列表元素支持
host或host:port;非标准端口必须带端口 - 中继在不同主机时填各自的公网地址
- 加完中继后务必复核:hbbs 日志的
relay-servers=行内容与客户端实际可用中继一致 - 新中继的 21117/21119 同样要放通防火墙与安全组
6.3 多 ID 服务器(rendezvous 互联)
hbbs 支持用 -R, --rendezvous-servers 指定多个 rendezvous 服务器做互联(单机部署留空,日志显示 rendezvous-servers=[])。注意 peer 数据库是各 hbbs 本地 SQLite,多 hbbs 不做共享存储,规划多 ID 服务器前要先确定客户端 ID 归属策略。
6.4 缩容步骤
缩容顺序与扩容相反——先摘下发列表,再停实例,否则客户端会拿到已下线的中继地址反复重试:
- 从 hbbs 的
relay-servers中移除待下线地址(控制台rs热改验证 → 固化到command: hbbs -r <保留的中继地址>) - 观察一个会话周期(建议 ≥ 30 分钟),确认无客户端仍在用该中继
- 停并移除被下线的中继实例及其端口映射
- 收尾清理:宿主端口从防火墙/安全组撤掉,数据目录保留一份备查
七、升级与回滚
7.1 升级前检查
- 备份现网数据(第三章,必做)
- 记录当前公钥:
cat /opt/rustdesk/data/hbbs/id_ed25519.pub - 确认新版本已发布并读取发布说明:官方 Releases 页
https://github.com/rustdesk/rustdesk-server/releases - 确认可回滚:本地保留旧版本编排文件与旧版本运行包
7.2 升级流程(实测)
编排中只改 image 标签(示例由 1.1.15 升到 1.1.16),然后重建:
cd /opt/rustdesk
docker compose up -d
实测输出:
Container rustdesk-1.1.16-hbbr Recreate
Container rustdesk-1.1.16-hbbs Recreate
Container rustdesk-1.1.16-hbbr Recreated
Container rustdesk-1.1.16-hbbs Recreated
Container rustdesk-1.1.16-hbbs Starting
Container rustdesk-1.1.16-hbbr Starting
Container rustdesk-1.1.16-hbbs Started
Container rustdesk-1.1.16-hbbr Started
升级后核验(版本 + 公钥 + 端口):
docker compose ps --format 'table {{.Name}}\t{{.Image}}\t{{.Status}}'
实测输出:
NAME IMAGE STATUS
rustdesk-1.1.16-hbbr rustdesk/rustdesk-server:1.1.16 Up Less than a second
rustdesk-1.1.16-hbbs rustdesk/rustdesk-server:1.1.16 Up Less than a second
docker logs rustdesk-1.1.16-hbbs 2>&1 | grep -m1 'Key:'
实测输出:
[2026-10-25 04:34:43.252673 +00:00] INFO [src/rendezvous_server.rs:1243] Key: tIOS6+HyV3YtZbGh57aTlN5cKrAF2Kg0w2gjWgm2dYY=
7.3 回滚流程(实测)
把 image 标签改回旧版本,同样 docker compose up -d 重建。实测由 1.1.16 回滚到 1.1.15:
docker compose ps --format 'table {{.Name}}\t{{.Image}}\t{{.Status}}'
实测输出:
NAME IMAGE STATUS
rustdesk-1.1.16-hbbr rustdesk/rustdesk-server:1.1.15 Up Less than a second
rustdesk-1.1.16-hbbs rustdesk/rustdesk-server:1.1.15 Up Less than a second
回滚后公钥一致(注意日志中的源码行号从 1.1.16 的 rendezvous_server.rs:1243 变为 1.1.15 的 1251,这本身就是版本已切换的旁证):
[2026-10-25 04:34:32.803690 +00:00] INFO [src/rendezvous_server.rs:1251] Key: tIOS6+HyV3YtZbGh57aTlN5cKrAF2Kg0w2gjWgm2dYY=
hbbr 回滚后启动即打印 QoS 默认值,可用于确认配置未被版本变更带走:
[2026-10-25 04:34:33.000984 +00:00] INFO [src/relay_server.rs:87] Start
[2026-10-25 04:34:33.001078 +00:00] INFO [src/relay_server.rs:105] DOWNGRADE_THRESHOLD: 0.66
[2026-10-25 04:34:33.001081 +00:00] INFO [src/relay_server.rs:115] DOWNGRADE_START_CHECK: 1800s
[2026-10-25 04:34:33.001082 +00:00] INFO [src/relay_server.rs:125] LIMIT_SPEED: 32Mb/s
[2026-10-25 04:34:33.001084 +00:00] INFO [src/relay_server.rs:136] TOTAL_BANDWIDTH: 1024Mb/s
[2026-10-25 04:34:33.001086 +00:00] INFO [src/relay_server.rs:146] SINGLE_BANDWIDTH: 128Mb/s
7.4 版本兼容性结论(实测)
- 密钥不变:1.1.16 → 1.1.15 → 1.1.16 双向切换后,
Key:全程为同一值,客户端无需改 Key - 数据库可双向读写:同一份
db_v2.sqlite3在 1.1.15 与 1.1.16 间切换启动均无建库报错、peer表可正常查询 - 配置语义未变:hbbr 的 QoS 五项与 hbbs 的派生端口规则在 1.1.15/1.1.16 一致
- 回滚边界:本结论仅覆盖 1.1.15 ↔ 1.1.16;跨大版本或跨大跨度回滚(尤其涉及数据库结构变更的版本)必须先在小环境做恢复演练,不要直接对生产回滚
7.5 升级最佳实践
- 挑窗口期:升级会重建服务,在线会话会中断
- 先升 hbbr(中继),验证无异常再升 hbbs(ID 服务器)——这样 ID 注册面始终有一个健康实例
- 每次只升一个版本台阶,不跨多版本跳跃
- 升级后按 4.3 清单核验,重点看公钥是否不变(若变了,说明数据目录出了问题,应立即回滚并恢复备份)
八、故障排查速查表
| 现象 | 首要排查 | 定位命令 | 常见处置 |
|---|---|---|---|
| 客户端显示离线 / 未就绪 | UDP 21116 未通 | ss -lun | grep 21116;安全组/防火墙规则 | 放通 UDP 21116(TCP 放通但漏 UDP 是最常见根因) |
| 客户端提示 Key 错误 | 客户端 Key 与服务端公钥不一致 | cat data/hbbs/id_ed25519.pub 与 2.4 的日志比对 | 逐字符改为一致(含尾部 =) |
| 全部客户端突然连不上、Key 全错 | 数据目录被重建,密钥被重新生成 | 日志搜 Private/public key written to | 立即按 4.4 恢复备份,先放数据后起服务 |
| 所有会话都走中继、打洞失败 | 强制中继被打开 / 对称 NAT | printf 'aur' | nc 127.0.0.1 21115 | always-use-relay N 恢复直连;对称 NAT 属正常兜底 |
| 中继带宽打满、画面卡顿 | 单连接被降级 / 总带宽上限 | tb、sb、ls、dt 控制台查询 | 调 SINGLE_BANDWIDTH/TOTAL_BANDWIDTH;确认不是 ALWAYS_USE_RELAY=Y 把流量全压到中继 |
| 单条大流量长连接被限速(中继其它空闲) | 降级机制按连接独立判定 | dt=0.66、t=1800s、ls=32Mb/s | 属设计行为;需要时调高 SINGLE_BANDWIDTH 或 LIMIT_SPEED |
| 某 IP 疯狂重连/恶意中继 | 黑/白名单 | printf 'B' | nc 127.0.0.1 21117 | blocklist-add <ip> 在线封禁;固化写 blocklist.txt |
| 服务反复重启 | 端口冲突 / 数据目录权限 | docker compose ps、docker logs --tail 50 | 释放占用端口;修正目录属主权限 |
| 进不去服务内部调试 | 极简运行包无 shell | — | 属正常形态;治理走日志 + loopback 控制台 |
| 磁盘持续增长 | 数据库/日志增长 | du -sh data/hbbs、count(*) from peer | 数据库增长属正常(每客户端一条记录);日志按采集侧策略轮转 |
| Web 客户端连不上 | 21118/21119 未放通 | ss -ltn | grep -E '2111[89]' | 放通两个 WebSocket 端口;确认客户端填了 ID 服务器 + Key |
排障通用姿势:先用 RUST_LOG=debug 重建服务抓一次全量日志(命令见 2.3),对照 2.3 的关键行表逐项排除;参数语义不清时回查同专栏《RustDesk 1.1.16 配置参数详解》。
九、常见问题
Q1:日常运维需要停服吗? A:巡检、控制台查询、日志查看全部只读,不停服;只有冷备打包和升级回滚需要短暂停服(实测停/启各在秒级)。不停机的备份方式见 3.5。
Q2:备份只备数据库行不行?
A:不行。密钥对(id_ed25519 + id_ed25519.pub)才是服务端身份,丢了等于整套服务重建、所有客户端改 Key;数据库丢了只是客户端需重新注册。至少两者都要备。
Q3:可以直接 cp db_v2.sqlite3 当备份吗?
A:不建议。数据库处于 WAL 模式,运行中单拷主库可能缺失最新写入。要么停服后整目录打包(3.2),要么用 sqlite3 .backup(3.5)。
Q4:恢复后客户端要不要重新配置? A:密钥对没变(备份就是原密钥),客户端无需改任何配置;只有服务端 IP/域名变了才需要客户端改「ID 服务器」地址。
Q5:docker logs 打不到控制台命令怎么办?
A:控制台只接受来自 127.0.0.1 的连接,且服务在独立网络命名空间里。用 --network container:<服务名> 加入其命名空间后再 nc 127.0.0.1 <控制台端口>,见 2.7。
Q6:控制台改的带宽值重启后为什么又回去了? A:控制台改动只在进程内存,重启即恢复编排/环境变量的值。临时救急用控制台,固化必须改配置,见 6.1。
Q7:监控能接 Prometheus 吗? A:开源版 1.1.16 没有指标端点(实测仅监听 21115–21119 业务端口)。可自建探活 + 日志告警 + 控制台拉取三件套(第五章),或用外部脚本把控制台查询结果转成时序数据。
Q8:升级把公钥弄变了怎么办?
A:说明数据目录在升级中被替换/重建。立即回滚到旧版本并先恢复备份数据再起服务(顺序见 4.4 注意事项),核验 Key: 与升级前一致后再对外。
十、参考链接
- 官方自托管文档(查询日期 2026-10-25):https://rustdesk.com/docs/en/self-host/
- 官方服务端仓库与 Releases(1.1.16 发布信息,查询日期 2026-10-25):https://github.com/rustdesk/rustdesk-server
- 官方配置与环境变量权威文档(查询日期 2026-10-25):https://github.com/rustdesk/rustdesk-server/blob/master/docs/environment-variables.md
- 官方 FAQ(查询日期 2026-10-25):https://github.com/rustdesk/rustdesk/wiki/FAQ
- 站内同系列:《RustDesk 1.5.0 介绍与选型指南》、《RustDesk 1.1.16 服务端 Docker Compose 部署指南》、《RustDesk 1.1.16 配置参数详解》(同专栏 RustDesk)