跳转到内容

部署

面向平台运维人员。这些任务会影响整个部署。请按任务要求准备服务器访问权限或平台管理权限。从管理员手册开始。

本页介绍如何在生产环境中运行 OpenBot。你要构建 Docker 镜像,准备数据库,设置平台,然后在反向代理后面启动服务器。每个设置项的说明,请看配置。


  • 一台装有 Docker 和 Docker Compose 的 Linux 服务器。
  • 一个给 OpenBot 用的域名,例如 api.example.com,以及它的 TLS 证书。
  • 一个给平台用的 OpenID Connect 提供方,例如 https://id.example.com。在其中注册一个客户端,重定向 URI 为 https://api.example.com/auth/callback/oidc。如果用户只通过组织的 SSO 连接登录,可以跳过这一项。
  • 一个模型服务,如果你想让 Bot(机器人)干活的话。设置完成后,通过 API 添加它。请看模型。

所有 Docker 文件都在 deploy/docker/ 中。一个 Dockerfile 生成两个镜像。每个镜像是一个构建目标(文件中一个有名字的最终阶段):

目标 镜像 运行什么
openbot openbot OpenBot 和它的迁移程序。
protocol-test openbot-protocol-test App Protocol 的测试服务。请看协议测试。

文件 docker-bake.hcl 告诉 Docker Bake 如何构建它们。在仓库根目录运行:

Terminal window
export OPENBOT_RELEASE=$(git rev-parse HEAD)
TAG=$OPENBOT_RELEASE docker buildx bake -f deploy/docker/docker-bake.hcl --load

这会为 linux/amd64 构建 openbot:$OPENBOT_RELEASE 和 openbot-protocol-test:$OPENBOT_RELEASE。--load 把它们放进你本地的 Docker。不设 TAG 时,标签是 local。如果只想构建一个镜像,就加上它的目标名,例如 openbot。

如果电脑不是 x86_64,Docker 需要 QEMU(一个能运行其他处理器代码的程序)来构建镜像。用 docker run --privileged --rm tonistiigi/binfmt --install amd64 安装一次即可。

两个镜像都基于 distroless,Node.js 版本和开发环境相同。distroless 镜像没有 shell,也没有包管理器,所以你不能用 docker exec 进入它们的 shell。它们以用户 nonroot(65532)运行。

OpenBot 镜像包含 Node.js、打包好的服务器、打包好的迁移程序和设置程序,以及数据库迁移文件。它不含构建工具,也不含任何密钥。

镜像中的路径 是什么
/app/dist/app/Main.mjs 服务器。镜像默认运行它。
/app/dist/app/Migrate.mjs 迁移程序。它负责准备数据库。
/app/dist/app/Setup.mjs 设置程序。它写入最初的平台设置。
/app/migrations 数据库迁移文件。

镜像中的服务器监听 0.0.0.0:3000。镜像带有健康检查,每五秒调用一次 /health。

OpenBot 先从环境变量读取每个设置。如果没有设置该变量,OpenBot 就改读文件 /run/secrets/<NAME>,例如 /run/secrets/OPENBOT_SECRET_KEYS。Docker 和 Compose 就把密钥放在这里。空文件视为未设置。请看配置。

环境变量会出现在 docker inspect 中。/run/secrets 中的文件不会。Compose 对所有密钥都使用文件。

把设置写进一个文件,例如 openbot.env。它只需要 OPENBOT_DATABASE_URL 和 OPENBOT_SECRET_KEYS 和 OPENBOT_CLUSTER_SECRET。可以从 deploy/docker/production.env.example 开始。docker run 不会替换 ${POSTGRES_PASSWORD},所以请自己写出完整的 OPENBOT_DATABASE_URL。

生成一次密钥:

Terminal window
echo "OPENBOT_SECRET_KEYS=k1:$(openssl rand -hex 32)" >> openbot.env
echo "OPENBOT_CLUSTER_SECRET=$(openssl rand -hex 32)" >> openbot.env

请看密钥。

节点间的私有调用使用 /internal/executions/rpc 和 /internal/resources/rpc。请只在私有网络开放这两个路径。所有节点使用同一个随机密钥。多节点部署中,为每个节点设置不同且可访问的主机地址。私有 RPC 客户端与 App 的出站网络检查分开。

迁移程序需要 OPENBOT_DATABASE_URL 和 OPENBOT_SECRET_KEYS。运行前停止所有 OpenBot 实例。备份数据库和对象存储键的清单。保留旧密钥,数据转换需要用它们打开旧记录。首次启动服务器和每次发布新版本之前都要运行:

Terminal window
docker run --rm --env-file openbot.env \
openbot:$OPENBOT_RELEASE /app/dist/app/Migrate.mjs

