Files
pikasTech-unidesk/docs/reference/provider-gateway.md
T
2026-05-05 13:23:53 +08:00

26 KiB
Raw Blame History

Provider Gateway Reference

Provider Gateway 是计算节点侧容器。它只主动连出到主 server 暴露的 provider ingress WebSocket,不要求计算节点有公网 IP,适合 NAT、内网和防火墙后的机器。

Main Server Self Provider

当前主 server 也运行一个 provider-gatewayproviderId 固定来自 config.jsonproviderGateway.id。这让单机环境也能验证完整的分布式调度闭环:frontend 发起任务,core 写数据库并通过 provider ingress WebSocket 下发,provider gateway 执行后回传状态。

Deployment Method

当前主 server 公网 IP 是 74.48.78.17config.json 中的 network.publicHost 必须保持为该地址;公网 frontend 入口是 http://74.48.78.17:18081/provider gateway 对外接入入口是 ws://74.48.78.17:18082/ws/providerprovider ingress 健康检查是 http://74.48.78.17:18082/health。主 server 本机 provider 由根目录 docker-compose.ymlprovider-gateway 服务启动,容器内使用 Docker 内网地址 ws://backend-core:8081/ws/provider 自接入;外部计算节点部署 provider-gateway 时必须改用公网 provider ingress URL,并复用 config.json / .state/docker-compose.env 中的 provider token、心跳间隔和重连参数。

计算节点部署 provider-gateway 的最小方法是:准备可运行 unidesk_provider-gateway 镜像的 Docker 环境,为节点分配唯一 PROVIDER_ID 与可读 PROVIDER_NAME,设置 PROVIDER_SERVER_URL=ws://74.48.78.17:18082/ws/providerPROVIDER_TOKENPROVIDER_LABELS_JSONHEARTBEAT_INTERVAL_MSRECONNECT_BASE_MSRECONNECT_MAX_MS,并挂载 /var/run/docker.sock:/var/run/docker.sock 作为 Docker 状态采集、任务执行和远程升级的唯一自动化通道。所有长期接入节点都必须配置 PROVIDER_UPGRADE_* 环境变量,把节点上的 UniDesk 仓库只读挂载到 PROVIDER_UPGRADE_WORKSPACE_PATH,并确保升级命令只重建 provider-gateway service,不影响 database、backend-core、frontend。provider-gateway 部署必须同时交付 Host SSH / WSL SSH 透传维护桥;WSL 节点应设置 HOST_SSH_HOST=host.docker.internalHOST_SSH_PORT=22HOST_SSH_USER=<WSL 用户>HOST_SSH_KEY=/run/host-ssh/id_ed25519HOST_REMOTE_CWD=/home/<WSL 用户>,并把只含维护私钥的宿主目录只读挂载到 /run/host-ssh

Mandatory SSH Passthrough Bundle

新增或重建 provider-gateway 时,Docker socket、远程升级和 SSH 透传必须作为同一个部署包验收,不能只让 provider 在线就认为完成。节点侧应先启动目标宿主或 WSL 的 sshd,把维护公钥写入目标用户 authorized_keys,再用只读目录挂载私钥到 provider-gateway 容器内 /run/host-sshprovider-gateway 环境变量必须包含 HOST_SSH_HOSTHOST_SSH_PORTHOST_SSH_USERHOST_SSH_KEYHOST_REMOTE_CWD。注册成功后,主 server 看到的 labels 必须同时满足 hostSshConfigured=truehostSshKeyPresent=truehostSshTarget 指向目标 sshd,且 unideskCapabilities 包含 host.ssh

计算节点镜像必须包含 ssh 客户端,否则 provider 虽然可以在线并执行 Docker 任务,但 host.ssh 调度会在节点侧失败。标准 src/components/provider-gateway/Dockerfile 已安装 openssh-client;如果节点使用本地兜底镜像或复制 Bun/Docker CLI 的自定义镜像,也必须同时安装或复制可用的 OpenSSH client,并在容器内通过 ssh -Vtest -r /run/host-ssh/id_ed25519ssh -i /run/host-ssh/id_ed25519 ... <target> hostname 做本地烟测后再接入主 server。

SSH 透传只作为维护桥,不作为普通计算任务和自动升级的执行通道。普通任务、Docker 状态采集和 provider.upgrade 仍必须走本地 Docker socket;SSH 透传用于节点诊断、人工修复和验证 WSL/宿主维护入口是否可达。

