
自建 Gitea 跑久了,Git LFS 大文件、issue 附件、头像、仓库归档、软件包和 Actions 制品会越堆越占本地盘,单机磁盘满了就得停机迁。Gitea 内置的 minio 存储类型能把这批大对象路由到任意 S3 兼容后端,RustFS 正好接上,Git 仓库本体仍留本地,大文件全进桶。
为什么 Gitea 的大文件该挪到对象存储
LFS 对象往往几十 MB 到几 GB,附件和软件包也常是二进制,它们和 Git 提交历史的性质完全不同:不常改、可重算、该和代码仓库解耦。把它们塞进 RustFS 桶之后,Gitea 容器可以随便重建,数据不丢;多实例横向扩展时,大文件也不再是单机的瓶颈。仓库本体、 issue 文本、PR 讨论这些结构化数据仍留在 Gitea 的数据库和本地卷里,只有那批「重」的对象走对象存储。
一份 app.ini 切到 RustFS
Gitea 通过 [storage] 段的 minio 类型连 RustFS,MINIO_ENDPOINT 用 Compose 网络内的 rustfs 主机名,默认走 path-style:
APP_NAME = RustFS Gitea
RUN_MODE = prod
WORK_PATH = /data/gitea
[server]
DOMAIN = localhost
ROOT_URL = http://localhost:3000/
HTTP_PORT = 3000
LFS_START_SERVER = true
[database]
DB_TYPE = sqlite3
PATH = /data/gitea/gitea.db
[storage]
STORAGE_TYPE = minio
MINIO_ENDPOINT = rustfs:9000
MINIO_ACCESS_KEY_ID = <your-access-key>
MINIO_SECRET_ACCESS_KEY = <your-secret-key>
MINIO_BUCKET = gitea-data
MINIO_LOCATION = us-east-1
MINIO_USE_SSL = false
[log]
MODE = console
LEVEL = info
[security]
INSTALL_LOCK = true
SECRET_KEY = change-me-to-a-random-string
这份配置覆盖 LFS、附件、头像、仓库归档、软件包和 Actions 制品六类存储段。官方用 gitea/gitea:1.24.4 对 rustfs/rustfs-x86-musl:v2.3.1 验证过,桶不存在时 Gitea 会在启动时自动创建。MINIO_LOCATION 同样是满足字段必填,真实路由靠 MINIO_ENDPOINT 指向 RustFS。Compose 里给 RustFS 服务加一个 /health 探活,让 Gitea 用 depends_on: condition: service_healthy 等存储就绪再起,能避免启动竞态;Gitea 容器设 USER_UID/USER_GID 让写入的文件属主稳定,省得挂载卷权限错乱。

