feat: add remote main server cli passthrough

This commit is contained in:
Codex
2026-05-05 01:56:42 +00:00
parent eb6df3ba92
commit cc1533c02f
7 changed files with 150 additions and 2 deletions
+9
View File
@@ -5,6 +5,7 @@ UniDesk 的统一 CLI 入口是根目录 `scripts/cli.ts`,运行方式固定
## Command Model
- `help` 输出命令索引,适合作为交互式入口。
- `--main-server-ip <ip> <command>` 通过 SSH 登录主 server,在主 server 的 UniDesk 仓库中执行同一个 `bun scripts/cli.ts <command>`stdout/stderr 和 exit code 原样透传给当前机器。
- `config show` 读取并校验根目录 `config.json`,不从环境变量、默认值或隐藏文件静默补配置。
- `check` 执行配置校验、文件存在性检查、`scripts/` TypeScript 检查、`src/components/` TypeScript 检查和 Docker Compose 配置检查。
- `server start` 创建异步 job,在后台执行 Docker 构建和启动;命令本身只负责返回 job id、日志路径和启动命令。
@@ -35,3 +36,11 @@ UniDesk 的统一 CLI 入口是根目录 `scripts/cli.ts`,运行方式固定
`bun scripts/cli.ts ssh D518` 应表现为登录 D518 WSL 的 shell`bun scripts/cli.ts ssh D518 hostname` 应像 `ssh D518 hostname` 一样只输出远端命令结果并返回远端 exit code。Provider ID 前的目标选择由 UniDesk 节点清单决定,`-p``-i``-l``-o` 等传统 ssh 传输参数由 provider-gateway 部署配置统一管理,CLI 会兼容性消费这些参数但不会覆盖节点侧维护桥配置。
core 只允许声明了 `host.ssh` capability 的 provider 使用 `ssh` 透传或 `host.ssh` dispatch;旧 provider 不支持该能力时必须快速失败并输出错误,不能把未知命令误判成 `echo` 成功。
## Remote Main Server Passthrough
`--main-server-ip` 是一个全局前缀,必须放在需要透传的命令同一次调用中,例如 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug health`。本地 CLI 只负责建立 SSH 连接,不读取本机 `config.json` 执行业务逻辑;真实命令在主 server 的 `--main-server-root` 目录中运行,默认目录是 `/root/unidesk`。默认 SSH 用户是 `root`、端口是 `22`;需要覆盖时使用 `--main-server-user``--main-server-port``--main-server-key`
计算节点可以用该入口测试自身的远程升级闭环,而不需要在计算节点公开 core REST API 或 database。标准顺序是:先运行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug health` 确认主 server 看到当前 Provider 在线;再运行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> provider.upgrade --mode schedule --wait-ms 15000` 触发真实 `provider.upgrade`;随后再次运行 `debug health` 确认节点重新上线,若节点配置了维护桥,再运行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh <PROVIDER_ID> hostname` 验证 SSH 透传能力。
远程透传只接受主 server SSH 信任边界内的 key;不要把 provider token、数据库端口或 backend-core REST API 暴露给计算节点。该入口的目标是复用主 server CLI 的既有鉴权和内网能力,让外部节点像“在主 server 上执行 CLI”一样完成自测。
+2
View File
@@ -44,3 +44,5 @@ Before claiming delivery, run these checks and keep their JSON output or screens
## Provider Upgrade Gate
When delivery explicitly includes upgrading a compute node such as D601 or D518, the automated E2E plan check is not sufficient. The operator must first bootstrap any legacy provider manually if it cannot yet schedule upgrades, then run `provider.upgrade` with `mode: "schedule"` against that Provider ID, confirm the task succeeds, confirm the node reconnects in the public frontend, and finally verify any required `host.ssh` capability with `bun scripts/cli.ts ssh <PROVIDER_ID> hostname`. This schedule check is a node-upgrade gate, not a replacement for the standard public frontend Playwright E2E gate.
External compute nodes should run that schedule check through the remote main-server passthrough form: `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> provider.upgrade --mode schedule --wait-ms 15000`. This proves the node can validate itself without direct access to backend-core REST or PostgreSQL.
+8
View File
@@ -62,6 +62,14 @@ backend-core 可以通过真实 WebSocket 调度向在线 provider 下发 `provi
旧版 provider-gateway 如果只能返回 plan 或因为旧环境中的 `PROVIDER_UPGRADE_ENABLED=false` 拒绝 schedule,需要先通过任意现有维护通道手动 bootstrap 一次。bootstrap 的目标不是长期流程,而是把节点更新到支持 always-enabled 远程升级和 Host SSH / WSL SSH 维护桥的版本;完成后必须立刻用 `bun scripts/cli.ts debug dispatch <PROVIDER_ID> provider.upgrade --mode schedule --wait-ms 15000` 做一次真实一键升级验证,再用 `bun scripts/cli.ts debug health` 或公网 frontend 确认该节点仍在线、`unideskCapabilities` 包含 `provider.upgrade`,需要 SSH 维护的 WSL 节点还必须包含 `host.ssh`
## Manual Upgrade Maintenance
手动升级只用于把旧节点 bootstrap 到支持 always-enabled 远程升级的版本;bootstrap 完成后,常规升级必须回到 `provider.upgrade schedule`。节点侧维护步骤是:进入节点本地 UniDesk 仓库,执行 `git pull --ff-only` 获取主 server 已推送版本;确认 `.state/provider-<ID>.env` 中存在 `PROVIDER_SERVER_URL=ws://74.48.78.17:18082/ws/provider``PROVIDER_ID=<ID>``PROVIDER_NAME=<ID>``PROVIDER_TOKEN``PROVIDER_LABELS_JSON``PROVIDER_UPGRADE_HOST_PROJECT_ROOT=/home/ubuntu/unidesk``PROVIDER_UPGRADE_WORKSPACE_PATH=/workspace``PROVIDER_UPGRADE_COMPOSE_FILE``PROVIDER_UPGRADE_ENV_FILE``PROVIDER_UPGRADE_COMPOSE_PROJECT``PROVIDER_UPGRADE_SERVICE=provider-gateway``PROVIDER_UPGRADE_RUNNER_IMAGE=unidesk_provider-gateway:<id>``DOCKER_SOCKET_PATH=/var/run/docker.sock``MONITOR_DISK_PATH=/`、心跳和重连参数。旧 env 文件中如果还残留 `PROVIDER_UPGRADE_ENABLED`,新版 provider-gateway 会忽略它;长期文档和新部署不得再依赖这个键。
如果节点已有专用 Compose,优先用节点本地 Compose 手动重建一次:`docker compose --env-file .state/provider-<ID>.env -f <compose-file> -p <compose-project> up -d --no-deps --build provider-gateway`。老版 `docker-compose` 可能在重建已存在容器时因为 `ContainerConfig` 兼容问题失败;此时只能移除目标 provider-gateway 容器后重新 `up -d --no-deps provider-gateway`,不得执行 `down -v``docker volume rm` 或任何会影响 database 命名卷的命令。如果节点当前只有 `docker run` 部署,则先构建镜像 `docker build -f src/components/provider-gateway/Dockerfile -t unidesk_provider-gateway:<id> .`,再以固定容器名重建:挂载 `/var/run/docker.sock:/var/run/docker.sock``/home/ubuntu/unidesk:/workspace:ro`、节点日志目录到 `/var/log/unidesk`,如需 WSL SSH 维护桥还要把只读私钥目录挂载到 `/run/host-ssh`,并使用同一个 `.state/provider-<ID>.env` 启动。无论 Compose 还是 `docker run`,容器名和镜像 tag 都必须带 Provider ID,便于 Docker 状态页、任务历史和节点本地排障互相对应。
手动升级完成后的判定标准固定为主 server 可观测结果,而不是节点容器 `running`:访问公网 frontend `http://74.48.78.17:18081/`,确认该 Provider 在线;随后在任意装有本仓库和主 server SSH key 的计算节点上执行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> provider.upgrade --mode schedule --wait-ms 15000`,确认任务 `succeeded` 且 result 包含 updater 容器信息;最后再次查看 frontend 或执行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 debug health`,确认节点重连和指标恢复。需要 Host SSH / WSL SSH 的节点,还必须执行 `bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh <PROVIDER_ID> hostname` 验证维护桥。
## Host SSH Maintenance Bridge
宿主 SSH / WSL SSH 转发只作为应急维护辅助路径,不用于自动计算任务调度。实现参考 `../web-terminal` 的经验:容器内使用只读挂载的私钥,主动连接宿主或 WSL sshd,并设置 `BatchMode=yes``StrictHostKeyChecking=accept-new``ServerAliveInterval=20``ServerAliveCountMax=3`。主 server Compose 会把 `config.json``sshForwarding.keyDir` 只读挂载为 `/run/host-ssh`provider 标签会上报 `hostSshConfigured``hostSshKeyPresent``hostSshTarget`,便于在前端节点清单确认维护桥是否具备条件。