Skip to content
  • 前置准备:
    • 端口防火墙开通:
      • sudo ufw allow 21114:21119/tcp
      • sudo ufw allow 21116/udp
      • sudo ufw reload
      • 如果云厂商,需要到平台开通
  • 部署容器

官方部署

version: '3'

services:
  hbbs:
    image: rustdesk/rustdesk-server:latest
    container_name: rustdesk-hbbs
    command: hbbs -r 119.28.106.79:21117
    ports:
      - "21115:21115"   # NAT类型测试
      - "21116:21116"   # ID服务器 (TCP)
      - "21116:21116/udp" # ID服务器 (UDP)
      - "21118:21118"   # WebSocket
      - "21119:21119"   # 备用
    volumes:
      - ./hbbs:/root
    restart: unless-stopped

  hbbr:
    image: rustdesk/rustdesk-server:latest
    container_name: rustdesk-hbbr
    command: hbbr
    ports:
      - "21117:21117"   # 中继服务器
    volumes:
      - ./hbbr:/root
    restart: unless-stopped

镜像部署

  • 多了一个 api 能力
  • 需要通过 RUSTDESK_API_RUSTDESK_KEYKEY 指定密钥,否则会无法连接,这里的密钥可以手动生成
  • 通过:
    • http://服务器IP:21114 进入RustDesk 管理面板
    • 修改用户名: sqlite3 /data/rustdesk/api/rustdeskapi.db "UPDATE users SET username='新用户名' WHERE username='旧用户名';"
    • 修改密码:docker exec rustdesk-server /app/apimain reset-admin-pwd 你的新密码
    • 查看所有用户:sqlite3 /data/rustdesk/api/rustdeskapi.db "SELECT username, is_admin FROM users;"
    • 密钥:
      • 私钥: /data/rustdesk/server/id_ed25519
      • 公钥:/data/rustdesk/server/id_ed25519.pub,客户端连接使用
#!/bin/bash
set -e

echo "=== RustDesk 自动捕获与闭环部署脚本 (自动获取IP版) ==="

# --- 1. 自动获取服务器IP ---
echo "正在自动检测服务器 IP..."

# 尝试获取公网 IP(使用多个服务,防止单个服务失效)
SERVER_IP=$(curl -s --max-time 5 http://ipinfo.io/ip 2>/dev/null || \
            curl -s --max-time 5 http://ifconfig.me 2>/dev/null || \
            curl -s --max-time 5 http://api.ipify.org 2>/dev/null || \
            echo "")

# 如果获取不到公网 IP,使用内网 IP
if [ -z "$SERVER_IP" ]; then
    SERVER_IP=$(ip route get 1.1.1.1 2>/dev/null | grep -oP 'src \K\S+' || \
                hostname -I 2>/dev/null | awk '{print $1}' || \
                ip addr show eth0 2>/dev/null | grep -oP 'inet \K\d+\.\d+\.\d+\.\d+' | head -1 || \
                echo "")
    echo "⚠️  无法获取公网 IP,使用内网 IP: $SERVER_IP"
else
    echo "✅ 检测到公网 IP: $SERVER_IP"
fi

# 如果还是获取不到,报错退出
if [ -z "$SERVER_IP" ]; then
    echo "❌ 错误:无法自动检测服务器 IP,请手动设置 SERVER_IP 变量"
    exit 1
fi

# --- 2. 配置定义 ---
BASE_DIR="/data/rustdesk"
# 使用 hex 格式生成 JWT_KEY,避免 Base64 字符问题
JWT_KEY=$(openssl rand -hex 32)

mkdir -p "$BASE_DIR/server" "$BASE_DIR/api"
cd "$BASE_DIR"

# --- 3. 阶段一:触发 Key 生成 ---
echo ""
echo "阶段 1:启动临时容器以生成原装密钥..."
cat > compose.yml << EOF
services:
  rustdesk:
    container_name: rustdesk-server
    image: lejianwen/rustdesk-server-s6:latest
    environment:
      - RELAY=${SERVER_IP}:21117
      - TZ=Asia/Shanghai
    volumes:
      - ./server:/data
    restart: "no"
EOF

docker compose up -d

# 轮询等待密钥生成,最多等待 120 秒
echo "等待镜像初始化并生成密钥文件..."
PUB_KEY_FILE="./server/id_ed25519.pub"
MAX_WAIT=120
WAITED=0

