CrowdSec: Community-Powered Security for Your Infrastructure
CrowdSec takes a fundamentally different approach to intrusion prevention compared to tools like Fail2Ban. While Fail2Ban operates in isolation, analyzing logs on a single server, CrowdSec adds a collaborative intelligence layer. When one CrowdSec agent detects an attack, the offending IP can be shared with the entire community, allowing every participant to preemptively block known attackers before they even reach your infrastructure.
Think of it as a crowd-sourced threat intelligence network combined with a local intrusion detection system. The architecture separates detection (the Security Engine) from enforcement (Bouncers), allowing flexible deployment across heterogeneous infrastructure.
CrowdSec vs Fail2Ban
| Feature | CrowdSec | Fail2Ban |
|---|---|---|
| Architecture | Separate engine + bouncers | Monolithic daemon |
| Threat intelligence | Community-shared blocklists | Local-only detection |
| Language | Go (single binary) | Python |
| Log parsing | YAML-based parsers + expr | Regex-based filters |
| Decision types | Ban, captcha, throttle | Ban only |
| Console/dashboard | Web-based console (free) | CLI only |
| API | Full REST API (LAPI) | Unix socket CLI |
| Docker support | First-class, native images | Manual configuration |
| Performance | High (compiled Go) | Moderate (Python) |
When to choose CrowdSec over Fail2Ban: CrowdSec is the better choice when you run multiple servers, need community threat intelligence, want flexible response actions beyond simple banning, or prefer a modern API-driven architecture. Fail2Ban is simpler for single-server setups where you just need basic SSH protection.
Architecture Overview
CrowdSec has three main components:
- Security Engine (crowdsec): Parses logs, evaluates scenarios, and creates decisions (ban/captcha/throttle). Runs the Local API (LAPI).
- Bouncers: Enforce decisions at the network edge. Multiple bouncer types exist: firewall (iptables/nftables), Nginx, Traefik, Cloudflare, and more.
- Central API (CAPI): The community hub. Your engine shares attack signals and receives curated community blocklists in return.
Installation
Native Installation
# Add CrowdSec repository (Debian/Ubuntu)
curl -s https://install.crowdsec.net | sudo sh
sudo apt install crowdsec
# RHEL/CentOS/Fedora
curl -s https://install.crowdsec.net | sudo sh
sudo dnf install crowdsec
# Check status
sudo cscli version
sudo cscli metrics
Docker Deployment
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
restart: unless-stopped
environment:
COLLECTIONS: "crowdsecurity/linux crowdsecurity/nginx crowdsecurity/sshd"
GID: "${GID:-1000}"
volumes:
# CrowdSec configuration and data
- crowdsec_config:/etc/crowdsec
- crowdsec_data:/var/lib/crowdsec/data
# Log sources to analyze
- /var/log/auth.log:/var/log/auth.log:ro
- /var/log/syslog:/var/log/syslog:ro
- nginx_logs:/var/log/nginx:ro
networks:
- crowdsec_net
# Firewall bouncer (runs on host network)
bouncer-firewall:
image: crowdsecurity/crowdsec-firewall-bouncer-nftables:latest
container_name: crowdsec-firewall-bouncer
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
- NET_RAW
environment:
CROWDSEC_BOUNCER_API_KEY: "${BOUNCER_API_KEY}"
CROWDSEC_URL: "http://crowdsec:8080"
depends_on:
- crowdsec
volumes:
crowdsec_config:
crowdsec_data:
nginx_logs:
networks:
crowdsec_net:
Collections, Parsers, and Scenarios
CrowdSec uses a hub system for distributing detection configurations:
# Browse available collections
sudo cscli collections list -a
# Install collections
sudo cscli collections install crowdsecurity/nginx
sudo cscli collections install crowdsecurity/sshd
sudo cscli collections install crowdsecurity/linux
sudo cscli collections install crowdsecurity/http-cve
# A collection bundles parsers + scenarios:
sudo cscli collections inspect crowdsecurity/nginx
# Parsers:
# - crowdsecurity/nginx-logs
# - crowdsecurity/http-logs
# Scenarios:
# - crowdsecurity/http-crawl-non_statics
# - crowdsecurity/http-path-traversal-probing
# - crowdsecurity/http-sqli-probing
# - crowdsecurity/http-xss-probing
# List installed scenarios
sudo cscli scenarios list
# List installed parsers
sudo cscli parsers list
Configuring Log Sources
# /etc/crowdsec/acquis.yaml (or acquis.d/*.yaml)
# SSH logs
---
filenames:
- /var/log/auth.log
labels:
type: syslog
# Nginx access logs
---
filenames:
- /var/log/nginx/access.log
labels:
type: nginx
# Nginx error logs
---
filenames:
- /var/log/nginx/error.log
labels:
type: nginx
# Docker container logs via journalctl
---
source: journalctl
journalctl_filter:
- "_SYSTEMD_UNIT=docker.service"
labels:
type: syslog
# Read from Docker container logs directly
---
source: docker
container_name:
- nginx-proxy
- traefik
labels:
type: nginx
Bouncers: Enforcement Layer
Firewall Bouncer
# Install the firewall bouncer
sudo apt install crowdsec-firewall-bouncer-nftables
# Generate an API key for the bouncer
sudo cscli bouncers add firewall-bouncer
# API key: a1b2c3d4e5f6...
# Configure the bouncer
# /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
api_url: http://127.0.0.1:8080/
api_key: a1b2c3d4e5f6...
mode: nftables
update_frequency: 10s
deny_action: DROP
deny_log: true
deny_log_prefix: "crowdsec: "
# Start the bouncer
sudo systemctl enable --now crowdsec-firewall-bouncer
# Verify nftables rules
sudo nft list ruleset | grep crowdsec
Nginx Bouncer
# Install the Nginx bouncer (OpenResty/Lua)
sudo apt install crowdsec-openresty-bouncer
# Or for the Nginx module approach:
sudo cscli bouncers add nginx-bouncer
# /etc/crowdsec/bouncers/crowdsec-openresty-bouncer.conf
API_URL=http://127.0.0.1:8080
API_KEY=your_bouncer_api_key
# Show captcha instead of blocking
BOUNCING_ON_TYPE=all
FALLBACK_REMEDIATION=captcha
BAN_TEMPLATE_PATH=/var/lib/crowdsec/lua/templates/ban.html
CAPTCHA_TEMPLATE_PATH=/var/lib/crowdsec/lua/templates/captcha.html
Traefik Bouncer
services:
traefik:
image: traefik:v3.0
command:
- "--experimental.plugins.crowdsec-bouncer-traefik-plugin.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin"
- "--experimental.plugins.crowdsec-bouncer-traefik-plugin.version=v1.3.0"
labels:
- "traefik.http.middlewares.crowdsec.plugin.crowdsec-bouncer-traefik-plugin.crowdseclapikey=${BOUNCER_API_KEY}"
- "traefik.http.middlewares.crowdsec.plugin.crowdsec-bouncer-traefik-plugin.crowdseclapischeme=http"
- "traefik.http.middlewares.crowdsec.plugin.crowdsec-bouncer-traefik-plugin.crowdseclapihost=crowdsec:8080"
# Apply the middleware to your services
webapp:
labels:
- "traefik.http.routers.webapp.middlewares=crowdsec@docker"
Decisions and Alerts
# View current decisions (active bans)
sudo cscli decisions list
# View alerts (detected attacks)
sudo cscli alerts list
# Inspect a specific alert
sudo cscli alerts inspect 42
# Manually add a decision
sudo cscli decisions add --ip 203.0.113.50 --duration 24h --reason "manual ban"
# Remove a decision
sudo cscli decisions delete --ip 203.0.113.50
# Add a range ban
sudo cscli decisions add --range 203.0.113.0/24 --duration 168h --reason "hostile network"
Community Blocklists
One of CrowdSec's key advantages is community-shared threat intelligence. When you install CrowdSec and register with the console, you automatically receive curated blocklists:
# Enroll with the CrowdSec console
sudo cscli console enroll YOUR_ENROLLMENT_KEY
# View community blocklist status
sudo cscli console status
# The console provides:
# - IP reputation data from the community
# - Curated blocklists for known bad actors
# - Visualization of attacks on your infrastructure
# - Alert management and analytics
Custom Scenarios
Create scenarios for application-specific attack detection:
# /etc/crowdsec/scenarios/my-app-bruteforce.yaml
type: leaky
name: my-company/my-app-bruteforce
description: "Detect brute force on my custom application"
filter: "evt.Meta.log_type == 'myapp' && evt.Meta.http_status == '401'"
groupby: "evt.Meta.source_ip"
capacity: 5
leakspeed: "10s"
blackhole: 5m
labels:
remediation: true
type: bruteforce
service: myapp
# Custom parser for your application logs
# /etc/crowdsec/parsers/s02-enrich/my-app-parser.yaml
name: my-company/my-app-parser
description: "Parse my custom application logs"
filter: "evt.Parsed.program == 'myapp'"
onsuccess: next_stage
statics:
- meta: log_type
value: myapp
nodes:
- grok:
pattern: '%{IPORHOST:source_ip} - \[%{HTTPDATE:timestamp}\] "%{WORD:method} %{URIPATHPARAM:uri} HTTP/%{NUMBER}" %{NUMBER:http_status}'
apply_on: message
statics:
- meta: http_status
expression: evt.Parsed.http_status
- meta: source_ip
expression: evt.Parsed.source_ip
The CrowdSec API (LAPI)
# The Local API provides programmatic access to decisions
# Get current decisions
curl -s http://127.0.0.1:8080/v1/decisions \
-H "X-Api-Key: ${API_KEY}" | jq .
# Add a decision via API
curl -s -X POST http://127.0.0.1:8080/v1/decisions \
-H "X-Api-Key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '[{
"duration": "24h",
"origin": "manual",
"scenario": "manual/ban",
"scope": "Ip",
"type": "ban",
"value": "203.0.113.50"
}]'
# Query if an IP has a decision
curl -s "http://127.0.0.1:8080/v1/decisions?ip=203.0.113.50" \
-H "X-Api-Key: ${API_KEY}" | jq .
Monitoring and Metrics
# Built-in metrics
sudo cscli metrics
# Output shows:
# - Parsed lines per source
# - Overflow (scenario triggers) per scenario
# - Active decisions by type
# - Bouncer requests
# Prometheus metrics endpoint
# /etc/crowdsec/config.yaml
prometheus:
enabled: true
level: full
listen_addr: 127.0.0.1
listen_port: 6060
# Scrape with Prometheus
# prometheus.yml
scrape_configs:
- job_name: crowdsec
static_configs:
- targets: ['localhost:6060']
CrowdSec represents a significant evolution in host-based intrusion detection. The combination of local behavior analysis with community threat intelligence provides protection that no single-server solution can match. For self-hosted infrastructure running Docker workloads, deploying CrowdSec alongside your reverse proxy gives you both reactive detection and proactive blocking of known malicious actors.