OSS Hub 部署与工程化:从本地运行到生产迁移
OSS Hub 部署与工程化:从本地运行到生产迁移
对象存储管理平台会接触 AccessKey、用户权限、文件删除和 Bucket 配置,因此“本地能跑”只是起点。
这篇文章整理 OSS Hub 从初始化到生产部署的完整链路,包括环境变量、数据库、构建产物、反向代理、OpenAPI、测试和演进边界。
运行要求
项目要求 Node.js 20.12+ 或 22+,推荐使用 Node.js 22 或更高 LTS 版本。
根目录使用 npm workspaces 管理:
backendfrontend安装一次依赖后,可以在根目录统一启动、构建、类型检查和测试。
本地快速开始
最短初始化流程是:
cp .env.example .envnpm installnpm run prisma:generatenpm run prisma:migratenpm run dev默认地址:
- 前端:
http://localhost:10011 - 后端:
http://localhost:10010 - 健康检查:
http://localhost:10010/health - OpenAPI:
http://localhost:10010/openapi.json
没有 SSO 时使用内置登录
.env.example 默认偏向 SSO。如果本地没有身份服务,可以改成:
AUTH_MODE=localVITE_AUTH_MODE=localLOCAL_ADMIN_USERNAME=adminLOCAL_ADMIN_PASSWORD=<本地强密码>后端和前端的认证模式必须一致。
VITE_* 变量会进入前端构建产物,因此修改生产认证模式后需要重新构建前端。
本地管理员只在 local 或 both 模式,并且密码已配置时自动创建或补齐管理员权限。
SSO 配置
SSO 模式需要配置:
- Issuer。
- Authorization Endpoint。
- Token Endpoint。
- JWKS URI。
- Client ID。
- Redirect URI。
- Logout Endpoint 或退出跳转地址。
- Audience 和权限 claim 规则。
前端负责 Authorization Code + PKCE,后端只接受 Bearer token 并执行 JWT/JWKS 验证。
生产环境需要确保:
- 回调地址与 SSO 应用配置完全一致。
- Issuer、Audience 和 JWKS 来源可信。
- 全站使用 HTTPS。
- 不在日志中记录完整 token。
第一条云存储
首次启动且数据库为空时,后端会创建一条默认云存储记录。
如果 .env 中的对象存储配置完整,会加密写入数据库;如果还是占位值,登录后需要在“设置 -> 云存储配置”补充。
需要确认:
- 云服务商分类。
- SDK 协议。
- Region 和 Bucket。
- AccessKey ID 与 Secret。
- 后端 SDK Endpoint。
- 公共访问域名。
- S3 是否使用 Path Style。
浏览器直传需要 Bucket CORS
前端把文件直接 PUT 到对象存储,因此浏览器检查的是 Bucket CORS,而不是 OSS Hub API 的 CORS。
至少需要根据实际上传方式允许:
- OSS Hub 页面域名。
PUT、POST、GET、HEAD等方法。Content-Type、ACL、存储类型和 Object 标签相关请求头。- 暴露
ETag或etag响应头。
如果目录浏览正常、后端 API 正常,但浏览器上传失败,最先检查的应当是 Bucket CORS。
分片上传能成功完成单个 PUT,却在最后提示缺少 ETag,也通常是因为没有暴露响应头。
开发与生产构建
开发环境:
npm run dev生产构建:
npm run build根构建流程会:
- 编译后端 TypeScript。
- 类型检查并构建 Vue 前端。
- 把前端产物复制到后端静态目录。
- 检查生产构建是否完整。
生产运行时由 Fastify 同时提供 API 和前端静态资源:
npm run start这样反向代理只需要指向一个后端端口,避免分别部署两个服务。
生产准备脚本
仓库提供生产准备脚本,用于检查环境、生成 Prisma Client、执行迁移并构建产物:
chmod +x scripts/prepare-production.sh./scripts/prepare-production.shnpm run prod:start:env生产环境应把 .env 作为受控配置文件,不提交到版本库。
SQLite 部署
SQLite 适合:
- 个人使用。
- 小团队单实例。
- 较低并发。
- 希望部署和备份简单的环境。
生产使用 SQLite 时需要:
- 把数据库放在持久化目录。
- 使用生产迁移命令,而不是
migrate dev。 - 定期备份数据库文件。
- 避免多个后端实例同时写同一个文件。
- 在备份和升级前确认服务状态。
SQLite 并不是对象文件本身的存储位置,因此数据库备份只包含配置、权限、索引、标签、会话和审计信息。
PostgreSQL 迁移
项目维护独立的 PostgreSQL Prisma schema,并提供完整迁移流程:
prepare -> preflight -> copy -> verify -> cutover对应命令包括:
npm run db:postgresql:preparenpm run db:postgresql:preflightnpm run db:postgresql:copynpm run db:postgresql:verifynpm run db:postgresql:cutover如果切换后发现问题,还提供 SQLite 回滚脚本:
npm run db:sqlite:rollback迁移前需要确保:
- SQLite 和 PostgreSQL schema 保持同步。
- 目标数据库为空或符合脚本预期。
- JSON、BigInt、时间和枚举字段转换正确。
- 用户、权限、文件、标签和对账记录数量一致。
- 新后端只连接一个最终数据库。
prisma:schema:check 用于避免两套 schema 随代码演进而产生漂移。
配置密钥管理
至少有两类密钥不能使用默认值:
AUTH_JWT_SECRET=<随机长字符串>CONFIG_ENCRYPTION_KEY=<另一条随机长字符串>它们的用途不同:
AUTH_JWT_SECRET:内置登录 token 签名。CONFIG_ENCRYPTION_KEY:云存储配置加密。
不应复用同一个值。
可以使用密码管理器、部署平台 Secret 或系统级环境文件管理。配置加密密钥一旦用于写入数据库,轮换前必须先设计重新加密流程。
反向代理
生产环境建议使用 Nginx、Caddy 或云负载均衡提供 HTTPS,再代理到 Fastify。
需要正确传递:
HostX-Real-IPX-Forwarded-ForX-Forwarded-Proto
SSO 回调、退出地址、CORS Origin 和站点公开地址都应使用最终 HTTPS 域名,而不是内部端口。
OpenAPI
项目把公开接口目录和 OpenAPI 文档纳入代码管理。
常用命令:
npm run openapi:generatenpm run openapi:checkOpenAPI 3.1 文件不仅描述路径、请求和响应,还记录接口所需权限。前端内置 API 文档页面直接使用这份接口目录。
这样可以避免三套信息分裂:
- 后端真实路由。
- 仓库文档。
- 前端 API 指南。

