docs: capture compute ssh passthrough lessons

This commit is contained in:
lyon
2026-05-05 12:32:39 +08:00
parent fea954f9ab
commit 6ffc06ed1f
+6 -2
View File
@@ -16,6 +16,8 @@ Provider Gateway 是计算节点侧容器。它只主动连出到主 server 暴
新增或重建 provider-gateway 时,Docker socket、远程升级和 SSH 透传必须作为同一个部署包验收,不能只让 provider 在线就认为完成。节点侧应先启动目标宿主或 WSL 的 sshd,把维护公钥写入目标用户 `authorized_keys`,再用只读目录挂载私钥到 provider-gateway 容器内 `/run/host-ssh`provider-gateway 环境变量必须包含 `HOST_SSH_HOST``HOST_SSH_PORT``HOST_SSH_USER``HOST_SSH_KEY``HOST_REMOTE_CWD`。注册成功后,主 server 看到的 labels 必须同时满足 `hostSshConfigured=true``hostSshKeyPresent=true``hostSshTarget` 指向目标 sshd,且 `unideskCapabilities` 包含 `host.ssh`
计算节点镜像必须包含 `ssh` 客户端,否则 provider 虽然可以在线并执行 Docker 任务,但 `host.ssh` 调度会在节点侧失败。标准 `src/components/provider-gateway/Dockerfile` 已安装 `openssh-client`;如果节点使用本地兜底镜像或复制 Bun/Docker CLI 的自定义镜像,也必须同时安装或复制可用的 OpenSSH client,并在容器内通过 `ssh -V``test -r /run/host-ssh/id_ed25519``ssh -i /run/host-ssh/id_ed25519 ... <target> hostname` 做本地烟测后再接入主 server。
SSH 透传只作为维护桥,不作为普通计算任务和自动升级的执行通道。普通任务、Docker 状态采集和 `provider.upgrade` 仍必须走本地 Docker socket;SSH 透传用于节点诊断、人工修复和验证 WSL/宿主维护入口是否可达。
## WSL Compute Node Deployment
@@ -34,7 +36,7 @@ WSL 本身会在没有前台进程时被 Windows 回收;如果该节点要作
标准镜像构建路径使用 `src/components/provider-gateway/Dockerfile`,基础镜像为 `oven/bun:1-alpine`,并在镜像内安装 Bun、Docker CLI、Compose plugin、`df` 和 provider-gateway 源码。WSL 或 Docker Desktop 环境中的 registry mirror、DNS 或代理配置可能导致 `oven/bun` 元数据拉取失败;此时不要修改 provider ingress 协议或服务端配置,应改用节点侧镜像交付兜底。
可复用的兜底方式是使用本机已存在的 Debian/Node 基础镜像,复制 WSL 本地 `bun``docker``docker-compose` plugin 到镜像内,再复制 `src/components/provider-gateway/src``src/components/shared/src`。该镜像必须能在容器内执行 `bun --version``docker version``docker compose version`,并通过挂载的 `/var/run/docker.sock` 执行 `docker info``docker ps`;只有这些命令通过后才能作为 `unidesk_provider-gateway:<provider-id>` 运行。该兜底镜像只改变节点侧交付方式,不改变 `PROVIDER_SERVER_URL`、token、heartbeat、labels、Docker socket 挂载和服务端验收标准。
可复用的兜底方式是使用本机已存在的 Debian/Node 基础镜像,复制 WSL 本地 `bun``docker``docker-compose` plugin 到镜像内,再复制 `src/components/provider-gateway/src``src/components/shared/src`。该镜像必须能在容器内执行 `bun --version``docker version``docker compose version``ssh -V`,并通过挂载的 `/var/run/docker.sock` 执行 `docker info``docker ps`;只有这些命令通过后才能作为 `unidesk_provider-gateway:<provider-id>` 运行。该兜底镜像只改变节点侧交付方式,不改变 `PROVIDER_SERVER_URL`、token、heartbeat、labels、Docker socket、SSH 私钥只读挂载和服务端验收标准。
## Deployment Verification
@@ -88,8 +90,10 @@ backend-core 可以通过真实 WebSocket 调度向在线 provider 下发 `provi
宿主 SSH / WSL SSH 转发是 provider-gateway 部署的必备维护能力,但只作为应急维护辅助路径,不用于自动计算任务调度。实现参考 `../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`,便于在前端节点清单确认维护桥是否具备条件。
WSL 计算节点使用 Docker Desktop daemon 时,provider-gateway 容器通常应连接 `host.docker.internal:22`,目标是当前 WSL 发行版里的 sshd,而不是给节点开放公网 SSH。节点侧必须确认 sshd 监听 `22`、目标用户可用维护公钥免密登录、`authorized_keys` 与挂载到 `/run/host-ssh/id_ed25519` 的私钥匹配;如果容器内直连 `host.docker.internal` 都失败,先修复 WSL sshd、Docker Desktop host gateway 或密钥权限,再排查 UniDesk WebSocket 透传。
维护桥通过真实 WebSocket dispatch 暴露为 `host.ssh` 命令。默认 payload 使用 `mode: "probe"`,远端只执行一个短命令并返回 `UNIDESK_SSH_TEST user=... host=... bridge=host.ssh cwd=...`;需要人工诊断时可以显式使用 `mode: "exec"``command` 字段执行有界命令。所有 `host.ssh` 执行都必须有超时,stdout/stderr 在 task result 中截断展示;自动升级和普通任务仍必须使用 Docker socket 与 `provider.upgrade`,不得把 WSL SSH 维护桥当成调度通道。
面向人的终端入口是 `bun scripts/cli.ts ssh <PROVIDER_ID> [ssh-like args...]`。无后续参数时打开远端登录 shell,有后续参数时执行远端命令并返回远端 exit code;该入口走 backend-core 内网 `/ws/ssh` broker 和 provider 既有 WebSocket,不新增公网 core 端口。传统 ssh 传输参数由 provider-gateway 环境变量统一控制,CLI 只负责把 Provider ID 后的远端命令和终端 stdin/stdout/stderr 透传过去。
验证 WSL SSH 桥时,先在目标 WSL 中启动 sshd 并确保维护公钥写入目标用户的 `authorized_keys`,再确认目标 provider 注册 labels 中 `unideskCapabilities` 包含 `host.ssh`。运行 `bun scripts/cli.ts debug dispatch <PROVIDER_ID> host.ssh --wait-ms 15000` 后,结果应在 `debug task latest` 或前端任务历史中显示 `status: succeeded``probeLine``UNIDESK_SSH_TEST``exitCode: 0`,并且目标节点 labels 中 `hostSshKeyPresent` 为 true;随后运行 `bun scripts/cli.ts ssh <PROVIDER_ID> hostname` 验证近似原生 ssh 的远端命令体验。在计算节点本机自测时,使用 remote CLI 透传同一组命令:`bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> host.ssh --wait-ms 15000``bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh <PROVIDER_ID> hostname`。如果 D518 这类 WSL 节点没有公网 SSH 入口,也必须通过这个 provider-gateway 自连维护桥完成验证,而不是要求主 server 直接连节点公网 22 端口;旧版 provider 未声明 `host.ssh` 时必须先升级 provider-gateway,否则 core 会拒绝 SSH 透传。
验证 WSL SSH 桥时,先在目标 WSL 中启动 sshd 并确保维护公钥写入目标用户的 `authorized_keys`,再确认目标 provider 注册 labels 中 `unideskCapabilities` 包含 `host.ssh`。运行 `bun scripts/cli.ts debug dispatch <PROVIDER_ID> host.ssh --wait-ms 15000` 后,结果应在 `debug task latest` 或前端任务历史中显示 `status: succeeded``probeLine``UNIDESK_SSH_TEST``exitCode: 0`,并且目标节点 labels 中 `hostSshKeyPresent` 为 true;随后运行 `bun scripts/cli.ts ssh <PROVIDER_ID> hostname` 验证近似原生 ssh 的远端命令体验。在计算节点本机自测时,使用 remote CLI 透传同一组命令:`bun scripts/cli.ts --main-server-ip 74.48.78.17 debug health``bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> host.ssh --wait-ms 15000``bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh <PROVIDER_ID> hostname`;默认 remote CLI 走公网 frontend 登录态,不需要主 server SSH key。健康检查必须能看到该 Provider 在线、`hostSshConfigured=true``hostSshKeyPresent=true``hostSshTarget` 正确、`unideskCapabilities` 包含 `host.ssh`probe 必须返回 `UNIDESK_SSH_TEST``ssh <PROVIDER_ID> hostname` 必须输出目标 WSL/宿主 hostname 且 exit code 为 0。如果 D518 这类 WSL 节点没有公网 SSH 入口,也必须通过这个 provider-gateway 自连维护桥完成验证,而不是要求主 server 直接连节点公网 22 端口;旧版 provider 未声明 `host.ssh` 时必须先升级 provider-gateway,否则 core 会拒绝 SSH 透传。