跳转到内容
天空之翼
选择 · Enter跳转 · Esc关闭 由 Pagefind 提供索引
EN

部署指南

Cloudflare 部署、CI、密钥管理与成本估算。

前端与后端分开部署。前端通过 HTTPS 调用 API;API 把元数据存进 D1,用户上传的对象放进 R2(也可以是任意 S3 兼容存储),KV 存放自由模式凭据、限流计数这类短生命周期的数据。

需要准备:

  • 一个 Cloudflare 账号(免费或付费均可)。
  • Wrangler CLI。用 npm install -g wrangler 安装,或借助 bun 直接调用 bunx wrangler
  • bun 1.3.14 及以上,用于运行仓库内的脚本。
  • (可选)GitHub 账号,用于 Pages 的 Git 集成与 CI。

登录 Cloudflare:

wrangler login

后端代码在 workers/,前端在 frontend/,两者共用 shared/ 里的类型。

  1. 创建 D1 数据库:

    wrangler d1 create picumet-db

    从输出中复制 database_id

  2. 创建 KV 命名空间:

    wrangler kv namespace create PICUMET_KV
    wrangler kv namespace create PICUMET_KV --preview

    复制 idpreview_id

  3. 创建 R2 存储桶:

    wrangler r2 bucket create picumet-storage

workers/wrangler.toml 里的占位 ID 换成真实资源 ID,并把 ENVIRONMENT 改为 production:

name = "picumet-api"
main = "src/index.ts"
compatibility_date = "2024-11-01"
compatibility_flags = ["nodejs_compat"]
account_id = "你的账号 ID"
[vars]
ENVIRONMENT = "production"
APP_BASE_URL = "https://picumet.com"
ALLOWED_ORIGINS = "https://picumet.com"
[[d1_databases]]
binding = "DB"
database_name = "picumet-db"
database_id = "你的 D1 database_id"
migrations_dir = "migrations"
[[kv_namespaces]]
binding = "KV"
id = "你的 KV 命名空间 ID"
[[r2_buckets]]
binding = "R2"
bucket_name = "picumet-storage"
绑定用途
DBD1 关系型数据库,存放元数据、配额、分享与日志。
KV会话撤销、限流计数、自由模式凭据与 seed 标记。
R2上传文件的默认对象存储。

把 API 绑到 api.yourdomain.com 时,加一段 routes 配置,并让 DNS 记录走 Cloudflare 代理:

routes = [
{ pattern = "api.yourdomain.com/*", zone_name = "yourdomain.com" }
]
  1. 安装依赖,先跑一次预检构建:

    cd workers
    bun install
    bun run build

    bun run build 执行 wrangler deploy --dry-run --outdir=dist,只打包不上线。

  2. 正式部署:

    bun run deploy

    bun run deploy 就是 wrangler deploy

  3. 验证健康检查:

    curl -s https://api.yourdomain.com/api/public/health/live
    curl -s https://api.yourdomain.com/api/public/health/ready

    /api/public/health/live 返回 {"service":"picumet-api","status":"ok"};/api/public/health/ready 在 seed 完成后返回 200"ready": true,初始化前返回 503。生产环境下,seed 未完成时业务 API 一律返回 503 INITIALIZATION_REQUIRED

迁移要在 API 上线之前执行,保证表结构与代码一致。迁移文件放在 workers/migrations/,按文件名顺序应用;每个文件幂等,并附带注释形式的回滚脚本。

cd workers
bun run db:migrate:local

这条命令等价于 wrangler d1 execute picumet-db --local --file=migrations/0001_initial.sql,针对本地 D1 执行。

动生产库之前,先对预发布 D1 跑同一份迁移:

bunx wrangler d1 execute picumet-db --preview --file=migrations/0001_initial.sql

生产迁移必须人工审核,不要让 CI 自动执行。

  1. 先审阅 workers/migrations/ 里要执行的迁移文件。

  2. 对远端数据库执行迁移:

    bunx wrangler d1 execute picumet-db --remote --file=migrations/0002_add_parts_and_download_tokens.sql
  3. 也可以按顺序应用全部待执行迁移:

    bunx wrangler d1 migrations apply picumet-db --remote
  4. 确认就绪探针返回 ready: true:

    curl -s https://api.yourdomain.com/api/public/health/ready

密钥用 wrangler secret put 写入,Workers 会加密保存,不会出现在 wrangler.toml 里。先生成强随机值再逐个设置:

openssl rand -base64 32
bunx wrangler secret put JWT_SECRET
bunx wrangler secret put ENCRYPTION_KEY

Picumet 没有内置的默认账号密码。首次启动的 seed 用 ADMIN_PASSWORD 创建初始管理员;生产环境下管理员缺失时,API 会 fail-closed(统一返回 503)。该密钥要在首次部署前后配好:

bunx wrangler secret put ADMIN_PASSWORD

