目前在和朋友一起开发独立游戏,由于媒体资源占用巨大,我的小机的存储逐渐吃紧,所以动了迁移lfs存储到兼容s3的对象存储上的想法,我选择的对象存储为cloudflare R2。
我的gitea是docker compose部署的,配置文件由docker env动态生成为app.ini [查看对应的官方文档],如果你是其他方式启动的gitea可以根据下面我的配置来进行相应的修改
首先修改容器的environment配置:
# LFS
GITEA__lfs__STORAGE_TYPE = local
GITEA__lfs__PATH = /data/git/lfs
# 存储
#自定义存储名称为cloudflare
#minio意味着是兼容s3的存储
GITEA__storage.cloudflare__STORAGE_TYPE = minio
#这里指向你的cloudflare R2 endpoint
GITEA__storage.cloudflare__MINIO_ENDPOINT = ABCDEFGHIJKLMNOPQRSTUVWXYZ.r2.cloudflarestorage.com
#是否允许提供直连地址
GITEA__storage.cloudflare__SERVE_DIRECT= false
GITEA__storage.cloudflare__MINIO_ACCESS_KEY_ID = [hidden]
GITEA__storage.cloudflare__MINIO_SECRET_ACCESS_KEY = [hidden]
GITEA__storage.cloudflare__MINIO_BUCKET = [hidden]
GITEA__storage.cloudflare__MINIO_LOCATION = auto
GITEA__storage.cloudflare__MINIO_USE_SSL = true
#Minio 校验算法:default(适用于 MinIO 或 AWS S3)或 md5(适用于 Cloudflare 或 Backblaze)
GITEA__storage.cloudflare__MINIO_CHECKSUM_ALGORITHM = md5
添加了自定义的存储配置以后,使用“docker compose down && docker compose up -d”命令重启一次容器,并检查容器内app.ini是否已经成功生成了自定义存储的配置。
接着进入容器的bash环境:
docker exec -it -u git gitea /bin/bash
进入以后在容器内执行下面的指令:
$ gitea migrate-storage -type lfs --minio-base-path lfs/ --storage minio --minio-endpoint ABCDEFGHIJKLMNOPQRSTUVWXYZ.r2.cloudflarestorage.com --minio-access-key-id [hidden] --minio-secret-access-key [hidden] --minio-bucket [hidden] --minio-use-ssl true --minio-insecure-skip-verify false
意思是将当前本地的lfs移动到对象存储上,这里的配置和上方app.ini内的值是一样的。其中minio-base-path这里强制让“lfs”指向“lfs/”目录。type允许什么样的值可以参阅:指令源文件
回车以后,gitea就开始执行数据迁移了

稍等片刻迁移将会结束

迁移完毕以后并修改environment为:
# LFS
GITEA__lfs__STORAGE_TYPE = cloudflare
使用“docker compose down && docker compose up -d”命令重启一次容器
这时候本地的lfs文件夹就可以先移除出gitea的目录,在检查完全不存在问题后彻底删除本地的lfs文件夹。
如果你使用的是 Backblaze B2,那么配置方法也类似,可以这样写:
# 存储
# 自定义存储名称为 backblaze
GITEA__storage.backblaze__STORAGE_TYPE = minio
# 这里指向 Backblaze S3 endpoint
GITEA__storage.backblaze__MINIO_ENDPOINT = s3.us-west-002.backblazeb2.com
# 是否允许提供直连地址(一般设置为 false)
GITEA__storage.backblaze__SERVE_DIRECT = false
GITEA__storage.backblaze__MINIO_ACCESS_KEY_ID = [hidden]
GITEA__storage.backblaze__MINIO_SECRET_ACCESS_KEY = [hidden]
GITEA__storage.backblaze__MINIO_BUCKET = [hidden]
GITEA__storage.backblaze__MINIO_LOCATION = us-west-002
GITEA__storage.backblaze__MINIO_USE_SSL = true
# Backblaze 要用 md5 校验
GITEA__storage.backblaze__MINIO_CHECKSUM_ALGORITHM = md5
然后在 LFS 模块(或 attachments 等)里指定:
# LFS
GITEA__lfs__STORAGE_TYPE = backblaze
这样 LFS 文件就会保存到 Backblaze B2 上,而不是本地。
注意:Gitea 的存储配置有一个容易踩坑的点 —— 全局配置中的 GITEA__storage__MINIO_ENDPOINT 等参数,并不会自动继承到每个子模块(比如 lfs、attachments、avatars、repo-archive 等)。
也就是说,如果你只配置了 GITEA__storage__MINIO_ENDPOINT,但没有在具体模块里(例如 GITEA__lfs__... 或 GITEA__attachment__...)指定 endpoint,Gitea 会在启动时提示 Endpoint: does not follow ip address or domain name standards 之类的错误。
因此推荐的做法是:
1. 在 GITEA__storage.<custom>__... 中完整定义一套对象存储配置(比如上文的 cloudflare)。
2. 在需要的模块里(如 lfs)指定 STORAGE_TYPE = cloudflare 来引用,而不是依赖全局 endpoint。
这样配置更清晰,不容易出错,也便于后期你想把不同的存储模块(比如 LFS、归档、包管理)放到不同 bucket 或不同存储时做扩展。