测试体系
项目测试分为几层。
后端单元测试
覆盖:
- 权限继承。
- ObjectKey 处理。
- 输入校验。
- 存储协议映射。
- 上传和同步中的纯逻辑。
一致性测试
检查:
- SQLite 与 PostgreSQL schema 是否同步。
- OpenAPI 与接口目录是否一致。
- 关键配置和生成文件是否漂移。
性能边界测试
验证分页、批量处理、同步步长和大数据量下的关键逻辑不会出现明显退化。
API 测试
使用构建后的 Fastify 应用验证认证、权限、文件和管理接口。还可以通过环境变量选择真实对象存储执行 live 测试。
前端与 E2E
- Node 测试设备识别等纯逻辑。
- Playwright 覆盖桌面页面。
- 独立 Playwright 用例覆盖移动端页面。
提交前主检查命令是:
npm run test:ci它串联 schema、OpenAPI、类型检查、后端测试、前端单元测试和生产构建。
安全边界
OSS Hub 的关键安全规则包括:
- 所有业务接口都需要认证。
- 所有写操作都需要服务端权限检查。
- 永久 AK/SK 不进入前端。
- 预签名 URL 必须短期有效,并限定对象 Key 和操作。
- 云存储凭据加密入库。
- 文件名和路径由后端标准化。
- 文本预览限制大小。
- SVG 不以内联 HTML 方式渲染。
- 删除和配置修改写入审计日志。
- 上游错误不返回密钥、内部路径和完整堆栈。
- 生产环境必须使用 HTTPS 和强随机密钥。
运维检查清单
上线前可以按下面顺序检查:
- SSO 或内置登录能正常完成。
- 普通用户只看到被授权的云存储。
- AccessKey 不出现在接口响应和浏览器存储中。
- Bucket CORS 允许小文件和分片上传,并暴露 ETag。
- 文件浏览、搜索、预览、下载和删除正常。
- 上传完成后数据库索引正确创建。
- 同步任务能发现缺失和变化对象。
- SQLite 或 PostgreSQL 备份策略已配置。
npm run test:ci通过。- HTTPS、反向代理和 SSO 回调地址使用最终域名。
当前边界
OSS Hub 已经形成完整闭环,但仍有明确边界:
- 大规模多实例部署更适合 PostgreSQL,而不是共享 SQLite。
- 预签名 URL 仍然依赖 Bucket CORS 正确配置。
- 不同 S3 兼容服务对生命周期、ACL 和标签的支持程度不同。
- 图片处理和防盗链是阿里云 OSS 扩展能力。
- 数据库索引不能保证实时反映所有外部对象变更,需要同步或访问时检查。
- 浏览器保存分片恢复状态,不等于服务端可以在任意设备自动续传。
后续演进
可以继续扩展的方向包括:
- 后台定时同步和任务队列。
- 更完整的跨设备分片续传。
- 对象版本管理和回收站恢复。
- CDN 刷新与缓存状态。
- 更细粒度的目录级权限。
- 审计日志查询和告警。
- 指标监控和对象存储调用成本统计。
- 更多 S3 兼容服务的能力探测。
- 配置密钥轮换和外部 Secret Manager。
系列总结
OSS Hub 最终解决的不是“如何上传一个文件”,而是对象存储进入团队日常使用后的一整套问题:
- 身份从哪里来。
- 谁可以访问哪个 Bucket。
- 文件如何避免经过业务服务器。
- 大文件失败后如何恢复。
- 对象如何被搜索和分类。
- 数据库与远端不一致时如何发现和修复。
- 多云差异如何被隔离,而不是散落在业务代码中。
- 项目如何被构建、测试、迁移和部署。
当这些问题形成闭环,对象存储才从一个 SDK 和 Bucket,变成一个真正可以交付给用户的资源管理平台。
部分内容可能已过时
OSS Hub 对象存储管理平台
记录 OSS Hub 从项目定位、多云对象存储适配、浏览器直传、索引对账,到 Vue 管理后台、部署和工程化收尾的完整实现。
March7th