部署与运维
本页用途
本页定义 chorus 常驻服务的生产部署基线。当前尚无产品代码和真实生产环境,命令是后续实现必须满足的运维契约;域名、容量、保留期和阈值在首发工单确认后补充,不能由 Agent 猜测。
安全边界
- 生产只部署已审核制品和
migrations/;不从D:\github\goadmin构建,不运行 AutoMigrate。 - dev-tools 生成路由、
/gen/todb和写源码能力不得注册或被 nginx 代理;仅隐藏菜单不合格。 - DSN、会话密钥、JWT secret、TLS 私钥只来自受控环境文件或密钥管理系统,权限最小化,不写入 Git/Wiki/日志。
- 原图、结果和缩略图保存在受保护目录,通过 portal 鉴权读取,不由 nginx 直接暴露。
- 数据迁移、回退、删除、清理和密钥轮换均是高风险操作,必须有工单、备份和人工确认。
服务概览
Internet
→ nginx/TLS
→ chorus-portal 127.0.0.1:8080(页面、HTMX、JSON、MVP 内嵌 worker)
→ chorus-admin 127.0.0.1:8081(MVP-1)
→ /admin-ui 静态构建产物(MVP-1)
portal/admin → MySQL 8.0
portal worker → Provider(安全 DialContext)
portal → /var/lib/chorus/storage(或后续对象存储适配)
| 项目 | 基线 |
|---|---|
| 运行账号 | 独立无登录 chorus 用户 |
| 制品目录 | /opt/chorus/releases/<commit>/,/opt/chorus/current 指向当前版本 |
| 配置 | /etc/chorus/chorus.env,仅运行账号可读 |
| 持久数据 | /var/lib/chorus/storage,不随版本目录切换 |
| 日志 | journald 或平台日志;结构化且脱敏 |
| 进程托管 | systemd:chorus-portal.service、chorus-admin.service |
| 数据库 | MySQL 8.0,独立最小权限账号 |
| 构建 | CI 使用 Go 1.26.5;portal/web 与 admin-ui 使用 Node >=22 + pnpm 9.15.1 |
配置与凭据
| 配置 | 用途 | 敏感 |
|---|---|---|
CHORUS_ENV=production |
启用生产安全门禁 | 否 |
CHORUS_DSN |
MySQL | 是 |
CHORUS_SESSION_KEY |
portal 会话 | 是 |
CHORUS_STORAGE_ROOT |
生成物目录 | 否 |
| 上游/存储超时、lease、worker 数 | 执行与优雅退出 | 否 |
CHORUS_SESSION_TTL_MINUTES |
服务端内存会话有效期 | 否 |
CHORUS_LOGIN_ATTEMPTS / CHORUS_LOGIN_WINDOW_SECONDS |
登录节流窗口 | 否 |
CHORUS_MAX_PROMPT_BYTES |
prompt 字节上限 | 否 |
CHORUS_MAX_IMAGES / CHORUS_MAX_IMAGE_BYTES / CHORUS_MAX_UPLOAD_BYTES / CHORUS_MAX_IMAGE_PIXELS |
上传边界 | 否 |
CHORUS_HISTORY_LIMIT |
历史查询上限 | 否 |
| 保留期与磁盘告警 | 清理和容量保护 | 否 |
生产启动必须校验必需配置、会话/JWT 密钥、目录权限、超时与 lease 关系;缺失或不安全时 fail closed。CHORUS_ENV=production 下若检测到 AutoMigrate 或 dev-tools 注册必须拒绝启动。
制品构建
在干净 CI 环境按固定提交来源导入后的 chorus 代码构建:
go version
corepack pnpm --dir portal/web install --frozen-lockfile
corepack pnpm --dir portal/web build
go test ./...
go vet ./...
go build -trimpath -o dist/chorus-portal ./portal
go -C admin build -trimpath -o ../dist/chorus-admin .
corepack pnpm --dir admin-ui install --frozen-lockfile
corepack pnpm --dir admin-ui build:prod
portal 的模板和静态资源嵌入 chorus-portal 二进制,运行环境不需要 Node,也不从 CDN 加载资源;CI 必须先按 portal/web/pnpm-lock.yaml 重建并确认工作区无差异。MVP-0 没有 admin/admin-ui 时跳过对应命令并在发布记录说明。制品记录 chorus commit、Go module 校验、portal/web 与 admin-ui lockfile 和固定 go-admin 来源提交。
首次部署与升级顺序
- 记录当前/目标 commit、迁移版本、制品校验值和回退条件。
- 备份 MySQL,并验证备份可读取;确认持久存储快照/备份策略。
- 把制品解压到新的 release 目录,不原位覆盖当前版本。
- 用相同 MySQL 8 版本的隔离库执行全部 migration up/down/up 验证。
- 停止取新任务并等待在途 worker 到优雅退出期限;旧 worker 未结束时不得启动会竞争同一租约的错误版本。
- 在生产执行
migrate ... up;检查版本,禁止任何 AutoMigrate。 - 原子切换
current,启动/重启 portal 和 admin。 - 执行健康、就绪、登录、提交 mock/受控测试和权限检查。
- 验证生产访问 dev-tools 路径为 404/未注册,并核对路由清单。
- 观察错误率、租约过期、磁盘和数据库连接;满足观察窗口后完成发布记录。
健康与就绪
应用必须提供:
/healthz:进程存活,不依赖上游;/readyz:必需配置有效、MySQL 可用、迁移版本匹配、存储可写、生产 dev-tools 未注册;- admin 健康路径不得泄露版本、DSN、路由或密钥。
systemctl status chorus-portal
curl --fail http://127.0.0.1:8080/healthz
curl --fail http://127.0.0.1:8080/readyz
journalctl -u chorus-portal -n 100 --no-pager
MVP-1 同样检查 admin 8081。外部检查经 TLS/nginx 访问,不把内部端口暴露公网。
portal 会话与请求边界
MVP-0 的终端用户会话保存在单个 portal 进程内存中,Cookie 只携带签名后的不透明 session ID。部署必须保持单实例;portal 重启或切换版本会让全部终端用户重新登录。不要在负载均衡后启动多个 portal 实例,除非先建立新的共享会话设计和工单。
生产 Cookie 必须为 Secure/HttpOnly/SameSite=Lax。反向代理不得记录 Cookie 或 CSRF header;请求日志和 GORM SQL 使用参数化输出。JSON 正文、multipart 总量、单图字节/像素/数量和历史查询都有显式生产配置,缺少任一阈值时启动失败。
上传先在应用层校验,再在 generation 事务回调中保存带 owner/generation metadata 的文件。事务失败只清理本请求保存的 key;存储根目录不能作为 nginx/static 目录暴露。
MVP-0 worker 已实现配置与退出行为
portal 单二进制会同时启动 HTTP server 和内嵌 worker。生产除现有 portal 限制外,还必须显式提供:
| 变量 | 约束 |
|---|---|
CHORUS_WORKER_LEASE_SECONDS |
正整数;必须大于 CHORUS_PROVIDER_HTTP_TIMEOUT_SECONDS + 5 |
CHORUS_WORKER_POLL_MILLISECONDS |
正整数;控制空队列轮询间隔 |
CHORUS_PROVIDER_HTTP_TIMEOUT_SECONDS |
正整数;安全 HTTP client 总超时和响应头超时 |
CHORUS_PROVIDER_MAX_RESPONSE_BYTES |
正整数;Provider JSON/Base64/下载响应读取上限 |
Provider API Key 由授权管理员通过管理端写入 provider_credentials.api_key。数据库、备份和管理员会话泄露会直接暴露完整 Key;必须限制数据库和管理端权限,列表/普通详情/日志/audit 禁止返回完整值,单条读取响应禁止缓存。部署环境不再需要 CHORUS_MASTER_KEY。
CHORUS_TEST_DISABLE_WORKER 是测试专用开关,只在 CHORUS_ENV=test 接受;开发和生产设置为 true 会启动失败。部署制品和服务配置不得设置该变量,portal/web/e2e/fixture 也不得进入生产运行命令。
#13 已在 Windows 前台进程两次用 Ctrl+C 验证停止认领、关闭 HTTP 并等待 worker 返回。真实 Linux/systemd 的 TERM、超时和重启恢复仍属于首次发布前门禁,不能把本机验证写成已上线。
worker 优雅退出
- 收到 TERM 后先停止认领新任务;
- 在途任务只在 lease_token 仍有效时提交;
- systemd 的停止等待时间大于应用优雅退出期限;
- 到期未完成时退出,让租约自然过期,新 worker 原子重领;
- 不把 running 改回 pending,不无条件标 failed,不删除其他 worker 文件。
- 每种 generation kind 必须恰好一个启用的 ProviderModel;0 个或多个都应 fail closed,不随机选取。
- Provider 请求和结果 URL 只走安全 Client;带 Authorization 的跨 origin 重定向必须拒绝。
- 上游超时后用独立短超时尝试最终 CAS;token 已陈旧时只清理本 attempt 生成的临时结果。
- 自动健康/发布验证使用 mock,不把真实 Provider 请求作为启动探针。
存储、备份与监控
必须备份 MySQL 和仍在保留期内的生成物元数据/文件,并定期做恢复演练。至少监控:
- MySQL 连接、慢查询、迁移版本;
- pending 数/最老等待时间、running 租约过期数、失败率;
- Provider 429/5xx/超时和熔断状态;
- 存储总量、可用空间、临时文件增长、缩略图失败;
- 登录失败/节流、SSRF 拦截和越权拒绝;
- portal/admin 健康与重启次数。
保留期、备份频率、RPO/RTO、磁盘阈值尚未确认,是生产上线门禁。清理任务不得在确认前启用。
回滚
- 优先使用向后兼容迁移并回滚二进制;先停止新任务,再切回上一 release,重启并执行健康检查。
- 不能仅通过切回代码撤销数据库变更。需要 down 或恢复备份时先评估数据丢失,取得人工确认。
- 若新版本已写入旧版本无法识别的数据,停止回滚并采用前滚修复或已演练的备份恢复方案。
- 回滚后检查 migration version、陈旧 worker CAS、任务重复、文件一致性和 dev-tools 路由。
- 每次真实发布前至少在隔离环境演练相同升级与回滚步骤。
已知限制
- 尚未完成真实 Linux/systemd/nginx 部署、备份恢复和回滚演练;
- 高可用、多机 worker、对象存储和滚动升级尚未设计;
- 生产域名、TLS、容量、保留期、告警、RPO/RTO 和具体超时/lease 阈值待首发部署工单确认;
- 在这些门禁完成前,本页不能作为“已验证可上线”的证据。
#24 管理端部署补充(2026-08-22)
- 先执行全部
migrations/,再启动chorus-admin server --config <受保护 settings.yml>;启动过程不会建库、迁移、seed 或 AutoMigrate。 - Casbin 只使用 migration 管理的
sys_casbin_rule;发布检查应确认未生成或依赖默认casbin_rule。 admin-ui静态产物通过pnpm --dir admin-ui build:prod构建,API 基址在部署时配置并由反向代理限制到管理网络。- 首次管理员只通过仓库外环境变量运行
chorus-admin-bootstrap;密码不得进入服务文件、命令历史、日志或文档。
单一外部 Host 与内部端口(#38)
config/local-services.yml 和 scripts/*-all.bat 仅用于 Windows 本地开发,不是生产服务管理器。生产继续由 systemd/等价服务管理器和反向代理托管,敏感配置分别保存在 Portal 环境与 Admin settings 中。
推荐同一外部 HTTPS Host 使用路径分流:
/ -> chorus-portal 内部 loopback 地址
/admin/ -> admin-ui 静态构建产物
/admin-api/ -> chorus-admin 内部 loopback 地址
反向代理必须正确剥离或保留前缀,并把 Admin UI 的构建期 API 基址设置为同源 /admin-api;不得把 Admin API 或 Portal 直接绑定到公网地址。Portal 与 Admin API 内部端口仍由各自配置控制,Admin UI 生产态没有独立 Node 端口。路径、Cookie scope、CORS、CSP、上传上限和 HTTPS 终止必须在独立部署工单验证后才能发布;#38 不执行发布或修改生产反向代理。
Windows 本机 Supervisor 运行
D:\supervisor 是当前 Windows 本地常驻运行方式,不替代生产反向代理或正式服务管理器。通过 scripts/install-supervisor.bat 生成三个独立实例:Portal、Admin API 和 Admin UI。Supervisor program 配置只保存进程路径、配置路径、Host/Port 与日志策略;Portal 凭据继续从 portal.environment_file 指向的受保护 PowerShell 文件读取,Admin 敏感值继续只存在于 admin/config/settings.yml。
安装或更新:
scripts\install-supervisor.bat
D:\supervisor\supervisord.exe ctl /c D:\supervisor\supervisord.conf reload
D:\supervisor\supervisord.exe ctl /c D:\supervisor\supervisord.conf status
回退时停止 chorus-user、chorus-admin-api、chorus-admin-ui,移除 D:\supervisor\programs\chorus.conf 后 reload,再按需使用 scripts/start-all.bat。不得同时使用两套入口占用相同端口。