WSL Compute Node Deployment

WSL 计算节点和普通外部计算节点使用同一套 provider ingress 协议:节点不暴露入站端口,只需要从 WSL 主动连出到 ws://74.48.78.17:18082/ws/provider。已验证的 WSL 节点命名口径是短设备编号,例如 PROVIDER_ID=D601PROVIDER_NAME=D601 保持一致;新增 WSL 节点必须替换为唯一 ID,避免把旧节点状态覆盖到同一条 unidesk_nodes.provider_id 记录。

WSL 节点应优先使用 WSL 内部原生 Docker Engine 和 /var/run/docker.sock,让资源采样、Docker 状态和任务执行都反映 WSL 计算环境本身,而不是 Windows 或 Docker Desktop 的代理上下文。如果当前 Docker CLI 实际连接 Docker Desktop daemon,也可以先作为可用计算节点接入,但必须在 PROVIDER_LABELS_JSON 中显式标注 dockerContext=docker-desktop 或等价标签,避免在 frontend 中把 Docker Desktop 资源误判为 WSL 原生资源。UniDesk 仓库建议放在 WSL 原生文件系统,例如 /home/ubuntu/unidesk,再按需从 Windows 工作区同步源码;长期运行和升级挂载应使用 WSL 原生路径只读挂到容器内 /workspace,减少 /mnt/c 权限、性能和路径转换问题。

WSL provider 的最小环境文件应放在节点本地私有路径,例如 /home/ubuntu/unidesk/.state/provider-<ID>.env,并由 docker run --env-file 读取。PROVIDER_LABELS_JSON 在 Docker env-file 中可以写成单行 JSON;如果临时用 shell source 方式调试,必须对整段 JSON 加引号,否则 shell 会按 {} 和逗号拆分导致 JSON 解析失败。WSL 节点建议至少包含这些 labels:hostrole=wsl-providerwsl=truedistrodocker=true;运行时 provider-gateway 会自动追加 runtimedockerSocketPresentgatewayUptimeSeconds.state/provider-<ID>.envlogs/provider-<ID>/ 和容器日志属于节点本地运行态,必须保持在 .gitignore 覆盖范围内,不能提交 provider token、登录态或运行日志。

长期运行推荐用 systemd 管理 provider-gateway 容器,而不是只在交互 shell 中运行 Bun 进程。systemd unit 的稳定形态是:ExecStartPre=-docker rm -f unidesk-provider-gateway-<ID> 清理同名旧容器,ExecStart=docker run --name unidesk-provider-gateway-<ID> --env-file ... -v /var/run/docker.sock:/var/run/docker.sock -v /home/ubuntu/unidesk:/workspace:ro -v /home/ubuntu/unidesk/logs/provider-<ID>:/var/log/unidesk -v <ssh-key-dir>:/run/host-ssh:ro unidesk_provider-gateway:<id>ExecStop=docker stop unidesk-provider-gateway-<ID>,并设置 Restart=always。临时部署可以直接使用 docker run -d --restart unless-stopped,但仍要保证容器名、env 文件、日志目录、SSH 私钥只读挂载和镜像 tag 都带上节点 ID,便于 frontend、Docker 状态、SSH 透传和本地排障互相对应。provider.upgrade 是长期接入节点的必备能力,provider-gateway 不提供 PROVIDER_UPGRADE_ENABLED 或等价禁用开关;如果节点缺少升级环境变量或 SSH 透传环境变量,必须修正节点部署,而不是在服务端接受只能预检、不能升级或不能维护透传的半成品状态。

WSL 本身会在没有前台进程时被 Windows 回收;如果该节点要作为长期在线算力,必须通过 Windows 启动项、计划任务或后台 wsl.exe -d <distro> -u root -- bash -lc "systemctl start docker unidesk-provider-gateway-<ID>.service; exec sleep infinity" 这类 keepalive 进程保持发行版运行。仅启用 WSL 内 systemd service 不等价于 Windows 层面的常驻守护。

WSL Network And Proxy Bootstrap

