traefik: add CrowdSec bouncer plugin + global fail-open middleware #77

Merged
k.renner merged 1 commits from traefik-crowdsec-bouncer into master 2026-06-27 11:06:15 +00:00
3 changed files with 53 additions and 0 deletions
@@ -0,0 +1,37 @@
# CrowdSec bouncer middleware, attached globally to the websecure
# entrypoint (see helmrelease.yaml ports.websecure.middlewares). The
# plugin queries the CrowdSec LAPI and rejects requests from IPs with an
# active ban decision.
#
# Fail-OPEN by design: Traefik is the only ingress controller, so a
# CrowdSec/LAPI outage must never take down every app. updateMaxFailure=-1
# means "never block when the LAPI is unreachable", and
# streamStartupBlock=false lets traffic flow during the initial decision
# sync. The security tradeoff (a LAPI outage briefly lets banned IPs
# through) is the right one for the sole ingress path; tighten later if
# wanted.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: crowdsec-bouncer
namespace: ingress
spec:
plugin:
bouncer:
enabled: true
logLevel: INFO
# stream mode keeps only the banned-IP list in local cache and syncs
# it from the LAPI periodically — minimal per-request latency.
crowdsecMode: stream
updateIntervalSeconds: 60
updateMaxFailure: -1
streamStartupBlock: false
defaultDecisionSeconds: 60
httpTimeoutSeconds: 10
crowdsecLapiScheme: http
crowdsecLapiHost: crowdsec-service.crowdsec.svc.cluster.local:8080
# Static pre-shared bouncer key, pre-registered with the LAPI via the
# crowdsec HelmRelease env BOUNCER_KEY_ingress. Same value as the
# crowdsec-bouncer-key Secret (already committed in plaintext as a
# low-sensitivity internal token).
crowdsecLapiKey: "k8s-homelab-ingress-bouncer-key-v1"
@@ -44,6 +44,15 @@ spec:
values:
deployment:
replicas: 2
# CrowdSec bouncer plugin (Yaegi). Traefik downloads the module source
# from GitHub at pod startup — the `ingress` namespace has no egress
# restriction so this succeeds, but if GitHub is unreachable at boot
# Traefik will not start. Pinned to a known-good release.
experimental:
plugins:
bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: v1.6.0
ingressClass:
enabled: true
isDefaultClass: false
@@ -74,6 +83,12 @@ spec:
scheme: https
permanent: true
websecure:
# Apply the CrowdSec bouncer to every router on this entrypoint —
# global enforcement, like the old ingress-nginx Lua bouncer. The
# Middleware itself is fail-open (see crowdsec-middleware.yaml), so
# a CrowdSec/LAPI outage never black-holes ingress.
middlewares:
- ingress-crowdsec-bouncer@kubernetescrd
# HTTP/3 is the headline reason for this migration — ingress-nginx
# cannot serve QUIC on UDP/443, so LAN clients that learned the
# `alpn=h3` hint (DNS HTTPS RR / Alt-Svc) over Cloudflare get
@@ -2,3 +2,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- helmrelease.yaml
- crowdsec-middleware.yaml