在 Cloudflare 上部署 mosoo
通过 GitHub Actions 云端部署,或在本地使用 Wrangler 工具链部署 mosoo。
mosoo 由两个 Cloudflare Workers 组成:API Worker 使用 D1、R2、Queues、Durable Objects 和 Containers;Web Worker 提供控制台,并通过服务绑定连接 API。mosoo 不是一个可以单独部署的 Cloudflare Pages 静态站点。
本指南介绍参考部署所采用的两种发布方式:
- 云端部署:由 GitHub Actions 构建并发布到 Cloudflare。
- 本地工具链部署:运维人员在本地代码仓库中通过 Wrangler 发布同一套配置。
两种方式共用 apps/api/wrangler.toml、apps/web/wrangler.toml 和仓库内的部署脚本。Cloudflare 资源只需准备一次,之后任选一种发布方式。
前置要求
- Cloudflare 账号已开通 Workers、D1、R2、Queues、Durable Objects 和 Containers。
- 一个由 Cloudflare DNS 托管的域名,例如
console.example.com;如需启用 App 部署,还需准备apps.example.com这类部署子域名。 - 已安装 Git、Docker、Bun、just,并能拉取仓库子模块。
- 一个具备上述账号资源和域名区域部署权限的 Cloudflare API 令牌。令牌和密钥不得提交到 Git,并应按以下操作范围配置最小权限。
| 范围 | 必需操作 |
|---|---|
| 账号 | Workers 脚本、版本、部署、自定义域名与 Containers;D1 迁移;R2;Queues;启用 App 部署时还包括 Pages 项目与域名 |
CLOUDFLARE_ZONE_ID 指定的域名区域 | 修改 App 部署域名的 Workers Routes |
| R2 S3 凭据 | 读写已部署应用使用的 sandbox-state 存储桶 |
CLOUDFLARE_ZONE_ID 必须对应 MOSOO_APP_DEPLOYMENT_DOMAIN 所在的域名区域。Cloudflare 控制台中的权限名称可能调整,应核对令牌是否允许这些具体 API 操作,而不是直接授予账号管理员权限。
克隆你的 fork,并安装仓库锁定的依赖:
git clone --recurse-submodules https://github.com/<owner>/mosoo.git
cd mosoo
bun install --frozen-lockfile1. 准备 Cloudflare 资源
从本地工作站创建资源时,先登录 Wrangler:
cd apps/api
../../node_modules/.bin/vp exec wrangler login
../../node_modules/.bin/vp exec wrangler whoami创建生产 D1 数据库,并记录命令返回的数据库 ID:
../../node_modules/.bin/vp exec wrangler d1 create mosoo-prod创建生产配置引用的 R2 存储桶:
../../node_modules/.bin/vp exec wrangler r2 bucket create mosoo-file
../../node_modules/.bin/vp exec wrangler r2 bucket create mosoo-sandbox-state创建 API 指令、构建产物和渠道最终投递所需的队列:
for queue in \
api-command \
api-command-dlq \
environment-artifact-build \
channel-final-delivery \
channel-final-delivery-dlq
do
../../node_modules/.bin/vp exec wrangler queues create "$queue"
done如果修改了资源名称,请同步修改 apps/api/wrangler.toml 中所有对应的生产者、消费者和绑定。
2. 配置域名与绑定
编辑两个 Wrangler 配置中的 [env.prod]。至少完成以下设置:
- 在
apps/api/wrangler.toml中:- 将
WEB_ORIGIN设为公开的 HTTPS 控制台地址; - 将
MOSOO_APP_DEPLOYMENT_DOMAIN设为应用部署域名; - 将 API 路由改为
<控制台域名>/api/*,并设置对应的zone_name; - 填入
wrangler d1 create返回的 D1database_id; - 如果没有采用默认名称,同步更新 D1、R2 和 Queue 名称;
- 将
AUTH_EMAIL_FROM改为 Cloudflare 域名区域已授权的发件地址。
- 将
- 在
apps/web/wrangler.toml中:- 将生产自定义域名改为同一个控制台域名;
- 保持
API服务绑定指向生产 API Worker 名称。
推荐的路由结构如下:
https://console.example.com/* -> Web Worker
https://console.example.com/api/* -> API Worker
https://*.apps.example.com/* -> mosoo 发布的应用(启用时)请分别按照 Cloudflare 各类资源的命名空间选择尚未使用的名称;Workers、D1 数据库、Queues、R2 存储桶和域名的命名与唯一性规则并不相同。不要复制其他部署的数据库 ID、账号 ID、区域 ID 或域名。
3. 保存生产密钥
当前生产配置要求 API Worker 具备以下密钥:
BETTER_AUTH_SECRETRUNTIME_ACTION_TOKEN_SECRETVAULT_ROOT_SECRETR2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYCLOUDFLARE_ACCOUNT_IDCLOUDFLARE_API_TOKENCLOUDFLARE_ZONE_IDGOOGLE_OAUTH_CLIENT_IDGOOGLE_OAUTH_CLIENT_SECRET
前三项应分别生成独立的随机值。在 Cloudflare 控制台创建 R2 S3 凭据和 Cloudflare API 令牌;为 Google OAuth 客户端配置公开的 mosoo 来源地址,并将回调地址精确设置为 https://console.example.com/api/auth/callback/google,其中示例域名应替换为 WEB_ORIGIN。
通过 Wrangler 保存每一项,不要把密钥写入 wrangler.toml 或提交到仓库的 .env 文件:
cd apps/api
../../node_modules/.bin/vp exec wrangler secret put BETTER_AUTH_SECRET --env prod
# 对上面列出的每一项生产密钥重复执行。如需使用邮件登录,请配置 Cloudflare Email Routing,并授权 AUTH_EMAIL 绑定使用的发件地址。PostHog 分析是可选项;不设置项目密钥时,分析功能保持关闭。
4A. 通过 GitHub Actions 云端部署
参考实现使用 .github/workflows/deploy-try.yml。工作流会检查仓库、在本地执行 D1 迁移链、读取远程 D1 迁移账本与 Queue 列表、试运行两个 Worker、依次部署 API 与 Web Worker,最后探测公开地址;它不会逐项预检所有 R2、Container 或绑定资源。
在 fork 中部署时:
- 修改工作流中的仓库限制、Environment 地址、公开健康检查地址和部署相关构建变量。
- 创建工作流所使用的 GitHub Environment,并限制为仅允许发布分支部署。
- 在 GitHub Environment 中添加
CLOUDFLARE_ACCOUNT_ID和CLOUDFLARE_API_TOKEN。它们用于 CI 身份验证;上一节保存的运行时密钥仍由 Cloudflare 管理。 - 禁止对发布分支执行强制推送或删除。
- 只将经过评审的
main提交推进到发布分支。
参考工作流在推送到 deploy/try 时发布:
git fetch origin
git push origin origin/main:deploy/try持续观察 GitHub Actions,直到仓库检查、试运行、部署和公开验证全部通过。工作流会串行执行发布,因为 D1 迁移、Queue 更新和 Worker 发布并不是一个原子事务。
仓库内置工作流默认拒绝从配置之外的仓库发布。fork 必须明确修改该限制,否则 CI 部署任务不会执行。
4B. 在本地使用 Wrangler 工具链部署
请在干净且经过评审的代码仓库中使用同一套已提交配置。Wrangler 可以通过 wrangler login 登录;导出 API 令牌则能让本地命令更接近 CI 环境。
不要把 just check 当成完整部署预检。API 部署脚本的第一个远程操作就是应用待执行的 D1 迁移,早于构建和产物校验。运行 just deploy 前,必须在同一个发布提交上完成下面全部非破坏性检查。
先导出生产凭据,并确认仓库、子模块与构建输入目录均无本地改动:
export CLOUDFLARE_ACCOUNT_ID="<你的账号 ID>"
export CLOUDFLARE_API_TOKEN="<你的 API 令牌>"
git status --short --branch
test -z "$(git status --porcelain=v1 --untracked-files=all)"
git submodule foreach --recursive \
'test -z "$(git status --porcelain=v1 --untracked-files=all)"'
test -z "$(git ls-files -v | grep -E '^[a-zS]')"
test -z "$(git ls-files --others --ignored --exclude-standard -- apps/web/src apps/web/public)"
just check在隔离的本地 D1 数据库上执行完整迁移链,再以只读方式检查生产迁移账本和 Queue 列表:
(
cd apps/api
persist_dir="$(mktemp -d)"
trap 'rm -rf "$persist_dir"' EXIT
../../node_modules/.bin/vp exec wrangler d1 migrations apply DB \
--local --env prod --persist-to "$persist_dir"
)
(
cd apps/api
../../node_modules/.bin/vp exec wrangler d1 migrations list DB --remote --env prod
../../node_modules/.bin/vp exec wrangler queues list
)本地迁移链失败时必须停止。如果远程账本显示有待执行迁移,应先检查确切 SQL,只有迁移是增量操作或已经得到明确生产批准时才能继续;同时确认第 1 步创建的五个 Queue 均存在。
构建 Driver 和 Web 产物,并试运行两个 Worker 的上传。以下命令只验证配置与产物,不会发布 Worker,也不会应用远程迁移:
./node_modules/.bin/vp run --filter agent-driver build
(
cd apps/api
../../node_modules/.bin/vp exec wrangler deploy --env prod --minify --dry-run
)
./node_modules/.bin/vp run --filter @mosoo/web build
(
cd apps/web
../../node_modules/.bin/vp exec wrangler deploy --env prod --dry-run
)
git status --short只有以上检查在同一个干净提交上全部通过后,才能执行真实发布:
just deployjust deploy 会先执行完整仓库检查,再依次部署 API 和 Web Worker。API 部署会应用待执行的远程 D1 迁移、检查数据库结构、确保必要队列存在、构建 Driver 容器并发布 API Worker;随后构建并发布控制台 Web Worker。
排查局部失败后,也可以只重新发布一侧:
just deploy-api
just deploy-web这两个局部命令会直接发布,不会运行完整检查。必须保留同一个干净的发布提交,并重新执行上面对应的构建与 dry-run 步骤。不要修改已经应用到生产环境的 D1 迁移;每次生产数据库结构变更都应新增迁移文件。
5. 验证部署
替换示例域名后,检查三个公开入口:
curl --fail --silent --show-error https://console.example.com/ >/dev/null
curl --fail --silent --show-error https://console.example.com/api/health
curl --fail --silent --show-error https://console.example.com/api/graphql \
-H 'content-type: application/json' \
--data '{"query":"query { __typename }"}'控制台应通过 HTTPS 正常加载,/api/health 应返回 mosoo 服务正常状态,GraphQL 应返回 Query。在对外开放前,还应检查两个 Worker 的日志,并确认 D1 迁移和 Queue 消费者均正常。
权威的停止条件、故障恢复和发布验收步骤见 mosoo 源码仓库中的 docs/production-deploy-verification.md。