- Published on
Git LFS 푸시 실패 413·403 원인과 해결법
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버에 대용량 바이너리(모델, 데이터셋, 영상, 아카이브)를 올리기 위해 Git LFS(Git Large File Storage)를 붙였는데, 막상 git push에서 413 또는 403이 터지면 꽤 난감합니다. 특히 CI/CD나 사내 GitLab(또는 프록시 뒤 Git 서버) 환경에서는 “내가 뭘 잘못했지?”보다 “어디가 막고 있지?”가 더 정확한 질문입니다.
이 글은 Git LFS 푸시 실패 413·403을 빠르게 분류하고, 클라이언트/서버/프록시/권한 관점에서 해결하는 체크리스트를 제공합니다. 단순히 http.postBuffer 같은 민간요법이 아니라, LFS가 실제로 어떤 요청을 보내고 어디서 차단되는지 기준으로 접근합니다.
1) 먼저 이해하기: Git push와 LFS push는 다르다
Git LFS를 쓰면 git push 한 번에 두 종류의 업로드가 일어납니다.
- Git 객체(push): 커밋/트리/태그 등 일반 Git 오브젝트
- LFS 객체 업로드: LFS 서버로 바이너리(large object)를 별도 업로드
즉, 에러가 413/403으로 났을 때 Git HTTP 엔드포인트가 막힌 건지, LFS 엔드포인트가 막힌 건지를 구분해야 합니다. LFS는 보통 다음과 같은 흐름을 탑니다.
POST /info/lfs/objects/batch(업로드/다운로드 URL을 받는 배치 API)- 그 다음 실제 바이너리 업로드(대개
PUT또는POST)
따라서 413/403이 뜨면 “Git 서버”가 아니라 프록시(Nginx/ALB/Cloudflare) 또는 LFS 백엔드가 요청 바디/권한을 차단했을 가능성이 큽니다.
2) 증상별 빠른 분류: 413 vs 403
2.1 413 (Request Entity Too Large)
의미: 요청 바디가 너무 큼. 보통 다음 지점에서 발생합니다.
- Nginx
client_max_body_size제한 - GitLab/Gitea/Bitbucket 앞단 프록시 제한
- ALB/Ingress 컨트롤러 바디 제한(또는 업로드 처리 방식)
- 일부 WAF 규칙(대용량 업로드 차단)
특징:
- 작은 파일은 되는데 특정 크기부터 실패
- LFS batch는 성공하고 실제 업로드에서 실패하는 경우가 많음
2.2 403 (Forbidden)
의미: 권한/인증/정책 차단. 대표 원인:
- LFS URL은 맞지만 토큰/자격 증명이 없음 또는 만료
- Git은 푸시 되는데 LFS 업로드만 403 (LFS 권한 별도)
- PAT/Deploy token에
write_repository/LFS 권한이 부족 - SSO/SAML 환경에서 토큰 스코프 제한
- WAF/Bot Control이 업로드 요청을 차단
WAF가 의심된다면 403이 “진짜 권한”이 아니라 “보안 정책 차단”일 수도 있습니다. (관련해서는 AWS WAF Bot Control 막힘으로 403 지속될 때에서 403이 권한이 아닌 경우를 분해하는 방법을 참고할 수 있습니다.)
3) 재현/진단: LFS가 어디로 무엇을 보내는지 로그로 확인
3.1 LFS 트레이스 켜기
가장 먼저 할 일은 LFS 요청 URL과 응답 코드가 어디서 나는지를 보는 것입니다.
# macOS/Linux
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git lfs push origin main
# 또는 일반 push에서 LFS 포함
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push origin main
여기서 확인할 포인트:
POST .../info/lfs/objects/batch가 200/202로 성공하는지- 실제 업로드 URL이 Git 서버 도메인인지, S3 같은 외부 스토리지인지
- 413/403이 어떤 URL에서 발생하는지
3.2 “Git은 성공, LFS만 실패”인지 확인
가끔 커밋 자체는 올라가고 LFS만 실패합니다. 이 경우 원격에는 포인터 파일만 올라가고 실제 바이너리는 빠져서, 다른 사람이 체크아웃하면 깨집니다.
# LFS 추적 파일 목록
git lfs track
# 현재 브랜치에서 LFS 오브젝트 상태
git lfs status
4) 413 해결: 업로드 크기 제한을 해제/상향
413은 대부분 서버/프록시 설정 문제입니다. 해결은 “클라이언트 버퍼”가 아니라 “요청을 받는 쪽”을 키우는 것입니다.
4.1 Nginx(리버스 프록시)에서 막히는 경우
Nginx 기본/관성 설정으로 client_max_body_size가 낮으면 LFS 업로드가 즉시 413이 납니다.
server {
# LFS 업로드를 고려해 충분히 크게
client_max_body_size 2g;
location / {
proxy_pass http://git-backend;
}
}
- 설정 후
nginx -t로 검증하고 reload - 업로드가 수백 MB~수 GB라면 1g/2g/10g 등 현실적인 상한을 잡습니다.
4.2 Kubernetes Ingress(Nginx Ingress)에서 막히는 경우
Ingress controller가 바디를 제한하는 흔한 케이스입니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: git
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "2g"
nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
spec:
rules:
- host: git.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: git-svc
port:
number: 80
proxy-request-buffering을 끄는 것은 대용량 업로드에서 프록시가 통째로 버퍼링하다 실패하는 상황을 줄이는 데 도움이 됩니다. 프록시/버퍼/타임아웃 이슈는 LFS뿐 아니라 대용량 스트리밍에서도 유사하게 나타나므로, 프록시 튜닝 감각은 LLM SSE 스트리밍 499 502 급증과 응답 끊김을 잡는 프록시 튜닝 체크리스트도 함께 보면 좋습니다.
4.3 GitLab 자체 제한 확인(자체 호스팅)
GitLab은 LFS를 포함해 업로드/아티팩트에 대한 제한이 여러 층에 걸쳐 있습니다.
체크 포인트(환경마다 다름):
- Nginx(내장/외부)
client_max_body_size - GitLab 설정의 최대 업로드 크기(버전/배포 형태에 따라 상이)
- 오브젝트 스토리지(S3/MinIO) 프록시 설정
권장 루트:
- 프록시 413인지(Nginx error log)
- GitLab workhorse/rails 로그에서 제한인지
- 오브젝트 스토리지 업로드 URL에서 413인지
4.4 클라이언트 설정은 보조적이다
git config http.postBuffer는 오래된 HTTP 전송 문제에 대한 우회로 알려져 있지만, LFS 업로드 413의 근본 해결책이 아닌 경우가 많습니다. LFS는 별도 전송을 하며, 서버가 바디를 거부하면 클라이언트 버퍼를 키워도 해결되지 않습니다.
5) 403 해결: “권한”인지 “정책 차단”인지부터 분해
403은 크게 두 갈래입니다.
- (A) 정상적인 권한 부족/인증 실패
- (B) WAF/보안장비/프록시가 차단
5.1 LFS 엔드포인트에서만 403이면 토큰/스코프를 의심
다음 패턴이면 거의 권한 문제입니다.
git push는 성공(커밋은 올라감)git lfs push또는 LFS object 업로드만 403
해결 체크리스트:
- PAT/Deploy Token 스코프
- GitHub:
repo(private 포함) 또는 세분화 권한에서 LFS 관련 권한 확인 - GitLab:
write_repository및 LFS 사용 권한
- GitHub:
- HTTPS 자격 증명 캐시/키체인 꼬임
- 기존 계정 토큰이 캐시돼 다른 권한으로 인증되는 경우
# 현재 저장된 자격증명(환경별로 상이)
git config --global --get credential.helper
# 자격 증명 지우기(예: cache helper)
git credential-cache exit
- SSO/SAML 조직 정책
- “브라우저 로그인은 되는데 토큰은 막힘” 같은 케이스
인증/권한을 체계적으로 점검하는 접근은 API 403에서도 동일합니다. 토큰 스코프, 프로젝트/조직 RBAC, 헤더/호스트 불일치 등을 점검하는 방식은 OpenAI Responses API 401 403 인증오류 점검 가이드와도 결이 같습니다(대상은 다르지만 디버깅 순서가 유사).
5.2 LFS 스토리지가 S3/MinIO로 분리된 경우: 서명 URL/버킷 정책
Git LFS는 종종 “Git 서버 → (배치 API) → S3 서명 URL 발급 → 클라이언트가 S3로 직접 PUT” 구조입니다.
이때 403은:
- 서명 URL 만료(시간 오차/지연)
- 버킷 정책이 PUT을 거부
- 프록시가
PUT메서드를 차단 - 특정 헤더가 제거되어 서명 검증 실패
확인 방법:
GIT_CURL_VERBOSE=1로그에서 실제 업로드 대상 호스트가 S3인지 확인- 동일 URL을
curl -v -X PUT로 재현(가능한 경우)
5.3 WAF/Bot/보안장비가 403을 내는 경우
업로드가 특정 네트워크(사내망/특정 리전)에서만 403이면 WAF 가능성이 큽니다.
- User-Agent/메서드/콘텐츠 타입 기반 차단
- 대용량 업로드를 “비정상 트래픽”으로 분류
- Rate limit 또는 anomaly score 기반 차단
이 경우엔 Git/LFS 설정을 만지기 전에 WAF 로그에서 차단 룰을 확인하고 예외를 추가하는 게 정답입니다. (AWS 환경이라면 위에서 언급한 WAF 403 트러블슈팅 글을 참고)
6) 실전 처방전: 가장 많이 먹히는 조합
6.1 사내 GitLab + Nginx 프록시 조합
- Nginx
client_max_body_size상향 - Ingress/프록시 버퍼링 off(대용량 업로드 시)
- GitLab LFS 활성화 및 프로젝트 LFS 사용 권한 확인
- 토큰 스코프 재발급 후
git remote -v가 올바른 계정/호스트인지 확인
6.2 GitHub 사용 시(대부분 403은 인증)
- HTTPS 원격이면 PAT 재발급(권한 포함)
- Credential helper 캐시 제거 후 재로그인
- 조직 SSO 승인 필요 여부 확인
- LFS quota/정책(조직/플랜) 확인
7) 예방: “큰 파일을 올릴 수 있는 경로”를 설계하자
Git LFS는 만능이지만, 다음을 미리 정하면 장애가 크게 줄어듭니다.
- LFS 최대 파일 크기/레포 쿼터를 문서화
- 프록시/Ingress 바디 제한을 LFS 요구사항에 맞게 기본값으로 상향
- LFS 스토리지를 S3로 분리했다면 버킷 정책과 서명 URL 만료 시간을 표준화
- CI에서
git lfs fetch && git lfs checkout단계에 실패 감지 추가
8) 체크리스트 요약
413
- 어디서 413인지 먼저 본다(LFS 업로드 URL)
- Nginx/Ingress
client_max_body_size/proxy-body-size상향 - 프록시 버퍼링/요청 버퍼링 비활성화 고려
403
- Git은 되는데 LFS만 403이면 토큰/스코프/RBAC부터
- S3/MinIO 서명 URL 구조면 버킷 정책/PUT 허용/헤더 보존 확인
- 네트워크/리전별로만 실패하면 WAF/보안장비 차단 로그 확인
필요하면, 현재 환경(예: GitHub/GitLab/Bitbucket, 프록시 Nginx/Ingress/Cloudflare, LFS 스토리지 S3/로컬)과 GIT_CURL_VERBOSE=1에서 403/413이 발생한 정확한 URL 한 줄만 알려주면, 원인 후보를 2~3개로 더 좁혀서 설정 값을 구체적으로 제안할 수 있습니다.