1. Nginx and OpenResty #
A Lua bouncer.
Install #
The Nginx bouncer relies on the Lua module. On Ubuntu 22.xx, this module may be missing: move to a newer version or use OpenResty, which includes it.
sudo apt install nginx lua5.1 libnginx-mod-http-lua luarocks gettext-base lua-cjson
sudo apt install crowdsec-nginx-bouncer
sudo nginx -t && sudo systemctl reload nginxConfigure #
The /etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf file can be overridden with a .conf.local file.
API_URL=http://127.0.0.1:8080
API_KEY=YOUR_KEY
MODE=stream
UPDATE_FREQUENCY=10
BOUNCING_ON_TYPE=all
FALLBACK_REMEDIATION=ban
RET_CODE=403
APPSEC_URL=http://127.0.0.1:7422| Option | Role |
|---|---|
MODE | live by default, or stream |
BOUNCING_ON_TYPE | all, ban, captcha |
FALLBACK_REMEDIATION | Remediation if the received type is unknown |
BAN_TEMPLATE_PATH | HTML page shown to banned IPs |
REDIRECT_LOCATION | Redirects instead of showing the page |
APPSEC_URL | Enables the WAF |
Captcha #
Captcha gives a legitimate user a chance, for example behind a shared IP. Three providers: recaptcha, hcaptcha, turnstile. Nginx must be able to reach them: configure resolver and lua_ssl_trusted_certificate.
CAPTCHA_PROVIDER=turnstile
SITE_KEY=YOUR_SITE_KEY
SECRET_KEY=YOUR_SECRET_KEY
CAPTCHA_EXPIRATION=3600sudo cscli decisions add --ip 192.0.2.6 --duration 1h --type captchaApache #
An Apache bouncer also exists, with WAF, virtual patching and bot detection through AppSec. Its logic is identical: API key, LAPI URL, then server reload. See the dedicated documentation.
2. HAProxy with SPOA #
Offloading the check outside HAProxy.
The principle #
Old bouncer deprecated. The old Lua HAProxy bouncer, still cited by many tutorials, is deprecated. Use the SPOA bouncer, the only one supporting AppSec.
Install and configure #
sudo apt install crowdsec-haproxy-spoa-bouncer
sudo cscli bouncers add haproxy-spoa
sudo cp /usr/share/doc/crowdsec-haproxy-spoa-bouncer/examples/crowdsec.cfg /etc/haproxy/crowdsec.cfgIn /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml, set api_url, api_key and listen_tcp: 127.0.0.1:9000. Then, in haproxy.cfg:
frontend http-in
bind *:80
option http-buffer-request
unique-id-format %[uuid()]
unique-id-header X-Unique-ID
filter spoe engine crowdsec config /etc/haproxy/crowdsec.cfg
acl body_within_limit req.body_size -m int le 51200
http-request send-spoe-group crowdsec crowdsec-http-body if body_within_limit || !{ req.body_size -m found }
http-request send-spoe-group crowdsec crowdsec-http-no-body if !body_within_limit { req.body_size -m found }
# Ban and captcha pages are in examples/haproxy.cfg
default_backend app
backend crowdsec-spoa
mode tcp
timeout connect 2s
timeout server 60s
server spoa 127.0.0.1:9000sudo crowdsec-spoa-bouncer -c /etc/crowdsec/bouncers/crowdsec-spoa-bouncer.yaml -t
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl restart crowdsec-spoa-bouncer haproxyTwo traps #
- Real IP. Behind a CDN, use
set-srcbefore thesend-spoe-grouplines, and only allow the trusted proxy on your ports. - 50 KB limit. A request body beyond this size is not inspected by the WAF. An attacker can use this to bypass it: reject these requests, except on your upload paths.
Sources #
Configurations from the official documentation consulted in November 2026: these bouncers were not run for this article.
My progress
Sign in to track your progress and take notes. Sign in
Recommended Articles
CrowdSec bouncers: principles and firewall bouncer
Understanding CrowdSec bouncers: where to block, live and stream modes, API keys, decisions API, ...
CrowdSec bouncers: Cloudflare, network devices, Kubernetes and custom bouncer
Block at the CDN with Cloudflare Workers, feed pfSense or MikroTik with Blocklist Mirror, protect...
Decisions, profiles, allowlists and AppSec in CrowdSec
Manage decisions with cscli, adapt block duration and type with profiles, avoid false positives w...
Protecting Traefik with CrowdSec: the bouncer plugin
Setting up the CrowdSec bouncer in Traefik: plugin, middleware, stream and live modes, real IP be...
CrowdSec: understanding the collaborative firewall
What CrowdSec is, how it detects and blocks attacks: Security Engine, parsers, scenarios, Local A...
CrowdSec observability: banned IPs, blocked attacks, Prometheus and Grafana
Monitoring CrowdSec: cscli metrics, banned IPs, detected attacks, volume blocked by bouncers, Pro...
Gestion des certificats SSL/TLS avec Let's Encrypt et ACME
Apprenez à automatiser la génération et le renouvellement de vos certificats SSL/TLS avec Let's E...
Protocole ACME : serveur ACME, challenges http-01 et dns-01, automatisation TLS
Comprendre le protocole ACME : rôle du serveur ACME (Let's Encrypt, ZeroSSL, step-ca), challenges...
HAProxy dans Kubernetes : L'Ingress Controller Haute Performance
Découvrez en profondeur l'intégration de HAProxy dans Kubernetes. Architecture Direct-to-Pod, opt...