CrowdSec

From Canasta Wiki

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/caddy and crowdsecurity/http-cve detection scenarios, and publishes IP decisions (bans).
  • A bouncer built into Caddy (the ghcr.io/canastawiki/canasta-caddy image, swapped in automatically) that pulls those decisions and returns 403 Forbidden to 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-caddy build (feature-off instances stay on stock Caddy)
  • Adds crowdsec to COMPOSE_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.yaml and config/crowdsec/whitelists.yaml in 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 enroll to 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