crowdsec/traefik: stop captchaing legit Immich mobile bursts

Mobile timeline scrubs prefetch ~100 thumbs in <1s, which exhausted the
immich-rate-limit (avg=500, burst=5000) and produced a cascade of HTTP
429s. CrowdSec's local http-429-abuse scenario then fired captcha:1 on
the source IP (alert #291, 2026-04-25 — owner's Hyperoptic IPv6).

Two changes:
- crowdsec: add a second whitelist doc (viktor/immich-asset-paths-whitelist)
  filtering events by Immich asset paths so they never feed leaky buckets.
  Auth endpoints intentionally excluded — brute-force protection unchanged.
- traefik: raise immich-rate-limit avg=500->1000, burst=5000->20000 so
  legitimate mobile scrubs don't produce 429s in the first place.
This commit is contained in:
Viktor Barzin 2026-04-26 09:27:16 +00:00
parent 222013806d
commit d0152e1f38
2 changed files with 17 additions and 2 deletions

View file

@ -96,6 +96,21 @@ resource "kubernetes_config_map" "crowdsec_whitelist" {
reason: "Trusted IP - never block"
ip:
- "176.12.22.76"
---
name: viktor/immich-asset-paths-whitelist
description: "Don't penalise legit Immich timeline bursts (mobile scrub, web grid)"
whitelist:
reason: "Immich asset endpoints are auth-gated; mobile scrub legitimately bursts"
expression:
- >
evt.Parsed.target_fqdn == "immich.viktorbarzin.me" &&
(evt.Parsed.request startsWith "/api/assets/" ||
evt.Parsed.request startsWith "/api/timeline/" ||
evt.Parsed.request startsWith "/api/asset/" ||
evt.Parsed.request startsWith "/api/search/" ||
evt.Parsed.request startsWith "/api/memories" ||
evt.Parsed.request startsWith "/api/albums" ||
evt.Parsed.request startsWith "/api/activities")
YAML
}
}

View file

@ -244,8 +244,8 @@ resource "kubernetes_manifest" "middleware_immich_rate_limit" {
}
spec = {
rateLimit = {
average = 500
burst = 5000
average = 1000
burst = 20000
}
}
}