同一迁移程序会把支持转换的 UUID 列从文本改为 PostgreSQL 的 uuid 类型,每个 ID 占 16 字节。旧 v4 值不变;新的存储 ID 在时间顺序有帮助时使用 v7。含混合格式或外部 ID 的列保留文本。按上文要求,停止所有服务器后再运行。

转换中断后,再运行同一命令。每一批数据与进度一起提交。损坏的记录会停止转换,并留下加密的错误报告。程序检查数量、引用、密钥和状态后,才将数据版本标记为就绪。检查通过前,服务器不能启动。运行中的服务器持有共享数据库锁;转换程序需要独占锁。

备份保留资源 ID、历史和待处理决策。结果不明的旧外部动作保留为 outcome_unknown。没有安全检查点的工作标记为 interrupted,并保留原因。缺少原始 token 的记录不能变成不受限制的成员调用。

恢复流量前可以还原备份。重新执行外部动作后,应向前修复数据。不要还原旧数据并重复这些动作。

在新数据库上运行一次设置程序:

Terminal window
docker run --rm --env-file openbot.env openbot:$OPENBOT_RELEASE \
/app/dist/app/Setup.mjs \
--public-origin=https://api.example.com \
--oidc-issuer=https://id.example.com \
--oidc-client-id=openbot \
--admin-email=alice@example.com

它把公开源、平台提供方和最初的平台管理员写入数据库。客户端密钥请用 -e OPENBOT_SETUP_OIDC_CLIENT_SECRET=... 传入,不要写在命令行参数里。所有参数请看平台。

你也可以在服务器启动后再运行设置。在那之前,除 /health 外的每个路由都返回 503 和 SetupRequired。

Terminal window
docker run -d --name openbot --env-file openbot.env \
-p 127.0.0.1:8080:3000 openbot:$OPENBOT_RELEASE

服务器启动时,会检查表结构和已完成的数据版本。任一检查失败,它都会停止,并在日志中写入错误。

Terminal window
curl http://127.0.0.1:8080/health
{ "status": "ok" }

/health 只说明 HTTP 服务器能够应答。它不检查数据库、设置或模型。

现在 Alice 可以登录了。她是平台管理员。下一步,添加一个模型,以及一个关联它的模型提供方。请看模型。

你也可以在服务器上直接用 Node.js 运行这些程序:

Terminal window
pnpm install --frozen-lockfile
pnpm --filter-prod @openbot-build/openbot... build
pnpm --filter @openbot-build/openbot migrate
pnpm --filter @openbot-build/openbot setup --public-origin=https://api.example.com --admin-email=alice@example.com
pnpm --filter @openbot-build/openbot start

包 @openbot-build/openbot 还提供命令 openbot-server、openbot-migrate 和 openbot-setup。有了包 @openbot-build/cli,你也可以用 openbot server、openbot migrate 和 openbot setup 运行它们。


文件 deploy/docker/compose.production.yaml 运行以下服务:

服务 镜像 主机上的端口
postgres postgres:18.6-alpine3.24,用摘要固定,数据在卷 postgres 中 无
migrate openbot:$OPENBOT_RELEASE 无
openbot openbot:$OPENBOT_RELEASE 127.0.0.1:8080,或 OPENBOT_PUBLISHED_PORT
protocol-test openbot-protocol-test:$OPENBOT_RELEASE 127.0.0.1:3001

migrate 在 PostgreSQL 健康之后运行一次迁移程序。只有 migrate 成功,openbot 才会启动。所以 up 总是先迁移数据库。

protocol-test 服务是 App Protocol 的公开测试服务。请看协议测试。即使你只用 OpenBot,这个文件也需要 PROTOCOL_TEST_PUBLIC_ORIGIN。

Compose 以 /run/secrets 中文件的形式提供 POSTGRES_PASSWORD、 OPENBOT_DATABASE_URL、OPENBOT_SECRET_KEYS 和 OPENBOT_CLUSTER_SECRET。这些值来自 .env.production。openbot 服务还接收 OPENBOT_OUTBOUND_ALLOW 和 OPENBOT_CLUSTER_HOST。产品设置保存在数据库中。migrate 服务需要 OPENBOT_DATABASE_URL 和 OPENBOT_SECRET_KEYS。

在模板中,OPENBOT_DATABASE_URL 使用 ${POSTGRES_PASSWORD},所以密码只需要设置一次。

Terminal window
cp deploy/docker/production.env.example .env.production
openssl rand -hex 32 # 把输出用作 POSTGRES_PASSWORD
echo "k1:$(openssl rand -hex 32)" # 把输出用作 OPENBOT_SECRET_KEYS
openssl rand -hex 32 # 把输出用作 OPENBOT_CLUSTER_SECRET

在 .env.production 中填写这些值。

Terminal window
export OPENBOT_RELEASE=$(git rev-parse HEAD)
TAG=$OPENBOT_RELEASE docker buildx bake -f deploy/docker/docker-bake.hcl --load
Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml config --quiet