WSL 节点出网异常时,先把代理设置固化到目标 WSL 用户的 ~/.bashrc,而不是只在当前 shell 临时 export。长期可复用的写法是在每次交互 shell 启动时从 /etc/resolv.conf 读取 Windows 宿主在 WSL NAT 中的 nameserver IP,再导出 http_proxyhttps_proxyHTTP_PROXYHTTPS_PROXYall_proxyALL_PROXY 指向 http://<windows-host-ip>:7890 / socks5://<windows-host-ip>:7890,并保留 no_proxy=localhost,127.0.0.1,::1,host.docker.internal。不要把某次启动看到的宿主 IP 当成永远不变的常量;动态读取可以避免 WSL 网络重建后代理失效。

Windows 代理程序常见默认只监听 127.0.0.1:7890,此时 WSL 访问 <windows-host-ip>:7890 会失败。可选修复是让代理程序监听 WSL 可达网卡,或在 Windows 用户态启动一个幂等 TCP relay,把 <windows-host-ip>:7890 转发到 127.0.0.1:7890netsh interface portproxy 通常需要管理员权限,不应作为普通节点 bootstrap 的唯一方案。.bashrc 可以在发现 <windows-host-ip>:7890 不可达时调用 Windows 侧脚本启动该 relay,但 relay 脚本、临时 apt source、日志和节点私钥都属于本地运行态,必须留在 .state 或用户目录,不能提交到仓库。

apt 或镜像构建遇到 archive.ubuntu.com 超时、代理 503 或 registry metadata 拉取失败时,优先使用节点侧临时镜像源或临时 apt sources 完成 bootstrap,例如把 Ubuntu 源临时替换到可达镜像后安装 openssh-server。这类网络兜底只解决节点初始化,不改变 PROVIDER_SERVER_URL、provider token、Docker socket、Host SSH 透传和 remote CLI 验收标准。

WSL Image Build Fallback

标准镜像构建路径使用 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 本地 bundockerdocker-compose plugin 到镜像内,再复制 src/components/provider-gateway/srcsrc/components/shared/src。该镜像必须能在容器内执行 bun --versiondocker versiondocker compose versionssh -V,并通过挂载的 /var/run/docker.sock 执行 docker infodocker ps;只有这些命令通过后才能作为 unidesk_provider-gateway:<provider-id> 运行。该兜底镜像只改变节点侧交付方式,不改变 PROVIDER_SERVER_URL、token、heartbeat、labels、Docker socket、SSH 私钥只读挂载和服务端验收标准。

如果兜底镜像还要承载 WSL SSH 透传,必须同时复制 /usr/bin/ssh/etc/ssh/ssh_config/etc/ssh/ssh_config.d 以及 ldd /usr/bin/ssh 输出的全部动态库,尤其不能漏掉 /lib64/ld-linux-x86-64.so.2 这类 ELF loader。只在 rootfs 中看到 /usr/bin/ssh 文件不代表可执行;验收必须运行 docker run --rm <image> /bin/sh -lc '/usr/bin/ssh -V && /usr/bin/docker compose version',再以实际 provider 容器执行 ssh -T -i /run/host-ssh/id_ed25519 -p 22 ubuntu@host.docker.internal hostname。若 Compose 使用 Docker bridge 网络,WSL 节点必须在 compose 文件中加入 extra_hosts: ["host.docker.internal:host-gateway"],否则容器内可能无法把 host.docker.internal 解析到 WSL 宿主。

Deployment Verification

provider-gateway 部署是否成功必须以 UniDesk frontend 中可见的 Provider 信息为准,不能只看节点容器 running。验证时访问 http://74.48.78.17:18081/,使用配置中的账号密码登录,进入 资源节点 / 节点清单,确认目标 PROVIDER_IDPROVIDER_NAMEonline 状态、lastHeartbeat 和 labels 可见;点击该节点的 查看原始JSON,确认 raw payload 中的 providerIdnamestatuslabels 与部署环境变量一致。随后进入 资源节点 / 资源监控,确认该 Provider 有 CPU、实际内存和硬盘采样曲线;进入 资源节点 / Docker 状态,确认 Docker daemon、containers、images、volumes、networks 已渲染出来,且 dockerSocketPresent 或 Docker ready 状态与预期一致。只有这些前端信息都能通过 UniDesk 正常读取,才说明 provider-gateway 已经真正挂载到主 server。

