内容提要
本文介绍Gitea的CDN化改造,核心是区分站点与分发:ROOT_URL指向Gitea自身,STATIC_URL_PREFIX指向CDN。推荐采用对象存储加CDN,将附件、LFS、归档迁至MinIO/S3,并开启SERVE_DIRECT=true,通过签名直链把大文件流量卸载到对象存储,源站仅返回302。私有资源严禁公共缓存,需依赖签名直链与CDN规则保障安全。改造前应备份配置与数据,并准备回滚方案。
延伸解读
ROOT_URL 与 STATIC_URL_PREFIX 的角色区分
改造中最易混淆的是 ROOT_URL 和 STATIC_URL_PREFIX。ROOT_URL 必须保持为 Gitea 实例的公开地址,它决定路由、OAuth/Webhook 回调以及 git clone 输出的克隆地址。若误将 ROOT_URL 指向 CDN,会导致登录回调失败、克隆地址错误等严重问题。STATIC_URL_PREFIX 则专用于将 /assets/、头像等静态资源前缀改写为 CDN 域名,两者职责分明,不可互换。
SERVE_DIRECT 如何卸载源站流量
开启 SERVE_DIRECT = true 后,Gitea 对附件、LFS、仓库归档不再自行转发字节流,而是返回 HTTP 302 重定向到对象存储生成的带签名临时直链。用户下载流量直接从对象存储或 CDN 获取,源站仅处理元数据与 302 响应。这是从根本上解决大文件占用源站带宽的关键开关,也是方案 B 优于纯 CDN 回源的核心原因。
私有资源的安全边界与签名机制
私有仓库的附件、归档和 LFS 对象严禁公共缓存。SERVE_DIRECT 依赖 HMAC-SHA256 签名直链,签名包含时间戳、过期时间和请求 ID,有效期建议 5-15 分钟,服务端校验时间戳与 nonce 以防重放。CDN 侧应对这类路径设为不缓存或仅缓存鉴权后的响应。同时,跨域时 Access-Control-Allow-Origin 必须指定 Gitea 域名,不可使用通配符。
改造前的备份与回滚准备
改造涉及配置、数据库和存储数据的变更,操作前必须完整备份 app.ini、PostgreSQL 数据库以及数据目录(含本地存储和 LFS)。若从 local 切换到对象存储,还需迁移历史数据,可使用 gitea dump 导出导入或 mc mirror 同步。回滚时停止服务、还原配置与数据、重启即可。建议回滚前再次备份当前配置,确保可双向切换。
Q&A
Gitea 从非 CDN 模式改造为 CDN 模式,核心配置原则是什么?
核心是区分站点与分发:ROOT_URL 必须保持为 Gitea 实例自身的公开地址(如 https://git.example.com/),绝不能指向 CDN;STATIC_URL_PREFIX 则指向 CDN 域名(如 https://cdn.example.com),用于静态资源分发。
为什么推荐使用对象存储加 CDN 的方案,而不是纯 CDN 回源?
纯 CDN 回源方案中,大文件(如仓库归档、LFS)仍从源站出口,带宽痛点未根本解决;而对象存储加 CDN 方案将附件、LFS、归档迁至 MinIO/S3,并开启 SERVE_DIRECT=true,通过签名直链把大文件流量完全卸载到对象存储,源站仅返回 302,从根本上卸载源站带宽。
SERVE_DIRECT 配置项的作用是什么?
SERVE_DIRECT = true 时,Gitea 对附件、LFS、仓库归档不再自己转发字节流,而是重定向(HTTP 302)到对象存储生成的带签名临时直链。这是真正卸载源站流量的关键开关,用户的下载流量直接从对象存储/CDN 走,源站只返回一个 302。
改造后如何验证 CDN 是否生效?
可通过以下方法验证:1) 检查响应头,curl -I 静态资源看是否命中 CDN(如 cf-cache-status: HIT),curl -I 归档看是否 302 到对象存储直链;2) 在 CDN 控制台查看缓存命中率,稳态下静态资源应 > 90%;3) 对比改造前后源站出口带宽与 QPS 曲线;4) 浏览器 DevTools 检查静态资源 Remote Address 是否指向 CDN。
私有仓库的附件和归档在 CDN 模式下如何保证安全?
私有资源严禁公共缓存。SERVE_DIRECT 通过带签名的临时直链访问对象存储,签名采用 HMAC-SHA256 算法,包含时间戳、过期时间(建议 5-15 分钟)和请求 ID 防重放,签名短时效避免越权;CDN 侧对这类路径应设为不缓存或仅缓存鉴权后的响应。
改造过程中如何管理 MinIO 的访问密钥?
MINIO_ACCESS_KEY_ID 和 MINIO_SECRET_ACCESS_KEY 严禁硬编码在 app.ini 中。生产环境建议使用 systemd 的 EnvironmentFile 或启动脚本注入环境变量,或使用 HashiCorp Vault、AWS Secrets Manager 等密钥管理服务。注意 Gitea app.ini 不支持 ${VAR} 插值语法。
如果 CDN 改造失败,如何回滚?
回滚步骤:1) 停止 Gitea 服务;2) 还原备份的 app.ini;3) 如涉及对象存储数据,按需还原数据目录;4) 重启 Gitea。回滚前建议再次备份当前配置,确保可双向切换。