fix(fail2ban): exclude /api/actions runner-protocol 401s from caddy-auth #195
Inga granskare
Etiketter
Inga etiketter
area/backups
area/ci
area/control-panel
area/identity
area/infra
area/observability
area/payments
area/security
area/storage
area/web
blocked
needs-info
needs-triage
ready-for-implementation
type
bug
type
chore
type
docs
type
epic
type
feature
type
task
wontfix
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Inget förfallodatum satt.
Beroenden
Inga beroenden satta
Referens
bitborg/bitborg-infra!195
Läser in…
Hänvisa till i nytt ärende
Ingen beskrivning angiven.
Ta bort grenen "fix/caddy-auth-ignore-actions-401"
Borttagning av en gren är permanent. Även om den borttagna grenen kan fortsätta existera en kort tid innan den faktiskt tas bort, kan det INTE ångras i de flesta fall. Vill du fortsätta?
Root cause (Action run 133 stuck 'waiting' for hours)
The Forgejo Actions runner gRPC protocol (
/api/actions/runner.v1.RunnerService/*, e.g.UpdateTask/UpdateLog) answers 401 by protocol during the ephemeral runner's token/handshake lifecycle — not because a credential is wrong.Our ephemeral runners share one SNAT egress IP (no floating IP), so those 401s pile up fast. The
caddy-authfail2ban jail counted them and banned the shared egress IP at nftables. Every subsequent runner was then dropped before it could declare itself — its registration row stayedagent_labels = null,last_online = epoch(never online) — so queued jobs (runs_on: [ci]) never matched a runner, the job satwaiting, and the runner-controller boot-looped (boot → can't declare →one-jobexits →poweroff→ reap → repeat), each cycle refreshing the ban.This is the same class as the
/v2/registry-handshake regression (#127/#175, fixed in #179) — one endpoint further along.Fix
Extend the
caddy-authignoreregexalternation to also exclude/api/actions/401s.Verification (fail2ban-regex against the live access log)
/v2/only)UpdateTask/UpdateLog(= maxretry → ban)+/api/actions/)Real credential brute force (
/user/login,/api/v1tokens, git-HTTPS Basic auth) still hitsfailregexand is jailed.Applied to prod + unbanned the egress IP: runner declared
[ci]+ came online within seconds, run 133 movedwaiting → running, queue drained to 0.Follow-up
Filing a separate issue for the systemic fix: flip the filter from a deny-list (ban all 401s minus a growing exclusion list) to an allow-list of genuine credential endpoints, so the next protocol-401 endpoint can't re-break CI. Plus verify the
RunnerQueueStalledalert fires (this ran silently).