WSL 节点还应补充一次真实调度验证:向该 PROVIDER_ID 下发 docker.ps,任务必须从 dispatched 进入 succeeded,并在结果中看到 WSL Docker daemon 返回的容器列表;对于容器化运行的 provider-gateway,列表中通常应包含 unidesk-provider-gateway-<PROVIDER_ID>。这一步可以同时证明 provider WebSocket、服务端任务路由、节点侧 Docker socket 和结果回传链路都已贯通。

SSH 透传自测是 provider-gateway 部署验收的一部分。目标 Provider 在线后,先确认 frontend 节点清单或 debug health 中该节点 labels 显示 hostSshConfigured=truehostSshKeyPresent=true 且能力包含 host.ssh;再运行 bun scripts/cli.ts debug dispatch <PROVIDER_ID> host.ssh --wait-ms 15000,任务必须 succeededresult 中 probeLine 必须包含 UNIDESK_SSH_TESTexitCode=0;最后运行 bun scripts/cli.ts ssh <PROVIDER_ID> hostname,输出必须是目标宿主或 WSL 的 hostname,进程退出码必须为 0。任何 provider 在线但不声明 host.ssh 的状态都只能算未完成部署。

自动化验证必须使用 Playwright 访问公网 frontend,而不是在容器内直接调 core API 代替浏览器验收。标准命令是 bun scripts/cli.ts e2e run;该命令会让 Playwright 打开公网 http://74.48.78.17:18081/、登录、抓取页面中的 Provider 信息和 查看原始JSON 内容,并检查 Provider 自接入、资源指标、Docker 状态和 provider.upgrade 预检。外部新增节点的人工验收应复用同一套前端路径:先确认 Provider 信息出现在节点清单,再确认资源监控和 Docker 状态页面有该节点的数据,最后通过任务调度向该 Provider 下发 echodocker.ps 或维护专用 host.ssh probe,并在任务历史中查看耗时、状态、stdout/stderr 摘要和失败原因。

Provider Ingress

provider ingress 是唯一允许公网暴露的 provider 连接接口,当前由 backend-core 容器的独立端口提供 /ws/provider/health。backend-core REST API 仍只在 Docker 内网开放,外部计算节点只应连接 provider ingress。

Docker Socket Path

自动任务执行只允许走本地 Docker socket。Compose 将 /var/run/docker.sock 挂入 provider-gatewayprovider 标签会报告 dockerSocketPresentdocker.ps 调试任务会通过该 socket 查询宿主 Docker 容器。

Gateway Version Metadata

provider-gateway 必须从自身 package.json 读取版本号,并在 register 与 heartbeat labels 中上报 providerGatewayNameproviderGatewayVersionproviderGatewayStartedAtproviderGatewayUpgradePolicy。backend-core 将这些 labels 合并到 unidesk_nodes.labels,frontend 在节点清单、资源监控和 资源节点 / 网关版本 中展示;旧节点缺少这些字段时只能显示版本未知,不能用猜测值替代。unideskCapabilitieshostSshConfiguredhostSshKeyPresenthostSshTarget 也是 WebUI 运维可用性徽标的数据源,用于直接显示每个计算节点的 SSH 透传可用性与远程更新可用性。

Docker Status Telemetry

provider-gateway 连接成功后必须周期性上报 Docker daemon 状态,数据来源是本地 Docker socket 上的 docker infodocker ps -adocker imagesdocker volume lsdocker network ls。backend-core 将最新快照保存到 unidesk_node_docker_statusfrontend 的资源节点 Docker 状态 子标签用该快照渲染 Docker Desktop 风格视图;该能力仍然只通过 provider 主动上报,不要求主 server 反向连接计算节点。

System Status Telemetry

provider-gateway 连接成功后必须周期性上报节点 CPU、内存和硬盘用量。采集来源是节点本地 /proc/stat/proc/loadavg/proc/meminfodf -PB1backend-core 将最新快照保存到 unidesk_node_system_status,并将历史采样保存到 unidesk_node_metric_samples 供 frontend 绘制任务管理器风格曲线。内存使用量采用实际占用口径:MemTotal - MemFree - Buffers - Cached - SReclaimable + Shmem,也就是不把 Linux page cache / buffer 计入占用;上报中同时保留 cacheBytes 便于排查。该链路仍然由 provider 主动上报,主 server 不反向探测计算节点。

Remote Provider Upgrade

