CrowdSec
Canasta includes an optional CrowdSec security profile that watches the Caddy access log, detects malicious traffic (scanners, brute-force, known CVE probes), and blocks offending IP addresses at the edge before requests reach MediaWiki. It is off by default and, when enabled, leaves existing behavior unchanged until a bouncer is enrolled.
CrowdSec is a Docker Compose feature. Kubernetes support is tracked separately and is not yet available.
How it works
Enabling CrowdSec adds two pieces:
- A CrowdSec engine container that tails Caddy's access log, runs it through the
crowdsecurity/caddyandcrowdsecurity/http-cvedetection scenarios, and publishes IP decisions (bans). - A bouncer built into Caddy (the
ghcr.io/canastawiki/canasta-caddyimage, swapped in automatically) that pulls those decisions and returns403 Forbiddento banned clients.
Detection acts on the real client IP. When Caddy is the edge it already sees the real client; when it sits behind a CDN or WAF you must tell it which proxy to trust (see below), or both detection and blocking would act on the proxy's IP.
Enabling CrowdSec
Enabling CrowdSec is two steps: turn on the profile, then enroll the bouncer. Enforcement does not begin until the bouncer is enrolled.
New instances
Create an .env file with CrowdSec enabled, then pass it to canasta create:
echo "CANASTA_ENABLE_CROWDSEC=true" > my.env
canasta create -i myinstance -w mywiki -e my.env
Existing instances
canasta config set CANASTA_ENABLE_CROWDSEC=true
This saves the setting and restarts the instance with the CrowdSec engine running. In both cases the CLI automatically:
- Switches the Caddy image to the bouncer-enabled
ghcr.io/canastawiki/canasta-caddybuild (feature-off instances stay on stock Caddy) - Adds
crowdsectoCOMPOSE_PROFILES - Renders the bouncer directive into the Caddyfile (only once a bouncer key is present, so an un-enrolled instance still boots cleanly)
- Materializes
config/crowdsec/acquis.yamlandconfig/crowdsec/whitelists.yamlin the instance directory
- Note: enabling CrowdSec without enrolling a bouncer is a safe, do-nothing state — Caddy starts normally but enforces no decisions. Run
canasta crowdsec enrollto begin enforcing.
Enrolling the bouncer
Run this once after enabling CrowdSec:
canasta crowdsec enroll
This registers the Caddy bouncer with the engine, stores the generated API key as CROWDSEC_BOUNCER_API_KEY, and restarts so the bouncer begins enforcing. It is idempotent — if a bouncer is already enrolled and a key is stored, it reports success and does nothing. Use --force to revoke the existing bouncer and issue a fresh key:
canasta crowdsec enroll --force
Managing decisions
Viewing status
Show the registered bouncers and the IP decisions currently in effect (read-only):
canasta crowdsec status
Banning and unbanning manually
Add a manual decision independent of automatic detection. A ban defaults to four hours; --duration and --reason are optional:
canasta crowdsec ban 203.0.113.50
canasta crowdsec ban 203.0.113.50 --duration 24h --reason scraper
Remove decisions for an IP (lifting a manual ban or one added by automatic detection):
canasta crowdsec unban 203.0.113.50
- Note: the bouncer pulls decisions on a short interval, so a newly added or removed ban takes effect within roughly 15 seconds rather than instantly.
Whitelisting trusted IPs
To stop CrowdSec from ever acting on traffic you trust (office IPs, monitoring, an upstream proxy), edit config/crowdsec/whitelists.yaml in the instance directory. It is a normal, version-controlled file — the same kind of durable, editable config as Caddyfile.global. Changes take effect on the next restart.
Recovering the real client IP behind a CDN or WAF
CrowdSec can only ban the right address if Caddy reports the real client IP. When Caddy is the edge this is automatic. When it sits behind a CDN or WAF, set CADDY_TRUSTED_PROXIES so Caddy reads the forwarded client IP — but only from the proxy you actually use:
canasta config set CADDY_TRUSTED_PROXIES=cloudflare
| Value | Behavior |
|---|---|
cloudflare |
Reads CF-Connecting-IP and trusts it only from Cloudflare's published edge ranges (refreshed in-process; no maintenance required).
|
imperva |
Reads Incap-Client-IP and trusts it only from Imperva's published ranges.
|
| comma-separated CIDRs | Trusts X-Forwarded-For from an explicit list of proxy networks (e.g. 10.0.0.0/8,192.168.0.0/16); runs on stock Caddy.
|
Locking trust to the provider's ranges is the safety property: if Caddy trusted the forwarded header from any source, a client connecting directly to the origin could forge its IP and dodge bans. A typo in the value is rejected when you run canasta config set.
Disabling CrowdSec
canasta config set CANASTA_ENABLE_CROWDSEC=false
This stops the CrowdSec engine, removes the bouncer directive from the Caddyfile, drops crowdsec from the active profile, and (if no other plugin feature needs it) returns Caddy to the stock image.
Resource requirements
CrowdSec adds one lightweight container (the engine) plus the bouncer that runs inside the existing Caddy container. It is far less resource-hungry than the Java-based observability or Elasticsearch stacks. See System requirements for overall sizing.
GitOps
On a GitOps-managed instance, the CrowdSec enable flag, the bouncer key, and CADDY_TRUSTED_PROXIES are stored as part of the instance's version-controlled configuration, so enabling CrowdSec survives a config regeneration or a git pull. The config/crowdsec/whitelists.yaml file is version-controlled with the rest of the instance config.
See also
- Help:Networking and TLS — how Caddy fronts the instance
- Help:Observability — searchable logs, including the Caddy access log CrowdSec reads
- Help:Troubleshooting — common errors and fixes