CrowdSec: collaborative intrusion prevention

fail2ban works, but it’s solo — every server sees the same SSH brute-force attempts independently. CrowdSec fixes that: when one server bans an IP, all CrowdSec users benefit from the shared blocklist.

Install

# CrowdSec engine
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
apt install -y crowdsec

# Caddy bouncer (rejects bad IPs at the reverse proxy level)
apt install -y crowdsec-caddy-bouncer

CrowdSec auto-detects running services and activates parsers. For a stock setup, it will parse SSH, Caddy, and Nginx logs out of the box.

Verify

sudo cscli metrics
sudo cscli decisions list  # active bans
sudo cscli alerts list    # recent alerts

You should see your first SSH brute-force attempts within minutes.

How it works

  1. Parsers read service logs (sshd, nginx, caddy, etc.)
  2. Scenarios match patterns (e.g. ssh-bf = brute force)
  3. Decisions are created (ban IP for 4 hours, by default)
  4. Bouncers enforce decisions (drop packets, return 403)
  5. Community blocklist shares anonymized signals with everyone

Tweak the bouncer for Caddy

The Caddy bouncer integrates as a Caddy module. Edit your Caddyfile:

{
    order crowdsec first
}

example.com {
    crowdsec
    reverse_proxy app:8080
}

Reload Caddy. Now banned IPs get rejected at the TLS handshake — before they hit your app at all.

Console (optional)

The free CrowdSec console gives you a dashboard with a map of attacks, top offenders, and your security posture. Sign up, then enroll your instance:

sudo cscli console enroll <your-enrollment-key>

This is optional but nice for visibility.

Why not keep fail2ban?

  • Shared intelligence: One user’s ban protects everyone
  • Faster: Bouncer can block at L4 (iptables) or L7 (Caddy)
  • Modern stack: HTTP API, dashboard, metric export
  • Better logs: Structured alerts, not raw regex

For a single server, fail2ban is fine. For 3+ servers, CrowdSec is worth the switch.