backend-core 可以通过真实 WebSocket 调度向在线 provider 下发 provider.upgrademode: "plan" 只返回升级计划,用于 E2E 和人工预检;mode: "schedule" 会要求 provider-gateway 通过本地 Docker socket 启动一个 detached updater 容器,由 updater 在节点本地执行 docker compose up -d --no-deps --build provider-gateway--no-deps 是强制要求,升级 provider-gateway 时不得重建或停止 database、backend-core、frontend。升级执行路径使用 Docker socket 和只读仓库挂载,不使用 Host SSH 维护桥作为自动调度通道。

远程升级策略固定为 always-enabled:只要 provider-gateway 在线并声明 provider.upgrademode: "schedule" 就必须真正调度升级容器,不允许被 PROVIDER_UPGRADE_ENABLED=false、前端隐藏按钮或服务端特殊名单禁用。升级能力的安全边界不是开关,而是显式 PROVIDER_UPGRADE_* 配置、Docker socket 权限、只读仓库挂载、固定 Compose service 和 --no-deps 约束。升级计划中必须展示 policy: "always-enabled"、updater 容器名、runner image、workspace、Compose project/service、env file、compose file 和实际 docker run 命令,方便前端任务历史与 CLI debug 直接诊断。

自动更新记录的权威来源是 backend-core 保存的 provider.upgrade 任务历史,而不是 provider-gateway 容器日志文件。frontend 必须按 Provider 聚合这些任务,并把状态、模式、task id、来源、耗时、策略、updater 容器摘要、失败原因和更新时间渲染为表格或卡片;完整 task/result JSON 只能由操作员点击 查看原始JSON 后查看。

旧版 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/providerPROVIDER_ID=<ID>PROVIDER_NAME=<ID>PROVIDER_TOKENPROVIDER_LABELS_JSONPROVIDER_UPGRADE_HOST_PROJECT_ROOT=/home/ubuntu/unideskPROVIDER_UPGRADE_WORKSPACE_PATH=/workspacePROVIDER_UPGRADE_COMPOSE_FILEPROVIDER_UPGRADE_ENV_FILEPROVIDER_UPGRADE_COMPOSE_PROJECTPROVIDER_UPGRADE_SERVICE=provider-gatewayPROVIDER_UPGRADE_RUNNER_IMAGE=unidesk_provider-gateway:<id>DOCKER_SOCKET_PATH=/var/run/docker.sockMONITOR_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 -vdocker 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 在线;随后在任意装有本仓库且 config.json 含正确 frontend 登录凭据的计算节点上执行 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,确认节点重连、指标恢复、labels 中 host.ssh 能力存在。每个 provider-gateway 手动升级后都必须用 remote CLI 再执行 bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> host.ssh --wait-ms 15000bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh <PROVIDER_ID> hostname,验证维护桥没有在升级后丢失;该 remote CLI 默认走公网 frontend,不需要指定 --main-server-key

Host SSH Maintenance Bridge

宿主 SSH / WSL SSH 转发是 provider-gateway 部署的必备维护能力,但只作为应急维护辅助路径,不用于自动计算任务调度。实现参考 ../web-terminal 的经验:容器内使用只读挂载的私钥,主动连接宿主或 WSL sshd,并设置 BatchMode=yesStrictHostKeyChecking=accept-newServerAliveInterval=20ServerAliveCountMax=3。主 server Compose 会把 config.jsonsshForwarding.keyDir 只读挂载为 /run/host-sshprovider 标签会上报 hostSshConfiguredhostSshKeyPresenthostSshTarget,便于在前端节点清单确认维护桥是否具备条件。

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: succeededprobeLineUNIDESK_SSH_TESTexitCode: 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 healthbun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> host.ssh --wait-ms 15000bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh <PROVIDER_ID> hostname;默认 remote CLI 走公网 frontend 登录态,不需要主 server SSH key。健康检查必须能看到该 Provider 在线、hostSshConfigured=truehostSshKeyPresent=truehostSshTarget 正确、unideskCapabilities 包含 host.sshprobe 必须返回 UNIDESK_SSH_TESTssh <PROVIDER_ID> hostname 必须输出目标 WSL/宿主 hostname 且 exit code 为 0。如果 D518 这类 WSL 节点没有公网 SSH 入口,也必须通过这个 provider-gateway 自连维护桥完成验证,而不是要求主 server 直接连节点公网 22 端口;旧版 provider 未声明 host.ssh 时必须先升级 provider-gateway,否则 core 会拒绝 SSH 透传。