生产密码规则:

  • 至少 12 位。
  • 必须同时包含字母和数字。
  • 没有固定默认值,每个环境生成独立的随机密码。
密钥是否必需用途
JWT_SECRET必需签名 JWT 会话令牌,至少 32 字节随机值。
ENCRYPTION_KEY必需对存储提供商凭据做 AES-GCM 静态加密的密钥。
ADMIN_PASSWORD生产必需初始管理员密码;缺失时 API fail-closed。
ADMIN_USERNAME可选初始管理员用户名,默认 admin
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM可选邮件发送,用于邮箱验证与密码重置。
TURNSTILE_SECRET_KEY可选Cloudflare Turnstile 人机验证。

ENVIRONMENTAPP_BASE_URLALLOWED_ORIGINSwrangler.toml 里的普通变量,不算密钥。

前端是纯静态的 Vite 构建产物。bun run build 执行 tsc -b && vite build,输出到 frontend/dist

先本地构建确认无误:

cd frontend
bun install
bun run build
  1. 把仓库推送到 GitHub。
  2. 在 Cloudflare 控制台新建 Pages 项目并关联该仓库。
  3. 构建配置:
    • 框架预设:Vite
    • 构建命令:cd frontend && bun install && bun run build
    • 构建输出目录:frontend/dist
    • 根目录:/
  4. 环境变量:
    • VITE_API_BASE_URL:https://api.yourdomain.com
    • VITE_TURNSTILE_SITE_KEY:你的 site key(可选)
  5. 点击保存并部署

之后每次推送到生产分支,Cloudflare 都会自动重新构建并发布。

cd frontend
bun run build
bunx wrangler pages deploy dist --project-name=picumet
类型名称内容代理
CNAME@picumet.pages.dev开启
CNAMEapi由 Workers 管理开启

.github/workflows/ci.yml 在每次 push 或 PR 到 main 时运行,它只是质量门禁,从不自动部署。部署要么手动执行 wrangler deploy,要么走 Cloudflare 侧的 Pages Git 集成。

工作流使用 bun 1.3.14:

  • workers:bun install --frozen-lockfilebun run typecheckbun run test
  • frontend:bun install --frozen-lockfilebun run typecheckbun run testbun run test:coveragebun run build

同一分支上的并发运行会自动互相取消(concurrency.cancel-in-progress)。工作流里没有部署步骤,也没有 Cloudflare 凭据;有了经过验证的回滚方案之后,再考虑加入自动部署。

变量类型是否必需说明
ENVIRONMENT变量必需developmentproduction,控制 fail-closed 的 seed 与限流。
APP_BASE_URL变量必需前端地址,用于邮件链接与 CORS。
ALLOWED_ORIGINS变量必需CORS 允许来源,逗号分隔。
JWT_SECRET密钥必需JWT 签名密钥。
ENCRYPTION_KEY密钥必需提供商凭据的 AES-GCM 加密密钥。
ADMIN_PASSWORD密钥生产必需初始管理员密码,至少 12 位且含字母和数字。
ADMIN_USERNAME密钥可选初始管理员用户名,默认 admin
DEMO_PASSWORD密钥可选演示用户密码,仅开发环境。
SMTP_HOSTSMTP_PORTSMTP_USERSMTP_PASSSMTP_FROM密钥可选邮件发送。
TURNSTILE_SECRET_KEY密钥可选Turnstile 人机验证。

wrangler.toml 里的绑定:DB(D1)、KV(KV 命名空间)、R2(R2 存储桶)。

免费额度足以支撑小规模部署:

  • Workers:每天 10 万次请求
  • Pages:构建与流量不限
  • D1:5GB 存储 + 每天 500 万行读取
  • KV:每天 10 万次读取 + 1000 次写入
  • R2:每月 10GB 存储 + 每月 100 万次 A 类操作

按 1000 用户、100GB 存储估算,月成本约 $21.5(Workers 约 $10、D1 约 $5、R2 约 $6.5)。扩容前先在 Cloudflare 控制台设置用量告警。

如果迁移失败或写坏了数据,不要直接在线上修补。

  1. 停止部署,把 API 回滚到上一个版本:

    wrangler rollback
  2. 检查失败的迁移,大部分迁移文件末尾附有注释形式的回滚脚本。

  3. 修复数据后重新执行修正过的迁移。

  4. 重新部署并验证就绪探针。

定时任务 reconcileQuotas 会按 file_metadata 重新计算 used_storageused_files。需要立刻对账时,手动执行同一段 SQL:

UPDATE user_quotas
SET used_storage = COALESCE((SELECT SUM(size) FROM file_metadata WHERE owner_id = user_quotas.user_id), 0),
used_files = (SELECT COUNT(*) FROM file_metadata WHERE owner_id = user_quotas.user_id)
WHERE user_id = '<user_id>';
  1. 立即部署修复版本(wrangler deploy)。
  2. 审计受影响时间段的 access_logs
  3. 按需吊销会话与 API 密钥,并通知受影响的用户。