Upload kernel deb straight to origin, bypassing Cloudflare's 100MB cap

The Actions runner is overseas, so git.chilldove.com resolves to Cloudflare anycast. Cloudflare free/pro rejects request bodies over 100MB with HTTP 413 at the edge, and the linux-image .deb exceeds 100MB, so every publish failed. The Gitea origin itself accepts the upload (verified to >=110MB); only the CDN edge rejects it.

Pin the publish curl to the registry origin via curl --resolve, sourced from the new PKG_ORIGIN_IP repo variable (no IP baked into git; SNI/Host stay git.chilldove.com so TLS and package routing are unchanged). Document the prerequisite in README and the migration spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-06-18 00:56:50 +08:00
parent c85b44c65a
commit 54afeb6762
3 changed files with 30 additions and 2 deletions
+24 -1
View File
@@ -18,6 +18,14 @@ env:
# https://git.chilldove.com/api/packages/icePigeon/debian # https://git.chilldove.com/api/packages/icePigeon/debian
PKG_REGISTRY: ${{ github.server_url }}/api/packages/${{ github.repository_owner }}/debian PKG_REGISTRY: ${{ github.server_url }}/api/packages/${{ github.repository_owner }}/debian
PKG_USER: ${{ github.repository_owner }} PKG_USER: ${{ github.repository_owner }}
# Optional origin pin for uploads. The kernel image .deb is >100 MB, which trips
# the request-body cap of a CDN/proxy fronting the registry (Cloudflare free/pro
# caps at 100 MB and returns 413 at the edge, before the body reaches Gitea — the
# origin itself accepts it). Set the Gitea repo/org variable PKG_ORIGIN_IP to the
# registry origin's address (the host behind the CDN) and the publish step pins the
# upload straight there via curl --resolve, bypassing the CDN. vars (unlike secrets)
# ARE available to workflow-level env. Leave empty if no CDN fronts uploads.
PKG_ORIGIN_IP: ${{ vars.PKG_ORIGIN_IP }}
# NOTE: PKG_TOKEN (the write:package secret) is declared at JOB level below. The # NOTE: PKG_TOKEN (the write:package secret) is declared at JOB level below. The
# secrets context is not available to workflow-level env, so a value set here # secrets context is not available to workflow-level env, so a value set here
# would silently be empty. # would silently be empty.
@@ -283,10 +291,25 @@ jobs:
exit 1 exit 1
fi fi
# The kernel image .deb is >100 MB, which trips the request-body cap of a
# CDN/proxy in front of the registry (Cloudflare free/pro = 100 MB) and 413s
# at the edge before the body reaches Gitea — the origin itself accepts it.
# If PKG_ORIGIN_IP is set, pin the upload straight to that origin so the
# oversized PUT never touches the CDN. SNI/Host stay $reg_host, so TLS and
# package routing are unchanged; only the TCP connect target moves.
reg_host=${PKG_REGISTRY#*://}; reg_host=${reg_host%%/*}
resolve=()
if [ -n "${PKG_ORIGIN_IP:-}" ]; then
resolve=(--resolve "${reg_host}:443:${PKG_ORIGIN_IP}")
echo "Uploading direct to origin ${PKG_ORIGIN_IP}, bypassing any CDN in front of ${reg_host}."
else
echo "PKG_ORIGIN_IP unset: uploading via DNS for ${reg_host}; if a CDN fronts it (e.g. Cloudflare, 100 MB cap) the kernel image will 413. Set the PKG_ORIGIN_IP variable to fix." >&2
fi
# Gitea returns 201/202 on upload, 409 when the file already exists. # Gitea returns 201/202 on upload, 409 when the file already exists.
upload() { upload() {
local f="$1" code local f="$1" code
code=$(curl -sS -o /dev/null -w '%{http_code}' \ code=$(curl -sS -o /dev/null -w '%{http_code}' "${resolve[@]}" \
--user "$PKG_USER:$PKG_TOKEN" --upload-file "$f" \ --user "$PKG_USER:$PKG_TOKEN" --upload-file "$f" \
"$PKG_REGISTRY/pool/stable/main/upload" || echo 000) "$PKG_REGISTRY/pool/stable/main/upload" || echo 000)
case "$code" in case "$code" in
+1 -1
View File
@@ -170,7 +170,7 @@ modinfo tcp_bbr 2>/dev/null | grep '^version:'
构建不会自动更新 BBR patch 本身。 构建不会自动更新 BBR patch 本身。
发布所需:CI 配置一个有 `write:package` 权限的 `PKG_TOKEN` secretGitea 实例需启用 Packages → Debian registry。 发布所需:CI 配置一个有 `write:package` 权限的 `PKG_TOKEN` secretGitea 实例需启用 Packages → Debian registry。若 registry 前面有 CDN/反代对上传请求体设限(如 Cloudflare 免费/Pro 版 100 MB 上限),内核镜像 `.deb`>100 MB)会在边缘被 413 拒绝——把 Gitea 源站地址(CDN 背后主机的 IP)配成 Gitea 仓库变量 `PKG_ORIGIN_IP`,发布步骤会用 `curl --resolve` 把上传直连源站、绕过 CDN(SNI/Host 不变,证书与包路由不受影响)。源站本身不受此限。
## 免责声明 ## 免责声明
@@ -58,6 +58,11 @@
- CI 需 `PKG_TOKEN` secret(有 `write:package` scope);自动注入的 `GITHUB_TOKEN` 不保证有 - CI 需 `PKG_TOKEN` secret(有 `write:package` scope);自动注入的 `GITHUB_TOKEN` 不保证有
包写权限。 包写权限。
- registry 保留历史版本以支撑「装指定版本」;将来再议 retention。 - registry 保留历史版本以支撑「装指定版本」;将来再议 retention。
- **上传路径不能经过有 body 上限的 CDN**(落地后实测补记):`git.chilldove.com` 对境外
runner 走 Cloudflareorange-cloud),CF 免费/Pro 版 100 MB 请求体上限会把 >100 MB 的内核
镜像 `.deb` 在边缘 413(源站 Baguette 实测可收 ≥110 MB)。CI 须配 Gitea 仓库变量
`PKG_ORIGIN_IP`,发布步骤用 `curl --resolve` 直连源站绕过 CF。详见
[[工程实践/案例/2026-06-17 Gitea Debian registry 上传被 Cloudflare 100MB body 上限 413]]。
## 不做(YAGNI ## 不做(YAGNI