远端网关:Docker、HTTPS 与私有管理
从匹配部署包构建网关,配置持久目录、HTTPS、SSH 配对及重启与回滚检查。
开发者接入什么情况下需要远端网关#
需要电脑离线时仍接收业务事件、需要固定 HTTPS 地址时,可以将网关部署到自己的服务器。助手仍在指定 Onevium 设备执行;网关不会把离线电脑变成在线执行器。离线任务只在允许期限内排队。
界面截图使用隔离演示数据,令牌为空、草稿未保存等状态均按图注说明。部署后请完成下方连接检查。
前提:先取得匹配部署包#
继续前应具备:
- 与桌面版本匹配的完整部署源码包,包含
server/gateway/Dockerfile、compose.example.yml及 Dockerfile 引用的协议和 workers 文件。 - 可用的 Docker Engine 与 Compose v2、服务器 SSH 权限、域名和有效 TLS 证书。
- 专用持久目录,以及有该目录权限的服务器账号。
- 可用的 Onevium 安装和模型连接。
没有部署包时先向维护者获取。本文不提供未经确认的公共镜像,也不要求普通用户 clone 私有仓库。下文镜像名只是在你服务器上构建的本地标签。
所有 Docker 命令在服务器的部署包根目录运行;SSH 转发命令则在运行 Onevium 的电脑执行。
地址只填 origin: 网关设置、ONEVIUM_GATEWAY_PUBLIC_URL,以及 API 示例的 GATEWAY_URL 都只含协议、主机和可选端口。若界面“API 地址”为 https://gateway.example.com/api/v1,这些值应填 https://gateway.example.com,去掉末尾 /api/v1。私有管理地址也只填 http://127.0.0.1:8430,不追加管理路径。
第一步:保存远端模式并导出设备公钥#
在 Onevium 打开「渠道 → 外部接入 → 外部接入设置 → 连接」:
- 「网关位置」选「远端网关」。
- 「网关地址」填计划使用的
https://gateway.example.com,不追加/api/v1。 - 展开「远端高级设置」,「管理连接」选「通过 SSH 私有连接」;私有管理地址可先填
http://127.0.0.1:8430,令牌暂不填。 - 先保存。切换连接方式会暂停外部接入;保存后才可点击「导出设备公钥」。
- 导出
onevium-device-public.json,通过已核验的 SSH 连接上传到服务器。
输入远端网关的 HTTPS 地址;切换连接方式在保存后生效。
文件包含 owner_id、device_id 和 public_key,不含私钥。不要另外生成私钥来替代桌面的执行身份。导出不表示已经配对、开启监听或发布服务。
第二步:构建本地镜像#
在匹配部署包根目录运行:
docker build -f server/gateway/Dockerfile \
-t onevium-gateway:preview-c2409f75f .
该 Dockerfile 使用 Node 24.15.0,镜像内安装并构建所需依赖。无需在日常 Onevium 安装目录执行 native rebuild。构建成功只得到镜像,不代表服务已启动。
准备一个新的专用数据目录。使用之后建立 SSH 转发的服务器账号核对 UID/GID:
id -u
id -g
下面示例把数据放在 /srv/onevium-gateway;确认它不是别的服务目录,再按本机权限创建:
sudo install -d -m 700 -o "$(id -u)" -g "$(id -g)" /srv/onevium-gateway
已有部署不要重新初始化或更换归属。SQLite 存储应使用支持本机文件锁的磁盘/块存储,不当作多主机共享数据库。
第三步:配置 Compose 与环境变量#
在部署包根目录创建 gateway.env。将 UID/GID 换成上一步输出,将域名和路径换成实际值:
GATEWAY_UID=1000
GATEWAY_GID=1000
ONEVIUM_GATEWAY_IMAGE=onevium-gateway:preview-c2409f75f
ONEVIUM_GATEWAY_DATA_PATH=/srv/onevium-gateway
ONEVIUM_GATEWAY_PUBLIC_URL=https://gateway.example.com
ONEVIUM_GATEWAY_ENABLED=1
ONEVIUM_GATEWAY_ACCEPTING_REQUESTS=0
ONEVIUM_GATEWAY_CALLBACK_HOSTS=
| 变量 | 作用 |
|---|---|
GATEWAY_UID/GID | 容器进程与 SSH 管理账号使用匹配文件权限 |
ONEVIUM_GATEWAY_DATA_PATH | 挂到容器 /data 的持久目录 |
ONEVIUM_GATEWAY_PUBLIC_URL | 公网 HTTPS origin;也是公开请求的 Host 校验依据 |
ONEVIUM_GATEWAY_ENABLED=1 | 显式启动服务器监听 |
ONEVIUM_GATEWAY_ACCEPTING_REQUESTS=0 | 初次配置期间拒绝新任务,保留管理与已有查询通道 |
ONEVIUM_GATEWAY_CALLBACK_HOSTS | 逗号分隔的精确回调域名;空值拒绝全部回调 |
部署包的 compose.example.yml 将容器 0.0.0.0:8420 映射为宿主 127.0.0.1:8420。不要改成向公网直接开放 8420。
基础 Compose 没有把接纳开关和回调名单传入容器。再创建 gateway.override.yml:
services:
gateway:
image: "${ONEVIUM_GATEWAY_IMAGE:?Set the local image tag}"
environment:
ONEVIUM_GATEWAY_ENABLED: "${ONEVIUM_GATEWAY_ENABLED:-1}"
ONEVIUM_GATEWAY_ACCEPTING_REQUESTS: "${ONEVIUM_GATEWAY_ACCEPTING_REQUESTS:-0}"
ONEVIUM_GATEWAY_CALLBACK_HOSTS: "${ONEVIUM_GATEWAY_CALLBACK_HOSTS:-}"
这一步不可省略;只在 gateway.env 中增加变量不会自动让未引用的变量进入容器。先验证合并配置:
docker compose --env-file gateway.env -p onevium-gateway \
-f server/gateway/compose.example.yml -f gateway.override.yml config --quiet
第四步:初始化身份并启动暂停接纳的网关#
把挂载参数中的公钥文件换成服务器上真实绝对路径,再执行:
docker compose --env-file gateway.env -p onevium-gateway \
-f server/gateway/compose.example.yml -f gateway.override.yml run --rm --no-deps --pull never \
-v /srv/onevium-device-public.json:/device-public.json:ro \
gateway init --identity-file /device-public.json
预期看到 Gateway identity initialized. No listener started.。初始化只写一次身份配置;如果提示文件已存在,先确认是否是已有部署,不要删除配置强行重试。Compose run在这里运行一次性初始化命令,不发布服务端口。
然后启动:
docker compose --env-file gateway.env -p onevium-gateway \
-f server/gateway/compose.example.yml -f gateway.override.yml up -d --no-build --pull never gateway
检查私有管理与日志:
docker compose --env-file gateway.env -p onevium-gateway \
-f server/gateway/compose.example.yml -f gateway.override.yml exec -T gateway node dist/cli.cjs manage --path state
docker compose --env-file gateway.env -p onevium-gateway \
-f server/gateway/compose.example.yml -f gateway.override.yml logs --tail 50 gateway
预期管理命令返回状态 JSON,启动日志包含 status: listening、public_management: false。这是应检查的结果,不是本文代你完成的实测。
第五步:配置公网 HTTPS 反向代理#
下面示例假定 Nginx 已安装并运行,代理与网关在同一服务器。将此 server 块加入你的站点配置,并替换域名与有效证书路径:
server {
listen 443 ssl;
server_name gateway.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
client_max_body_size 20m;
location / {
proxy_pass http://127.0.0.1:8420;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_buffering off;
}
}
先检查语法,成功后再加载;检查失败时先修复,不执行 reload:
sudo nginx -t
sudo nginx -s reload
必须保留公网 Host、传递 WebSocket 升级头,并关闭代理缓冲以供 SSE 使用。Nginx 官方 WebSocket 说明解释了升级头为什么需要显式转发。
这是 Docker 远端网关配置;不要套用“内置网关把上游 Host 改为 loopback”的规则。更不能反代 Onevium 的原网页/管理端口。
从有权访问的客户端检查:
curl -sS -o /dev/null -w '%{http_code}\n' \
https://gateway.example.com/api/v1/management/state
预期为 404。公网不开放管理接口;浏览器脚本带 Origin 的直接业务请求也会被拒绝。业务访问应来自你的后端。
第六步:建立 SSH 私有管理并配对#
管理 socket 在容器 /data/control/gateway.sock,对应宿主 /srv/onevium-gateway/control/gateway.sock。目录权限为 700,socket 和控制令牌为 600。
在服务器受信任终端取得控制令牌:
docker compose --env-file gateway.env -p onevium-gateway \
-f server/gateway/compose.example.yml -f gateway.override.yml exec -T gateway node dist/cli.cjs management-token
输出是敏感的私有管理令牌,只粘贴到 Onevium 对应密码字段,不写入 URL、代码或日志截图。
在 Onevium 所在电脑开启转发,并保持此终端连接:
ssh -o ExitOnForwardFailure=yes -N \
-L 127.0.0.1:8430:/srv/onevium-gateway/control/gateway.sock \
gateway-user@YOUR_SERVER
使用已核验的 SSH 主机和密钥,不关闭主机校验。SSH 用户必须有宿主 socket 权限。-L 的本地地址明确绑定 loopback;OpenSSH 手册说明了本地端口到远端 Unix socket 的转发形式。
返回 Onevium 远端高级设置,核对:
| 字段 | 本例值 |
|---|---|
| 网关地址 | https://gateway.example.com |
| 管理连接 | 通过 SSH 私有连接 |
| 私有管理地址 | http://127.0.0.1:8430 |
| 私有管理令牌 | 上一步取得的 control-token |
私有管理字段近景:填写地址与令牌,保存后再配对。图中令牌为空,草稿尚未保存。
保存后点击「配对当前设备」。预期提示设备已配对;若失败,先查 SSH 与私有管理,不要把管理地址改成公网 /management。仅有公网 URL 不足以管理自托管网关。
第七步:发布服务、允许接纳并做一次真实调用#
- 在远端模式下创建或选择应用,配置助手与项目能力。
- 运行能力检查,通过后点「发布服务」。流程见外部接入。
- 把服务器
gateway.env的ONEVIUM_GATEWAY_ACCEPTING_REQUESTS改为1,重新执行上面的up -d --no-build --pull never gateway命令,使环境变更进入容器。 - 在 Onevium 应用页面点「启用外部接入」,确认连接状态。
- 用该应用的密钥和已认证主体提交一个只回复测试文字的请求,保存回执,再查询实际 Run 结果。
看到 202、容器 running、设备 paired 都不能单独证明闭环完成。 应看到同一 run_id 从接纳走到真实终态,并在后端取得正确结果。API 和 SSE 示例见会话,凭据范围见身份认证。
需要结果回调时,把精确域名加入服务器 ONEVIUM_GATEWAY_CALLBACK_HOSTS,重新应用 Compose 配置,再配置回调。它只接受公网 HTTPS/443,空名单、内网或 localhost 不会放行。详见Webhook 与回调。
重启后验证什么#
先停止测试发送方,并等已有任务到终态或完成必要核对,再重启网关:
docker compose --env-file gateway.env -p onevium-gateway \
-f server/gateway/compose.example.yml -f gateway.override.yml restart gateway
restart 用于同一配置的重启;修改 env 或镜像后使用本教程的 up 命令重新创建容器。Compose 会保留挂载目录,见官方 up 说明。
检查四件事:
- 私有管理仍可读取,应用和设备身份未变。
- 原应用密钥仍可查询旧 Run 和会话。
- 已完成附件仍能下载,内容校验一致。
- Onevium 恢复连接后,没有把“已开始但结果未知”的工作当新任务重跑。
未知结果可能处于 reconciling、pending_sync 等状态,需要实际确认。服务器在线只能接纳并限期排队,不能让休眠电脑执行任务。
暂停、备份与回滚#
- 暂停业务发送方,检查当前 Run;确认终态或记录待核对项。
- 将
ONEVIUM_GATEWAY_ACCEPTING_REQUESTS=0后重新应用 Compose,验证新任务返回 503、旧结果仍可查询。 - 在 Onevium 暂停外部接入。需要一致备份时停止网关,再复制完整持久目录到一个新的受限备份位置。
docker compose --env-file gateway.env -p onevium-gateway \
-f server/gateway/compose.example.yml -f gateway.override.yml stop gateway
备份应包含身份配置、数据库及相关文件、私有控制凭据和附件。不要仅复制运行中的单个 SQLite 文件,不要用 down -v 或删除 /data 作为回滚步骤。
回退镜像前先确认它与当前数据格式兼容。不能确认时保持暂停,使用维护者提供的兼容版本或匹配快照。恢复旧快照可能遗漏之后已发生的执行与回调,必须核对,不能自动重放业务副作用。恢复后先保持接纳为 0,检查身份、旧数据与连接,再允许新请求。
常见失败与定位#
| 现象 | 先查哪里 |
|---|---|
| 构建缺文件 | 是否拿到完整匹配包,是否在包根目录 build |
| init 文件已存在 | 是否已初始化;不要覆盖已有 owner/device 身份 |
| 容器启动后退出 | enabled、server-config.json、目录权限、日志 |
| 地址正确却 403 | PUBLIC_URL 与实际 Host、反代是否保留 Host、请求是否带 Origin |
| 502/WSS 断开 | 宿主 8420 监听、TLS 代理、Upgrade 头与超时 |
| 私有管理 401/无法连接 | control-token、SSH 转发存活、loopback 地址、socket UID/GID |
| 配对按钮不可用 | 是否先保存、是否仍有草稿、私有地址与令牌是否已配置 |
| 202 长时间未完成 | Onevium 在线状态、助手发布/能力、审批与 Run 状态 |
| 改了 env 没生效 | 是否通过 override 传入,并重新执行 up 而非只 restart |
| 重启后数据消失 | DATA_PATH 是否变化、是否误用了新 volume;不要重新初始化掩盖问题 |
下一步与验收边界#
保留本次镜像标签、部署配置和数据备份位置。记录真实 API、模型执行、SSH、TLS、SSE、回调以及重启恢复的结果。完成这些检查前,状态应写“部署待验收”,不能写“生产已上线”。
继续阅读身份认证、业务会话和Webhook 与结果回调。