while [ ! -f "$PUB_KEY_FILE" ] && [ $WAITED -lt $MAX_WAIT ]; do
    sleep 2
    WAITED=$((WAITED + 2))
    echo "  已等待 ${WAITED} 秒,密钥文件尚未生成..."
done

if [ -f "$PUB_KEY_FILE" ]; then
    # 读取并去除所有可能的不可见字符
    CAPTURED_KEY=$(cat "$PUB_KEY_FILE" | tr -d '\n\r ')
    echo "✅ 成功捕获密钥: ${CAPTURED_KEY:0:20}..."
else
    echo "❌ 错误:镜像未能在 ${MAX_WAIT} 秒内生成密钥文件!"
    echo "检查容器日志:"
    docker logs rustdesk-server 2>&1 | tail -20
    exit 1
fi

# 停止临时容器
docker compose down

# --- 4. 阶段二:动态重写正式配置 ---
echo ""
echo "阶段 2:注入捕获的密钥并重新部署正式服务..."

cat > compose.yml << EOF
services:
  rustdesk:
    container_name: rustdesk-server
    image: lejianwen/rustdesk-server-s6:latest
    ports:
      - "21114:21114"
      - "21115:21115"
      - "21116:21116"
      - "21116:21116/udp"
      - "21117:21117"
      - "21118:21118"
      - "21119:21119"
    environment:
      - RELAY=${SERVER_IP}:21117
      - ENCRYPTED_ONLY=1
      - MUST_LOGIN=N
      - TZ=Asia/Shanghai
      - RUSTDESK_API_RUSTDESK_ID_SERVER=${SERVER_IP}:21116
      - RUSTDESK_API_RUSTDESK_RELAY_SERVER=${SERVER_IP}:21117
      - RUSTDESK_API_RUSTDESK_API_SERVER=http://${SERVER_IP}:21114
      # 核心:自动注入读取到的 Key
      - RUSTDESK_API_KEY_FILE=/data/id_ed25519.pub
      - KEY=${CAPTURED_KEY}
      - RUSTDESK_API_RUSTDESK_KEY=${CAPTURED_KEY}
      - RUSTDESK_API_JWT_KEY=${JWT_KEY}
    volumes:
      - ./server:/data
      - ./api:/app/data
    restart: unless-stopped
    stdin_open: true
    tty: true
EOF

# --- 5. 阶段三:正式上线 ---
echo "阶段 3:启动正式服务..."

docker compose up -d --force-recreate

# 在容器重建后设置权限,确保 API 能读取新生成的文件
chmod -R 777 "$BASE_DIR/server" "$BASE_DIR/api"

echo "------------------------------------------------"
echo "✅ 自动闭环部署成功!"
echo "服务器 IP: ${SERVER_IP}"
echo "捕获到的 Key: ${CAPTURED_KEY:0:30}..."
echo "管理后台: http://${SERVER_IP}:21114"
echo "------------------------------------------------"

# 最终健康检查
echo "等待服务初始化(10秒)..."
sleep 10

# 检查容器状态
if ! docker ps | grep -q rustdesk-server; then
    echo "❌ 错误:容器未运行!"
    echo "容器日志:"
    docker logs rustdesk-server 2>&1 | tail -30
    exit 1
fi

# 使用 docker exec 检查端口监听
PORT_CHECK=$(docker exec rustdesk-server sh -c "ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null || echo 'no-tool'" 2>/dev/null || echo "check-failed")

if echo "$PORT_CHECK" | grep -q ":21114"; then
    echo "✅ 状态:API 服务已启动,端口 21114 正在监听。"
else
    echo "⚠️ 警告:API 端口检测未通过,请检查日志确认服务状态。"
    echo "容器日志 (最后30行):"
    docker logs rustdesk-server 2>&1 | tail -30
fi

echo ""
echo "=== 部署信息 ==="
echo "服务器 IP: ${SERVER_IP}"
echo "ID Server: ${SERVER_IP}:21116"
echo "Relay Server: ${SERVER_IP}:21117"
echo "API Server: http://${SERVER_IP}:21114"
echo ""
echo "=== 常用命令 ==="
echo "查看日志: docker logs -f rustdesk-server"
echo "停止服务: docker compose down"
echo "重启服务: docker compose restart"
echo ""
echo "=== 防火墙/安全组端口 ==="
echo "请确保以下端口已开放:21114, 21115, 21116, 21117, 21118, 21119"

正在精进