How to Self-Host CrowdSec: Collaborative Intrusion Prevention 2026
·OSSAlt Team
crowdsecsecurityidsipsself-hostingdockerfail2ban2026
TL;DR
CrowdSec (MIT, ~10K GitHub stars, Go) is a collaborative intrusion detection and prevention system. Like fail2ban, it detects attacks by reading logs — but then shares threat intelligence with the entire CrowdSec network, so everyone benefits. It automatically blocks known bad IPs using community-contributed blocklists. Cloudflare WAF costs $20/month for basic protection. CrowdSec gives you crowd-sourced threat intelligence for free.
Key Takeaways
- CrowdSec: MIT, ~10K stars, Go — modern collaborative IDS/IPS
- Crowd-sourced blocklists: Block IPs that are attacking other CrowdSec users worldwide
- Bouncers: Enforcement components for Caddy, Nginx, iptables, Cloudflare, and more
- Scenarios: Detect brute force, credential stuffing, port scanning, L7 DDoS
- Console: Free web dashboard at app.crowdsec.net for monitoring
- vs fail2ban: CrowdSec adds shared threat intelligence and a richer scenario system
How CrowdSec Works
Logs (Nginx, SSH, etc.) → CrowdSec Agent → Decisions (ban, captcha)
↑ ↓ ↓
CrowdSec API Bouncers (enforce)
↑ ↓
Community Intel
(crowd-sourced blocklists)
- Agent reads logs and detects attack patterns (scenarios)
- Decisions are created: ban IP, show captcha, throttle
- Bouncers enforce decisions at the reverse proxy, firewall, or CDN level
- Community: your detections contribute to the global blocklist; you receive others' detections
CrowdSec vs fail2ban
| Feature | CrowdSec | fail2ban |
|---|---|---|
| Shared threat intel | Yes (crowd-sourced) | No (local only) |
| IP reputation lists | Yes (community) | No |
| Language | Go | Python |
| Performance | Fast | Slow with many rules |
| Actions | Ban, captcha, throttle | Ban only |
| Web console | Yes (free) | No |
| API | REST API | CLI only |
| Bouncer ecosystem | Rich (Caddy, Nginx, CF) | iptables only |
| Configuration | YAML scenarios | Regex filters |
Part 1: Docker Setup
# docker-compose.yml
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
restart: unless-stopped
ports:
- "8080:8080" # API (local only — don't expose publicly)
- "6060:6060" # Prometheus metrics (optional)
volumes:
# CrowdSec config and data:
- crowdsec_config:/etc/crowdsec
- crowdsec_data:/var/lib/crowdsec/data
# Log sources (mount the logs you want CrowdSec to watch):
- /var/log:/var/log:ro
- caddy_logs:/var/log/caddy:ro # Caddy access logs
# - nginx_logs:/var/log/nginx:ro # Nginx logs
# - /var/log/auth.log:/var/log/auth.log:ro # SSH logs
environment:
# Collections to install on first run:
COLLECTIONS: >-
crowdsecurity/linux
crowdsecurity/caddy
crowdsecurity/http-cve
crowdsecurity/whitelist-good-actors
# crowdsecurity/nginx # If using Nginx
# crowdsecurity/sshd # If SSH is exposed
# Enroll in CrowdSec Console (optional):
# ENROLL_KEY: "your-enrollment-key"
# ENROLL_INSTANCE_NAME: "my-server"
volumes:
crowdsec_config:
crowdsec_data:
caddy_logs: # Your Caddy log volume
docker compose up -d
# Check it's running:
docker exec crowdsec cscli version
docker exec crowdsec cscli metrics
Part 2: Configure Log Sources
Caddy
Make sure Caddy logs to a file that CrowdSec can read:
{
log {
output file /var/log/caddy/access.log
format json
}
}
CrowdSec acquirer config:
# /etc/crowdsec/acquis.yaml (or acquis.d/caddy.yaml)
source: file
filenames:
- /var/log/caddy/access.log
labels:
type: caddy
Nginx
source: file
filenames:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
labels:
type: nginx
SSH
source: file
filenames:
- /var/log/auth.log
labels:
type: syslog
Docker container logs
source: docker
container_name:
- my-webapp
labels:
type: nginx
Part 3: Install Bouncers
Bouncers enforce CrowdSec's decisions (bans, captchas, etc.).
Caddy Bouncer
# Generate an API key for the bouncer:
docker exec crowdsec cscli bouncers add caddy-bouncer
# Outputs: API key = abc123...
# Add to docker-compose.yml:
caddy:
image: caddy:latest
# Use the CrowdSec Caddy module:
# Build a custom Caddy with: xcaddy build --with github.com/hslatman/caddy-crowdsec-bouncer
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
{
crowdsec {
api_url http://crowdsec:8080
api_key abc123...
ticker_interval 15s
}
}
yourdomain.com {
crowdsec
reverse_proxy localhost:3000
}
Nginx Bouncer
# Generate bouncer API key:
docker exec crowdsec cscli bouncers add nginx-bouncer
# docker-compose.yml:
nginx-bouncer:
image: crowdsecurity/cs-openresty-bouncer:latest
container_name: nginx-bouncer
restart: unless-stopped
environment:
CROWDSEC_BOUNCER_API_KEY: "abc123..."
CROWDSEC_AGENT_HOST: "crowdsec:8080"
depends_on:
- crowdsec
Firewall Bouncer (iptables/nftables)
# Install directly on the host:
curl -s https://install.crowdsec.net | sudo bash
sudo apt install crowdsec-firewall-bouncer-iptables
# Or nftables:
sudo apt install crowdsec-firewall-bouncer-nftables
# Configure:
sudo vim /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
# api_url: http://localhost:8080
# api_key: abc123...
Cloudflare Bouncer
docker exec crowdsec cscli bouncers add cloudflare-bouncer
# docker-compose.yml:
cloudflare-bouncer:
image: crowdsecurity/cs-cloudflare-bouncer:latest
restart: unless-stopped
environment:
CROWDSEC_BOUNCER_API_KEY: "abc123..."
CROWDSEC_AGENT_HOST: "crowdsec:8080"
CLOUDFLARE_API_TOKEN: "${CF_API_TOKEN}"
CLOUDFLARE_ACCOUNT_ID: "${CF_ACCOUNT_ID}"
Part 4: Scenarios and Collections
List installed scenarios
docker exec crowdsec cscli scenarios list
docker exec crowdsec cscli collections list
Install additional collections
# WordPress protection:
docker exec crowdsec cscli collections install crowdsecurity/wordpress
# Traefik:
docker exec crowdsec cscli collections install crowdsecurity/traefik
# HTTP generic attacks:
docker exec crowdsec cscli collections install crowdsecurity/http-cve
# Whitelist known good bots (Google, Bing, etc.):
docker exec crowdsec cscli collections install crowdsecurity/whitelist-good-actors
What scenarios detect
| Scenario | Detects |
|---|---|
crowdsecurity/http-bf | HTTP brute force (login pages) |
crowdsecurity/ssh-bf | SSH brute force |
crowdsecurity/http-crawl-non_statics | Aggressive crawlers |
crowdsecurity/http-bad-user-agent | Known malicious user agents |
crowdsecurity/http-path-traversal | Path traversal attempts |
crowdsecurity/http-sqli | SQL injection attempts |
crowdsecurity/http-xss | Cross-site scripting attempts |
crowdsecurity/http-cve-* | Known CVE exploits |
Part 5: Managing Decisions
# View active decisions (bans):
docker exec crowdsec cscli decisions list
# Ban an IP manually:
docker exec crowdsec cscli decisions add -i 1.2.3.4 -d 24h -t ban -r "manual block"
# Ban a range:
docker exec crowdsec cscli decisions add -r 1.2.3.0/24 -d 48h -t ban -r "abusive range"
# Remove a ban:
docker exec crowdsec cscli decisions delete -i 1.2.3.4
# Whitelist your own IP:
cat >> /etc/crowdsec/parsers/s02-enrich/whitelist.yaml << 'EOF'
name: my-whitelist
description: "Whitelist my IPs"
whitelist:
reason: "My trusted IPs"
ip:
- "203.0.113.10" # Your home IP
- "10.0.0.0/8" # Internal network
EOF
docker exec crowdsec cscli hub update
docker compose restart crowdsec
Part 6: CrowdSec Console
The free cloud console at app.crowdsec.net provides:
- Real-time alert visualization
- Attack statistics and trends
- Community blocklist status
- Multi-instance management
Enroll your instance
# Get enrollment key from app.crowdsec.net:
docker exec crowdsec cscli console enroll YOUR_ENROLLMENT_KEY \
--name "my-server" \
--tags "production,web"
Part 7: Alerts and Notifications
Send alerts to ntfy
# /etc/crowdsec/notifications/ntfy.yaml
type: http
name: ntfy
log_level: info
format: |
{{ range . -}}
{{ .Alert.Scenario }} triggered by {{ .Alert.Source.IP }}
{{ end -}}
url: "https://ntfy.yourdomain.com/crowdsec-alerts"
method: POST
headers:
Title: "CrowdSec Alert"
Priority: "high"
Tags: "shield"
# /etc/crowdsec/profiles.yaml (add notification):
name: default_ip_remediation
filters:
- Alert.Remediation == true && Alert.GetScope() == "Ip"
decisions:
- type: ban
duration: 4h
notifications:
- ntfy
on_success: break
Part 8: Metrics and Monitoring
# View metrics:
docker exec crowdsec cscli metrics
# Sample output:
# Acquisition:
# /var/log/caddy/access.log: 15423 lines read, 12 events parsed
# Parsers:
# crowdsecurity/caddy-logs: 12 parsed
# Scenarios:
# crowdsecurity/http-bf: 3 triggered
# View alert history:
docker exec crowdsec cscli alerts list
# View specific alert:
docker exec crowdsec cscli alerts inspect 42
# Prometheus metrics (if port 6060 exposed):
curl localhost:6060/metrics
Maintenance
# Update:
docker compose pull
docker compose up -d
# Update hub (scenarios, parsers, collections):
docker exec crowdsec cscli hub update
docker exec crowdsec cscli hub upgrade
# Backup config:
tar -czf crowdsec-config-$(date +%Y%m%d).tar.gz \
$(docker volume inspect crowdsec_crowdsec_config --format '{{.Mountpoint}}')
# Check bouncer connectivity:
docker exec crowdsec cscli bouncers list
# Logs:
docker compose logs -f crowdsec
See all open source security tools at OSSAlt.com/categories/security.