☰
Gitea LFS上传报413?从Nginx到Gitea逐层排查与解决
2026/10/17 14:42:09 网站建设 项目流程

1. Gitea LFS 遇到 413:先分清是谁“嫌你文件大”

如果你在用 Gitea 做团队代码托管,并且开了 Git LFS 来管大文件,那么你对 HTTP 413 应该不陌生。常见场面是:本地推一个几百 MB 的设计素材或者模型包,git push一开始还好,传到一半终端直接报错,服务端甩回来一个413 Request Entity Too Large。很多人第一反应是去翻 Gitea 的 LFS 配置,折腾了半天却没用,原因多半是卡在了 Gitea 前面的 Nginx / Apache 反向代理上。

HTTP 413 的意思是“请求体太大”,服务端拒绝接收。放在 Gitea LFS 的场景里,就是你推的大文件对象已经进入 HTTP 请求体,但还没等 Gitea 的 LFS 逻辑处理,就被前置 Web 服务拦下了。换句话说,这不是 Gitea 不让你传,而是挡在它前面的代理不让你传。这个问题很适合刚接触自建 Git 服务的同学,也适合被运维问题困住的开发者,因为定位思路一旦理顺,改起来其实非常快。

1.1 一条最典型的 413 报错

先看现象。假设你往一个 Gitea 仓库推送 LFS 对象,文件大约 390 MB,终端的输出大概是这样的:

$ git push origin main Uploading LFS objects: 0% (0/1), 390 MB | 0 B/s ... batch response: HTTP 413 error: failed to push some refs to 'http://git.example.com/team/assets.git'

有些版本还会在batch response后面附带Repos或者 URL 信息,但核心不会变:客户端把对象交给服务器时,服务器在 HTTP 层直接拒绝了 413。

如果你去 Nginx 的 error log 里翻,会看到一条很经典的记录:

client intended to send too large body: 1048576 bytes

这里的1048576是 1 MB,正好是 Nginx 默认的请求体上限。也就是说,你的 LFS 对象超过 1 MB,Nginx 在读取请求体的过程中发现已经超额,直接中断并返回了 413。这条日志几乎可以一锤定音:问题在 Nginx,不在 Gitea。

1.2 请求链路里到底哪个环节会产生 413

Gitea 常见的部署方式是“Nginx / Apache / Caddy 反向代理 + Gitea 本地监听 3000 端口”,甚至再加上 Docker。你的请求链路通常是:

git 客户端 ↓ HTTP Nginx 反向代理(443 或 80) ↓ 转发 Gitea(127.0.0.1:3000) ↓ LFS 存储(本地磁盘 / S3 等)

这条链路里,只要有一层对“请求体大小”做了限制,就可能出现 413。Nginx 默认限制 1 MB,Apache 默认对LimitRequestBody也有自己的行为,Gitea 自身在 LFS 上同样存在文件大小配置。不同层的限制值还不一样,所以“到底是谁拦的”才是排查重点。

有一个生活化的类比:你想把一个大箱子寄出去,快递柜门口的尺寸限制没通过,你就算把箱子打包得再严实也没用。反向代理就是那个快递柜,它不关心箱子里是什么,只关心“你这个 HTTP 请求体有多大、超没超我设定的上限”。

1.3 先做一个快速区分:绕过反向代理直连 Gitea

判断 413 来自哪一层,最快的方法是绕过 Nginx / Apache,直接推给 Gitea。如果 Gitea 直接监听3000端口,而你又能从某台服务器上访问它,可以临时把远端地址改成直连:

git remote set-url origin http://127.0.0.1:3000/team/assets.git git push origin main

如果你发现直连 Gitea 时同样的文件能传上去,走域名就不行,那几乎可以肯定,问题出在反向代理那一层。如果直连 Gitea 也 413,再考虑 Gitea 自身的 LFS 限制。这个对照实验花不了两分钟,但能帮你少走很多弯路。

2. 最常见解法:调整 Nginx 的请求体大小上限

Nginx 反向代理是 Gitea LFS 场景里出现 413 的重灾区,因为它的默认client_max_body_size只有 1 MB。团队里只要有人传一个超过 1 MB 的 LFS 文件,基本就会立刻踩中。解决方案也很直接:把上限调高,通常调到团队最大单个 LFS 文件的 1.2 倍左右。

