ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

在 DigitalOcean App Platform 上部署 Manifest:Web 服务 + Dev PostgreSQL + Space 对象存储的完整实战指南

2026/9/16 15:36:38 拓冰建站 浏览量
在 DigitalOcean App Platform 上部署 Manifest:Web 服务 + Dev PostgreSQL + Space 对象存储的完整实战指南 在 DigitalOcean App Platform 上部署 ManifestWeb 服务 Dev PostgreSQL Space 对象存储的完整实战指南【免费下载链接】llm-gatewayConnect Your Agents And Harnesses With Any Provider 项目地址: https://gitcode.com/GitHub_Trending/manifest7/llm-gateway本指南基于仓库 deploy/digitalocean/TUTORIAL.md 展开讲解如何通过 DigitalOcean 官方的 Deploy to DigitalOcean 流程把 Manifest开源 AI 模型网关部署为 App Platform 上的 Web 服务并搭配 Dev PostgreSQL 数据库与用户自备的 DigitalOcean Space 对象存储用于持久化请求记录request recordings。读完本文你将掌握 App Platform 部署模板的完整参数填写方法、密钥生成规范、S3 兼容存储的配置要点以及部署后的健康检查与生产化建议文中同时结合 app.config.ts、request-recording-storage.service.ts 等源码说明每个环境变量的底层作用。一、部署方案总览Manifest 是一个 OpenAI 兼容的 AI 模型路由网关可连接各类 LLM 提供商与 Agent。在 DigitalOcean 上官方推荐的部署形态是一套三件套组合组件类型用途App Platform Web Service应用服务承载 Manifest 后端与内置前端页面Dev PostgreSQL托管数据库应用主数据库开发档DigitalOcean Space用户自备对象存储持久化请求记录request recordings整个部署通过 DigitalOcean 的Deploy to DigitalOcean流程完成该按钮会读取公开仓库中的.do/deploy.template.yaml部署模板据此在 App Platform 上创建应用。需要注意的是App Platform 没有持久化卷no persistent volumes其本地文件系统是临时性的ephemeral因此任何需要跨重启、跨实例保留的数据——尤其是请求记录——都必须放在外部持久化存储中这就是引入 Space 的原因。同时部署模板无法自动创建带限定权限scoped的 Space 凭证所以 Space 与受限访问密钥必须在部署前由你在 DigitalOcean 控制台手动创建。该方案会创建付费资源App Platform 服务、Dev PostgreSQL、Space部署前请确认账号已开通计费billing且目标区域可用 App Platform。二、前置条件账号与 Space 准备开始部署前你需要满足以下前置条件一个已开通计费billing enabled的 DigitalOcean 账号所选区域region内可访问 App Platform一个私有privateSpace以及该 Space 专属的受限 Read/Write/Delete 访问密钥。准备 Space 时请在 DigitalOcean 控制台完成如下动作并记录四个信息Space 名称对应REQUEST_RECORDING_S3_BUCKET区域端点region endpoint格式形如https://nyc3.digitaloceanspaces.com访问密钥 IDaccess key密钥secret key。建议为 Space 创建受限limited访问密钥只授予该 Space 的读、写、删除权限而不是使用具有全局权限的密钥——这与仓库中其他平台模板的安全做法一致例如 app.json 中要求 access key 仅限读写删除录制 bucket 内的对象。三、发起部署Deploy to DigitalOcean 流程准备好上述信息后在浏览器打开 DigitalOcean 的部署入口https://cloud.digitalocean.com/apps/new?repohttps://github.com/mnfst/manifest/tree/mainDigitalOcean 会读取仓库的部署模板并在正式部署前提示你填写缺失的 secret 值。此时需要你为下列敏感变量生成并填入独立的值。四、密钥生成与核心环境变量详解4.1 生成两份相互独立的随机密钥文档明确要求为BETTER_AUTH_SECRET与MANIFEST_ENCRYPTION_KEY各生成一个独立的随机值使用命令openssl rand -hex 32每次执行都会输出一个 64 位十六进制字符串32 字节。请分别运行两次得到两个不同的值一个用于BETTER_AUTH_SECRET另一个用于MANIFEST_ENCRYPTION_KEY切勿复用同一个值。为什么必须两个都填且互不相同packages/backend/.env.example 给出了清晰的源码级解释BETTER_AUTH_SECRET是会话session cookie签名密钥最小 32 字符MANIFEST_ENCRYPTION_KEY是静态加密at-rest encryption密钥用于加密存储的 LLM 提供商 API Key、OAuth Token 以及请求记录本身。AES-256-GCM 密钥由该 secret 通过 scrypt 派生若MANIFEST_ENCRYPTION_KEY未设置Manifest 会回退使用BETTER_AUTH_SECRET作为加密密钥。这样虽然省事但一旦会话 cookie 泄露攻击者就能解密所有已存储的提供商凭证——两个泄露面完全重叠。设置两个独立值能让两条泄露路径互不关联。另外请注意静态加密密钥一旦变更旧的已存储请求记录将无法读取会被保留期策略清理因此生产环境应长期妥善保管这两个 secret。4.2 请求记录的 S3 相关变量部署时需填写的 Space 相关变量如下环境变量填写内容说明REQUEST_RECORDING_S3_BUCKET你的 Space 名称存放请求记录的 bucketREQUEST_RECORDING_S3_ENDPOINThttps://space-region.digitaloceanspaces.comSpace 的区域端点用于定位实际 Space 所在区域REQUEST_RECORDING_S3_ACCESS_KEY_ID受限 Space 访问密钥 ID仅需该 Space 的读写删权限REQUEST_RECORDING_S3_SECRET_ACCESS_KEY对应 secret与上面的 access key 配对REQUEST_RECORDING_S3_REGION保持us-east-1按文档要求保持默认值REQUEST_RECORDING_S3_FORCE_PATH_STYLE保持false使用虚拟主机风格virtual-hosted styleURL其中后两个变量的说明值得展开REQUEST_RECORDING_S3_REGIONus-east-1需要原样保留因为 DigitalOcean 的 AWS SDK 指引guidance是通过endpoint来实际选择 Space 所在区域的region 仅用于请求签名REQUEST_RECORDING_S3_FORCE_PATH_STYLEfalse则让 SDK 采用虚拟主机风格寻址而非路径风格这是 DigitalOcean Spaces 兼容 AWS S3 的默认行为。这些变量在源码中的定义见 packages/backend/src/config/app.config.ts它们被逐一读取并注册为 NestJS 配置项requestRecordingS3Bucket: process.env[REQUEST_RECORDING_S3_BUCKET] ?? , requestRecordingS3Endpoint: process.env[REQUEST_RECORDING_S3_ENDPOINT] ?? , requestRecordingS3Region: process.env[REQUEST_RECORDING_S3_REGION] ?? , requestRecordingS3AccessKeyId: process.env[REQUEST_RECORDING_S3_ACCESS_KEY_ID] ?? , requestRecordingS3SecretAccessKey: process.env[REQUEST_RECORDING_S3_SECRET_ACCESS_KEY] ?? , requestRecordingS3ForcePathStyle: process.env[REQUEST_RECORDING_S3_FORCE_PATH_STYLE] true,4.3 底层实现S3RecordingStorage 如何工作request-recording-storage.service.ts 中的S3RecordingStorage类展示了这些配置的真实用途它基于aws-sdk/client-s3构造S3Client将region、endpoint、forcePathStyle与可选的凭证对直接传入new S3Client({ region: config.region, endpoint: config.endpoint, forcePathStyle: config.forcePathStyle, credentials: config.accessKeyId config.secretAccessKey ? { accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey } : undefined, });写入对象时PutObjectCommand将ContentType显式设为application/octet-stream——这是因为请求记录正文是客户端侧密文见 request-recording-codec.ts 的压缩加密逻辑若声明为 gzip 内容编码某些 S3 兼容存储或 CDN 会在 GET 时尝试透明解压导致数据损坏。对象在 Space 中的键名遵循如下层级结构来自 objectKey 方法request-recordings/v1/tenants/{tenantId}/requests/{requestId}/attempts/{attemptId}.json.gz这也印证了文档中请求记录是 Space 中的私有对象的说法——每条请求、每次重试尝试attempt都有独立的对象便于审计与追溯。五、PostgreSQL 连接uselibpqcompat 与 sslmoderequire部署模板会自动把uselibpqcompattrue追加到 DigitalOcean 的 PostgreSQL URL 上。这样做的原因是DigitalOcean 生成的连接串默认带sslmoderequire而 Node 生态的pg驱动在解析这种连接串时需要兼容性开关才能正确处理uselibpqcompattrue让pg采用 libpq 兼容的解析方式从而在 TLS 连接下正常工作。这一处理并非 DigitalOcean 独有——仓库中 deploy/aws/manifest.yaml 的 AWS 部署同样在连接串中拼接了?uselibpqcompattruesslmoderequire可见这是 Manifest 在托管 PostgreSQL 平台上统一使用的连接串约定。如果你在其他平台如 Koyeb上部署deploy/koyeb/TUTORIAL.md 也给出了类似要求连接串需带sslmoderequire无查询参数时用?已有参数时用追加。由于 App Platform 通过环境变量注入数据库连接串你不需要也不应该手动修改DATABASE_URL模板会自动完成上述追加处理。六、验证部署与创建首个管理员App Platform 完成部署后打开应用 URL形如https://your-app.ondigitalocean.app创建第一个账号。第一个注册的账号将成为管理员admin因此请在公开分享应用地址前完成这一步验证后端健康状态打开https://your-app-url/api/v1/health该健康检查端点在源码中位于 health.controller.ts路由为GET /api/v1/health正常返回{ status: healthy, uptime_seconds: 42 }值得注意的细节是当进程进入优雅关停draining状态时该端点会返回503并携带{ status: shutting_down, ... }让平台边缘停止向该副本路由新流量——这也是 App Platform 滚动部署期间判断实例是否健康的重要依据。七、注意事项与生产化建议7.1 Dev Database 仅适合起步DigitalOcean 的部署按钮目前只支持公开仓库与 Dev Database。Dev 档数据库适合试用与开发环境生产数据请从 App Platform 设置中将 Dev Database 升级为托管数据库managed database以获得更优的性能、备份与高可用能力。7.2 切勿移除 S3 变量如第一节所述App Platform 的本地文件系统是临时性的应用重启或实例重建都会清空。因此除非你明确禁用记录持久化否则不要移除上述REQUEST_RECORDING_S3_*变量。Manifest 的存储选择默认是auto能力检测模式见 app.config.ts完整且配对的 S3 凭证优先无 S3 凭证时自托管部署才会回退到挂载的文件系统。在 App Platform 上唯一合理的回退就是 Space移除这些变量等价于放弃记录持久化。7.3 删除应用不会删除 Space删除 App Platform 应用不会级联删除 Space。如果你不再使用请先导出需要的请求记录再单独清理 Space避免数据永久丢失。7.4 其他值得关注的生产配置结合仓库中其他平台部署文档与 .env.example生产环境还建议关注MANIFEST_MODEselfhosted与BIND_ADDRESS0.0.0.0让后端监听所有网卡接口供平台边缘路由流量参考 app.json 与 Koyeb 模板的做法NODE_ENVproduction以生产模式运行后端DB_POOL_MAX按数据库连接上限控制连接池大小避免连接数打满App Platform 的托管数据库同样有连接数限制参见 deploy/heroku/TUTORIAL.md 中按档位调小池的同类处理。结语在 DigitalOcean App Platform 上部署 Manifest 的核心思路可以概括为三句话用 App Platform 跑无状态应用、用 Dev/托管 PostgreSQL 存业务数据、用私有 Space 持久化请求记录。只要在部署前把私有 Space 与受限密钥准备好按模板要求填写两组独立的随机密钥和六个 S3 变量保持REQUEST_RECORDING_S3_REGIONus-east-1与REQUEST_RECORDING_S3_FORCE_PATH_STYLEfalse不变即可顺利完成部署并通过/api/v1/health快速验证。仓库中 deploy/ 目录还提供了 AWS、Fly、GCP、Coolify、EasyPanel、Koyeb、Heroku 等平台的同类指南可作为多平台部署的对照参考。【免费下载链接】llm-gatewayConnect Your Agents And Harnesses With Any Provider 项目地址: https://gitcode.com/GitHub_Trending/manifest7/llm-gateway创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考