缺少必需的设置时,它会显示错误。不加 --quiet 时,它会打印填好所有值的完整配置。

Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml up -d --wait

--wait 会等到所有服务都健康后才返回。镜像每五秒检查一次健康状态。服务进程停止时,Compose 会重新启动它。

在第一次 up 之后,运行一次设置程序:

Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml \
run --rm openbot /app/dist/app/Setup.mjs \
--public-origin=https://api.example.com \
--oidc-issuer=https://id.example.com \
--oidc-client-id=openbot \
--admin-email=alice@example.com

在完成这一步之前,除 /health 外的每个路由都返回 503 和 SetupRequired。请看平台。

要发布新版本,请构建新镜像并设置新的 OPENBOT_RELEASE。停止全部 OpenBot 实例,备份数据库和对象键清单,再运行 up -d --wait。新的 OpenBot 启动前,migrate 会再次运行。不要删除 postgres 卷。它保存着你的全部数据。

你可以在一个负载均衡器后面运行多个 OpenBot 实例。给每个实例:

  • 相同的 OPENBOT_DATABASE_URL,
  • 相同的 OPENBOT_SECRET_KEYS 和 OPENBOT_CLUSTER_SECRET,
  • 各不相同、且其他节点都能访问的 OPENBOT_CLUSTER_HOST,
  • 相同的 OPENBOT_OUTBOUND_ALLOW(如果你设置了它)。参见出站连接。

每个节点使用自己的私有地址,不要使用负载均衡器的地址。扩容 Compose 的 openbot 服务时,必须为每个新节点配置独立主机名。compose.check.yaml 中的两个节点展示了这种配置。

所有共享设置都存放在数据库中。管理员修改设置后,每个实例会立即使用新设置。请看配置。迁移程序和设置程序只运行一次,不要在每个实例上都运行。


在生产环境中,由反向代理处理 HTTPS,并把流量转发给 127.0.0.1:8080 上的 OpenBot。OpenBot 只提供普通 HTTP,所以只有代理提供 HTTPS。

代理必须:

  • 拒绝所有访问 /internal/ 下路径的公开请求,

  • 把 Origin、Cookie 和 Authorization 头原样转发给 OpenBot,

  • 不缓冲响应,因为 Turn 可以用服务器发送事件(SSE)流式输出,

  • 允许长时间的响应。执行事件流可以保持打开,直到执行结束。

server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/ssl/api.example.com.pem;
ssl_certificate_key /etc/ssl/api.example.com.key;
location /internal/ {
return 404;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 1h;
}
}

与 OpenBot 同源的浏览器客户端可以使用登录 cookie。它不需要用户令牌。为此,你的代理把一部分路径转发给 OpenBot,其余路径转发给你的客户端。

路径 转发给 是什么
/auth/* OpenBot 登录、退出,以及 App 授权回调。
/v1/* OpenBot API。
/health OpenBot 健康检查。
/openapi.json OpenBot OpenAPI 文档。
/docs OpenBot 交互式 API 参考。可选。
其他所有路径 你的客户端 你的页面,包括 /。

当你把客户端挂在 / 上时,GET / 的服务文档就不再公开。这没有问题。客户端可以直接使用上面的路径。

登录后,OpenBot 会把浏览器送回你客户端上的某个路径。默认是 /。你的客户端还必须处理这些返回地址:

  • App 授权之后的 /?authorization=<flowId>。接下来调用 completeAppAuthorization。请看 App。
  • 开发者测试授权之后的 /?developerTest=<testId>。请看开发者工具。

返回路径可以是同源上的任意路径,但 /auth/、/v1/ 和 /development/ 下的路径除外。


备份下面这些东西,并把它们放在一起:

  1. 数据库。 它保存平台和组织的设置、账户、组织及其成员、用户令牌、模型和模型提供方、SSO 连接、审计日志、Bot、Chat 及其历史,以及 App 连接。
  2. OPENBOT_SECRET_KEYS。 这些密钥用来解密数据库中的机密:App 密钥、模型提供方密钥、SSO 客户端密钥和登录密钥。没有这些密钥,数据库备份无法恢复这些机密。
  3. 文件的 bucket。 它保存人们上传的文件的字节。数据库只记录它们的名字。

使用 Compose 时,这样备份数据库:

Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml \
exec -T postgres pg_dump -U openbot -Fc openbot > openbot-$(date +%F).dump

恢复时,先用 docker compose --env-file .env.production -f deploy/docker/compose.production.yaml stop openbot 停止 OpenBot。然后运行 pg_restore:

Terminal window
docker compose --env-file .env.production -f deploy/docker/compose.production.yaml \
exec -T postgres pg_restore -U openbot -d openbot --clean < openbot-2026-10-20.dump

此开发任务请参见 发布和检查项目.