六类存储段都去了哪
minio 类型一旦配好,六类大对象会一起改道进桶:LFS 是 Git 大文件的实体,键名是内容 SHA-256,所以同一份内容不会重复存;附件是 issue、PR 里上传的文件,落在 attachments/ 前缀;头像是用户图片;仓库归档是 git archive 打出的压缩包;软件包是 Gitea Package Registry 的产物;Actions 制品则是 CI 跑出来的产物。它们键名前缀不同,但都在同一个 gitea-data 桶里,IAM 策略只要放通这一个桶就能全覆盖。也正因为都在同一个桶,按桶做生命周期、跨区复制、审计都只需一套策略,运维面比散在多台机器本地盘简单得多。软件包和 Actions 制品这两类往往体积大、访问频度低,原本最容易被本地盘忽略、进而拖垮整机;移进 RustFS 后,它们和 LFS 一样走对象存储的弹性容量,发布再频繁也不占 Gitea 本机空间。Git 仓库本身的提交对象、ref、配置仍在 Gitea 的本地卷与数据库,不进对象存储,这也意味着仓库元数据仍要单独备份。
LFS 指针文件是怎么回事
提交里并不会直接塞进几百 MB 的二进制,Git 只放一个 LFS 指针文件,内容是一段含 SHA-256 和原始大小的文本,*.bin 这类大文件由 .gitattributes 里的 git lfs track 规则标记。真正的字节在推送时由 LFS API 写到 RustFS,克隆时按指针里的哈希从桶里拉回。所以上 RustFS 之后,本地仓库反而更轻,重对象全在对象存储一侧按需取用,这也是大仓库迁移到 LFS 后克隆飞快的原因。
推一个 LFS 对象验证落桶
在网页建好仓库后,从工作站推一个 LFS 跟踪的文件:
mkdir lfs-demo && cd lfs-demo
git init
git config user.email you@example.com
git config user.name you
git lfs install
git lfs track "*.bin"
git add .gitattributes
dd if=/dev/urandom of=dataset.bin bs=1M count=8
git add dataset.bin
git commit -m "add LFS dataset"
git remote add origin http://localhost:3000/<your-username>/rustfs-demo.git
git push origin main
git push 经 Gitea 的 LFS API 把对象写进 RustFS。把仓库克隆到另一目录执行 git lfs pull,两份 dataset.bin 的 sha256 一致,因为两个客户端都从 RustFS 读对象。issue 里上传的附件则以 attachments/<前缀>/<uuid> 形式落桶。
用 RustFS 自带命令行核对对象确实在桶里:
docker compose exec rustfs /usr/bin/rc ls local/gitea-data/ -r
输出里的 lfs/ 和 attachments/ 两类键,就是 LFS 对象与附件。LFS 对象的键是 Git LFS 协议用的 SHA-256 内容哈希,所以同一份内容不会被重复存储。
容量随桶走,不再受单机盘限制
把大对象迁到 RustFS 之后,最直观的变化是 Gitea 不再被单机磁盘容量卡脖子:本地卷只装 Git 仓库元数据,几 GB 就够;LFS、附件、制品这些会膨胀的部分在对象存储一侧按需增长,加盘扩桶即可,不用停机迁数据。对发布频繁、CI 产出多的团队,这层解耦能少很多「磁盘满了停机清」的事故。和本地盘相比,对象存储的扩容是在桶侧加盘而非停机迁数据,Gitea 侧感知不到。代价是对象存储的出口流量和存储量要单独算账,大文件频繁拉取时留意带宽,必要时配合上一段说的缓存层一起用。
已有本地 LFS 怎么迁到 RustFS
对已经在跑、大文件存在本地的 Gitea,改 [storage] 切到 RustFS 后,新写入会直接进桶,但存量对象不会自动搬。稳妥做法是先在新配置下做一次全量 git lfs fetch --all 把对象拉回,再 git lfs push --all origin 推到接了 RustFS 的实例,存量迁移期间双写验证一致再切流量。这不是零停机操作,挑低峰做,并提前用 gitea dump 备份仓库与数据库。
排查三类启动异常
打开的是 Gitea 安装页而不是登录页:配置文件必须位于容器内 /data/gitea/conf/app.ini,挂载路径不对就会用默认配置走安装向导,按 Compose 示例挂载文件并重启。推送失败报 LFS 或 403:核对 app.ini 里的凭证与 RustFS 一致,并确认 rustfs 主机名在 Compose 网络内能解析,看 docker compose logs gitea | grep -i minio 能定位。对象写进了本地存储而不是 RustFS:环境变量 GITEA__storage__STORAGE_TYPE: minio 与 app.ini 的 [storage] 段必须一致,改完重启再看 Initialising 日志行。

接下来该做的
验证通过后,下一步用访问密钥管理给 gitea-data 桶换专用凭证,别和其他业务共用。建议再套一条 IAM 策略把这对密钥的权限收到 gitea-data 这一个桶,即使密钥泄露影响面也只在这个桶。生产环境把 SQLite 换成 MariaDB/PostgreSQL,并按 Gitea 文档把软件包、Actions 制品拆到独立桶,避免一类数据膨胀拖垮另一类。官方接入指南在 devops/gitea,Gitea 项目见 GitHub,RustFS 仓库在 github.com/rustfs/rustfs。桶侧也可以顺手配生命周期,把冷附件自动沉降到更低成本的存储层,进一步省存储开销。
本文介绍如何将Gitea的LFS大文件、附件、头像、仓库归档、软件包及Actions制品等六类大对象统一迁移至RustFS作为S3兼容后端,解除单机磁盘容量瓶颈。通过配置app.ini启用S3存储类型,利用RustFS提供高兼容性、自动建桶、路径式访问等能力,实现数据解耦、多实例扩展与运维简化。内容涵盖配置方法、存储路由逻辑、LFS指针机制、落桶验证、存量迁移及常见启动异常排查。
433

被折叠的 条评论
为什么被折叠?