2.1 找到正在用的 Nginx 配置

先确认你服务器上 Nginx 的实际配置路径。不同安装方式路径会不一样:

/etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf /etc/nginx/sites-available/*

如果 Nginx 跑在 Docker 里,配置文件通常在容器内,也可能通过-v参数挂载到宿主机。我的建议是先执行下面这条命令,看当前的client_max_body_size到底是多少:

grep -r "client_max_body_size" /etc/nginx/

只要某个配置文件里改了它,grep 就能看到。如果一条都没搜到,说明用的是默认的 1 MB,这就是 413 的直接来源。

2.2 正确的配置应该写在哪个位置

client_max_body_size可以写在http、server、location三个层级里。正常生产环境我推荐写在 Gitea 对应的server块里,这样只对当前站点生效,避免影响同一个 Nginx 上的其他服务。

假设你的 Nginx 配置长这样:

server { listen 443 ssl http2; server_name git.example.com; client_max_body_size 1024m; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }

1024m表示 1024 兆,也就是 1 GB。Nginx 的 size 单位还可以写成1g,但为了统一便于理解,我习惯用m为单位。

如果你想更精准一点,只针对 LFS 上传接口放开限制,也可以写在location里。Gitea 的 LFS 请求路径一般形如:

/team/assets.git/info/lfs/objects

可以在反向代理配置中单拎出来:

location ~ ^/.*\.git/info/lfs/ { client_max_body_size 2048m; proxy_pass http://127.0.0.1:3000; }

不过说实话,对于大多数团队仓库,直接在server块设一个合理上限就够了,不需要为 LFS 单独建location。除非你同一个 Nginx 上还挂了其他业务,且不希望它们共用这么大的请求体上限。

2.3 改完配置后必须做校验和重载

改 Nginx 配置文件有个铁律:先nginx -t再看结果,最后再 reload,不能直接 restart 一把梭。很多 413 没解决,不是因为改成不够大,而是因为配置文件写错了,Nginx 根本没加载成功。

校验命令:

sudo nginx -t

看到syntax is ok和test is successful之后再重载:

sudo systemctl reload nginx

如果 Nginx 跑在 Docker 容器里,配置文件也在容器内,需要进容器执行:

docker exec <nginx容器名> nginx -t docker exec <nginx容器名> nginx -s reload

重载后别急,先去 error log 里确认没有新的client intended to send too large body记录,再用一个大文件真真切切推一次。

3. Apache 反向代理 Gitea:用 LimitRequestBody

不是所有人都用 Nginx。有些团队习惯用 Apache 作为前置 Web 服务,Gitea 同样会被ProxyPass反代到后端。Apache 环境下出现 413,一般不是client_max_body_size,而是LimitRequestBody。

3.1 在虚拟主机配置里放开请求体限制

Apache 的LimitRequestBody默认情况下并不是无限制的,而且不同版本、不同模块下表现可能不一样。最稳妥的办法是显式设置一个足够大的值。这个指令的单位是字节,假设你想允许 1 GB,需要写成:

1073741824

在虚拟主机里配置如下:

<VirtualHost *:443> ServerName git.example.com ProxyPass / http://127.0.0.1:3000/ ProxyPassReverse / http://127.0.0.1:3000/ LimitRequestBody 1073741824 </VirtualHost>

改完以后,需要验证配置并重载 Apache:

sudo apachectl configtest sudo systemctl reload apache2

有些发行版的命令可能是httpd -t,不过套路一致:先检查配置语法,再平滑重载。

3.2 多个虚拟主机时别改错层级

如果你这台服务器上不止一个站点,LimitRequestBody最好写在 Gitea 对应的<VirtualHost>内部,不要随手写到全局配置里。否则别的站点如果也希望限制上传体积,就会因为你这个“放宽”操作一起被影响。

还有一个容易踩的坑:LimitRequestBody可以写在<Directory>、<Location>或ProxyPass相关的上下文里,如果你用了很复杂的路径规则,最好先确认当前配置文件的httpd.conf版本到底支持哪种写法。绝大多数 Gitea 反代场景就是 VirtualHost 一层,写在里面就行。

4. 如果请求已经到了 Gitea:检查 Gitea 自身的 LFS 限制

反向代理调整好了,还是 413,那就需要把注意力转向 Gitea 本身。虽然这种情况没有 Nginx 那么常见,但一旦遇到,很多人会反复抓头:代理都放开了,TLS 也没问题,为什么还是被拒?原因可能是 Gitea 的app.ini里配置了 LFS 文件大小上限。

4.1 app.ini 中的 LFS 文件大小配置

Gitea 的配置文件无论用二进制部署还是 Docker 部署,最终都会落到custom/conf/app.ini。常见路径有:

/var/lib/gitea/custom/conf/app.ini /data/gitea/conf/app.ini

在配置文件中,LFS 相关的核心参数在[server]段:

[server] LFS_START_SERVER = true LFS_MAX_FILE_SIZE = 0

LFS_MAX_FILE_SIZE的单位是字节,0表示不限制。如果你发现这里被设置成了类似104857600的值,也就是 100 MB,那么超过 100 MB 的 LFS 对象就会被 Gitea 拒绝。因为 LFS 服务收到上传请求后,会先判断对象大小是否超过这个值,超了就直接返回客户端错误,其中就包括 413。

所以当“绕过代理直连 Gitea 也 413”时,第一件事就是检查这个值。你可以先看当前值:

grep -A 5 "\[server\]" /data/gitea/conf/app.ini

如果确认被限制了,把它改成 0,或者改成团队需要的合理值:

[server] LFS_MAX_FILE_SIZE = 2147483648

这表示允许最大 2 GB 的 LFS 文件。注意这里的 2 GB 是单个文件大小,不是仓库总量。

4.2 修改后如何平滑生效

Gitea 不会像 Nginx 那样自动 reload 配置,改完app.ini后需要重启 Gitea 服务。systemd 部署通常是:

sudo systemctl restart gitea

Docker 部署则是在容器配置挂载正确的前提下重启容器:

docker restart <gitea容器名>

重启之后,再推一次大文件验证。如果之前是 Gitea 限制导致的 413,你会发现这一步之后问题就消失了。

这里有个小提醒:如果在[server]段写了很多自定义配置,修改的时候要格外小心,别把其他键值不小心动掉。Gitea 对app.ini里的未知键值虽然不至于报错,但某些键之间是有关联的,最好只改当前需要的一个。

5. 从零开始的完整排查流程:从复现到收尾

前面几个章节把每个可能的原因都拆开讲了,但实际生产环境里问题不会主动告诉你“我是谁的错”。我在处理这类问题时,一般会按一套完整的顺序来,效率高,也不会漏。

5.1 抓取客户端侧的详细日志

先让报错现场留下完整记录。Git 的 HTTP 请求细节默认是不打印的,所以需要强制打开:

GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push origin main 2>&1 | tee /tmp/git-push.log

这条命令会把所有 HTTP 请求头、响应头和 Git LFS 的输出都留在/tmp/git-push.log。你可以在里面搜HTTP/1.1 413,也可以搜索Request Entity Too Large。拿到确切的响应码,后续排查就有方向了。

如果日志里能看到类似:

< HTTP/1.1 413 Request Entity Too Large < Server: nginx

那就明确说明响应来自 Nginx。如果Server头显示的是 Gitea 或别的信息,那就更可能是 Gitea 自身。

5.2 绕过反向代理,直连 Gitea 做对照实验

这是判断“代理拦截”还是“后端拒绝”最有效的一条路。临时把远端地址切到 Gitea 的直连地址:

git remote set-url origin http://127.0.0.1:3000/team/assets.git git push origin main

前提是你能访问到 Gitea 的监听端口。如果你部署在云端安全组内,用内网地址更安全;如果 Gitea 只监听了127.0.0.1:3000,你需要登录到本机操作,或者用 SSH 隧道把本地端口转发过去。

重点观察两个差异:

  • 直连 Gitea 成功走完推送,走域名失败:反向代理上限太小。
  • 直连 Gitea 仍然 413:Gitea 自身 LFS 限制,或更下游的存储配置有问题。

这个对照做完,你基本能确定问题归属。

5.3 逐层修改并验证

确定是反向代理之后,按之前章节的配置改。每一步改完,不要急着把别的配置也一起动,一次只改一个变量,验证一次。我的习惯顺序是:

  1. 先看 Nginx / Apache 的 error log。
  2. 修改请求体大小上限。
  3. 配置语法检查。
  4. 平滑重载。
  5. 再推一次 LFS 文件。

如果还在 413,再回到app.ini看LFS_MAX_FILE_SIZE。这样每一步都有日志可对,不容易出现“反正我把所有配置都改了,也不知道哪一步起作用”的糊涂账。

5.4 最后用真实文件推一次

很多人改完配置后,随便找一个几十 MB 的文件测试,以为没问题了。这样其实不够,因为你的限制可能是 512 MB,而测试文件才 10 MB,根本测不出边界。建议用团队里“最大的那一个 LFS 文件”去验证,或者用dd生成一个接近限制值的临时文件。

生成一个大文件:

dd if=/dev/zero of=/tmp/big-test.bin bs=1M count=1200

这会生成一个 1200 MB 的文件,如果你把client_max_body_size设置成1024m,这个测试正好能复现 413;如果你设置成1500m,它又能证明已经够了。测完记得清理测试文件,不要真的推到生产仓库里。

6. 常见问题与避坑经验

这个章节结合我自己的实际经验,把最容易出问题的几个点整理一下。里面的坑不一定能在文档里看到,但踩过的朋友应该都知道那种“明明按步骤做了,怎么还不行”的抓狂感。

6.1 改完 Nginx 依然 413 的几种情况

最常见的是“改错地方了”。你 grep 到某个配置文件已经写了client_max_body_size 1024m,但可能那个配置块根本不是 Gitea 这个站点用的。Nginx 的server_name匹配很严格,你可能改了 A 站点的 server 块,实际上 Gitea 跑在 B 站点下面。所以我建议先确认:

nginx -T 2>/dev/null | grep -A 10 "server_name git.example.com"

看这个 server 块里有没有生效的client_max_body_size。

第二种常见情况是“改了配置没重载”。有些同学改完文件直接不管了,Nginx 还是旧配置在工作,自然 413 依旧。必须执行nginx -t和systemctl reload nginx。

第三种情况是用了多层代理。比如服务器前面还有一层 CDN 或云负载均衡,这些前置服务也可能有请求体大小限制。你本地调 Nginx 调了半天,其实最外层还有一个看不见的拦截者。这种情况需要到对应控制台查看请求日志或者限制配置。

6.2 413 与 Git 缓冲区的关系

很多人碰到 413 会条件反射去执行:

git config http.postBuffer 524288000

这个动作对普通 Git 大包上传可能会有用,因为它改的是客户端在 HTTP 协议里发送 pack 数据时的缓冲策略。但对 Git LFS 的 413 来说,作用非常有限。LFS 对象走的是 Gitea 的 LFS API,请求体就是那个对象文件本身,Nginx 在服务端看到请求体太大就直接 413 了,客户端缓冲区改成什么都绕不过服务端限制。

所以我的建议是:在做任何客户端调整之前,先把服务端反向代理和 Gitea 的限制查一遍。服务端不放开,客户端改再多也是白搭。

6.3 到底给多大才不算“拍脑袋”

client_max_body_size不能乱设,太小没意义,太大又有风险。比较合理的做法是“团队最大单个 LFS 文件 + 20% 余量”。

假如你们团队明确约定单个文件不超过 2 GB,那 Nginx 可以设置成:

client_max_body_size 2304m;

这样既保证正常业务不会碰到边界,也给请求头、Content-Type 等额外字节留了空间。如果完全不知道上限,可以先设成1024m,跑一段观察,再根据实际使用情况调整。

我个人的经验是:除非是自己一个人用的服务器,否则别为了省事直接写成0。0代表不限制,虽然省心,但容易让异常请求或者恶意上传无限占用带宽和磁盘。给一个明确但宽松的上限,比“彻底放开”安全得多。

最后再分享一个小技巧

如果你已经按上面所有步骤排查过,却还是遇到 413,不妨检查一下 Nginx 的 access log 和 Gitea 的 log 时间是否对齐。有些问题看上去是配置问题,其实是多个服务实例并存导致的“你改的是 A 服务,流量实际走了 B 服务”。这时候不是继续改参数,而是先去把实际接收请求的服务实例找出来。

处理 Gitea LFS 的 413,说穿了就是一层一层问:请求体被谁拒绝了?是 Nginx、Apache,还是 Gitea 自己?只要这个思路清晰,绝大多数情况五分钟内就能解决。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询