Replace fail2ban with CrowdSec
Replace fail2ban with CrowdSec: install the agent and firewall bouncer, activate crowd-sourced blocklists, configure scenarios, and verify enforcement with nftables.
Before you start
- ▸Root or sudo access on the target server
- ▸fail2ban currently installed (or at least awareness of what log sources to protect)
- ▸nftables available and not replaced by a conflicting firewall manager (or firewalld installed for the firewalld bouncer variant)
- ▸A free account at app.crowdsec.net for the community blocklist enrollment
Fail2ban has protected Linux servers for nearly two decades by parsing logs and firing iptables rules. CrowdSec does the same job but adds a crowd-sourced threat intelligence layer: every participating server shares attacker IPs with a global network, and you benefit from blocks that other operators have already earned the hard way. The local agent is a log parser and signal emitter; bouncers are the enforcement pieces that actually drop traffic. That separation makes CrowdSec more composable than fail2ban and easier to audit.
Remove or Disable fail2ban First
You only need one tool reacting to the same log lines. Stop and mask fail2ban before proceeding.
sudo systemctl stop fail2ban
sudo systemctl disable --now fail2ban
Optionally purge it — the config can always be reinstalled later:
# Debian/Ubuntu
sudo apt purge fail2ban
# Fedora / RHEL / Rocky
sudo dnf remove fail2ban
# Arch
sudo pacman -Rns fail2ban
Install the CrowdSec Agent
CrowdSec maintains its own repository. Use it — distro repos often carry stale versions and CrowdSec moves quickly.
Debian and Ubuntu
curl -fsSL https://packagecloud.io/crowdsec/crowdsec/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/crowdsec-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/crowdsec-archive-keyring.gpg] \
https://packagecloud.io/crowdsec/crowdsec/debian $(lsb_release -cs) main" \
| sudo tee /etc/apt/sources.list.d/crowdsec.list
sudo apt update && sudo apt install crowdsec
Fedora, RHEL 8+, Rocky Linux
sudo dnf install dnf-plugins-core
sudo dnf config-manager --add-repo \
https://packagecloud.io/crowdsec/crowdsec/config_file.repo?os=el&dist=8
sudo dnf install crowdsec
On RHEL/Rocky you may need to enable EPEL first: sudo dnf install epel-release.
Arch Linux (AUR)
paru -S crowdsec # or: yay -S crowdsec
Enable and start the service:
sudo systemctl enable --now crowdsec
Understand the Architecture
The agent (crowdsec) reads log files through acquisition configs, runs them through parsers, and evaluates scenarios — YAML state machines that detect attack patterns like SSH brute force or web scanning. When a scenario fires, it creates an alert. Alerts are stored in a local SQLite database (or PostgreSQL/MySQL in multi-server setups).
Bouncers are separate processes that query the local API for active decisions and enforce them — in the firewall, Nginx config, or wherever makes sense. The agent never touches your firewall directly.
Install Scenarios (Collections)
Collections bundle parsers and scenarios for a given service. The installer auto-detects common daemons, but you should verify and add what you need.
# List installed collections
cscli collections list
# Common additions
cscli collections install crowdsecurity/sshd
cscli collections install crowdsecurity/nginx
cscli collections install crowdsecurity/linux # syslog, auth.log
cscli collections install crowdsecurity/postfix
After adding collections, reload the agent so it picks up new parsers:
sudo systemctl reload crowdsec
Confirm scenarios are running:
cscli scenarios list
You should see entries like crowdsecurity/ssh-bf (SSH brute force) and crowdsecurity/http-crawl-non_statics if nginx is installed.
Configure Log Acquisition
Acquisition files live in /etc/crowdsec/acquis.d/. The installer creates sensible defaults; check them.
cat /etc/crowdsec/acquis.d/sshd.yaml
A typical entry looks like this (do not copy blindly — journald paths vary):
cat /etc/crowdsec/acquis.d/nginx.yaml
# Expected output (varies):
# filenames:
# - /var/log/nginx/access.log
# - /var/log/nginx/error.log
# labels:
# type: nginx
If your service logs to systemd journal rather than a file, use the journald source type:
cat <<'EOF' | sudo tee /etc/crowdsec/acquis.d/sshd-journal.yaml
source: journald
journalctl_filter:
- "_SYSTEMD_UNIT=sshd.service"
labels:
type: syslog
EOF
Install a Bouncer
Without a bouncer nothing actually blocks traffic. The firewall bouncer is the most common choice; it drives nftables (preferred) or iptables.
Debian/Ubuntu
sudo apt install crowdsec-firewall-bouncer-nftables
Fedora / RHEL / Rocky
sudo dnf install crowdsec-firewall-bouncer-nftables
Arch
paru -S crowdsec-firewall-bouncer
The package installer registers the bouncer with the local API automatically. Verify it is enrolled:
cscli bouncers list
You should see cs-firewall-bouncer with a valid API key. Enable the service:
sudo systemctl enable --now crowdsec-firewall-bouncer
The bouncer creates an nftables table called crowdsec. Confirm it:
sudo nft list table inet crowdsec
Enable the Community Blocklist
CrowdSec pulls a free, crowd-sourced IP blocklist that is updated every 24 hours. Enroll your instance to activate it. You need a free account at app.crowdsec.net.
# Replace TOKEN with your enrollment key from the CrowdSec console
cscli console enroll <YOUR_ENROLLMENT_TOKEN>
sudo systemctl restart crowdsec
After a few minutes, check that the blocklist subscription is active:
cscli hub list
Decisions from the community feed appear alongside local decisions in:
cscli decisions list
Verify Everything is Working
# Overall agent health
cscli metrics
# Recent alerts generated locally
cscli alerts list
# Active bans (local + community)
cscli decisions list
# Check the bouncer applied an nftables rule
sudo nft list ruleset | grep crowdsec
To simulate a brute-force detection without real attacks, use the built-in test harness:
cscli simulation enable crowdsecurity/ssh-bf
# Feed fake log lines, then check alerts:
cscli alerts list
cscli simulation disable crowdsecurity/ssh-bf
The Web Dashboard (optional)
CrowdSec ships a local dashboard powered by Metabase. It requires Docker.
sudo cscli dashboard setup --listen 0.0.0.0
It prints a random admin password on first run — save it. The dashboard binds to port 3000 by default. Restrict access in your firewall; this is not a public-facing service. For a production server, the hosted CrowdSec Security Engine console is usually the better choice — it aggregates multiple instances without running Metabase locally.
Troubleshooting
- No decisions appearing: Run
cscli metricsand check the Parsed row for your log source. If it is zero, acquisition is broken — confirm the file path exists and the label type matches the parser. - Bouncer not blocking after a decision: Confirm the bouncer service is running (
systemctl status crowdsec-firewall-bouncer) and thatnft list table inet crowdsecshows rules. If you run firewalld, installcrowdsec-firewall-bouncer-firewalldinstead of the nftables variant. - False positives on your own IP: Whitelist it permanently:
cscli decisions delete --ip 203.0.113.5then add it to/etc/crowdsec/parsers/s02-enrich/whitelists.yaml. - Logs not parsed on Arch / systemd-only distros: Make sure the
journaldacquisition file is in place and thetypelabel matches what the parser expects (check parser YAML in/etc/crowdsec/parsers/). - CrowdSec uses too much CPU: Large log files or high-traffic nginx installs can spike CPU briefly on startup. Set
max_leakspeedin/etc/crowdsec/config.yamlto rate-limit log ingestion.
Frequently asked questions
- Does CrowdSec send my server's logs to the cloud?
- No. Only the attacker IP and the scenario that fired are shared — never log content or data about your users. You can review exactly what is transmitted in the CrowdSec console under 'Signal sharing'.
- Can I run CrowdSec alongside firewalld instead of raw nftables?
- Yes. Install crowdsec-firewall-bouncer-firewalld instead of the nftables variant. It manages a dedicated firewalld zone called 'crowdsec' and integrates cleanly with firewalld's rule priority system.
- How do I whitelist my own IP address so it is never banned?
- Add your IP or CIDR range to the whitelist parser at /etc/crowdsec/parsers/s02-enrich/whitelists.yaml under the 'ip' key, then run sudo systemctl reload crowdsec. This prevents the agent from ever creating a decision for that address.
- What happens if the CrowdSec agent crashes — does enforcement stop?
- No. The bouncer polls the local API independently. If the agent is down, the bouncer continues enforcing previously fetched decisions until they expire. New threats will not be detected, but existing blocks remain active.
- Is the community blocklist the same as the paid threat intelligence feeds?
- The free community blocklist is crowd-sourced from enrolled instances and is a solid baseline. CrowdSec also sells premium blocklists (CVE-targeted, Tor exit nodes, proxy lists) under its CTI subscription, which are separate from the free tier.
Related guides
Manage Secrets with Ansible Vault
Encrypt Ansible secrets with AES-256 using ansible-vault: encrypt files and inline vars, automate with password files, and isolate group-level secrets with vault IDs.
AppArmor Explained
Learn how AppArmor profiles work, how to switch between enforce and complain mode, create new profiles, and diagnose access denials on Ubuntu, Debian, and Arch.
Apply CIS Benchmarks with OpenSCAP
Use OpenSCAP and scap-security-guide to evaluate, report on, and remediate Linux systems against CIS Benchmarks — covering install, eval, and automation.
How to Audit a Linux System with auditd
Set up auditd on Linux to track file access, syscalls, and privilege use. Covers persistent rules, file watches, ausearch, and aureport across major distros.