How to install CrowdSec on Ubuntu and Debian
Install the CrowdSec engine and its nftables firewall bouncer, watch SSH and nginx logs, allowlist your own addresses, and see what it blocks.
Tested on Ubuntu 24.04 LTS, Debian 13 Stable
Before you start
- A server running Ubuntu 24.04 or 26.04 or Debian 12 or 13
- Root or a user with sudo
- nginx installed if you want its logs watched
To install CrowdSec on Ubuntu or Debian, add its repository with curl -s https://install.crowdsec.net | sudo sh, then run sudo apt install crowdsec crowdsec-firewall-bouncer-nftables. The first package reads your logs and decides who is attacking; the second (the bouncer) blocks those addresses in the kernel firewall. Both are configured for SSH, and for nginx if it's installed, without further steps.
This tutorial was run with CrowdSec 1.8.1 and firewall bouncer 0.0.36 on Ubuntu 24.04 and Debian 13.
CrowdSec or fail2ban?
Both read logs and ban addresses that misbehave. The difference is what else comes with it:
| fail2ban | CrowdSec | |
|---|---|---|
| What decides a ban | Regular expressions per jail, in jail.local |
Parsers and scenarios from the CrowdSec Hub, installed as collections |
| Who does the blocking | fail2ban itself, through iptables, nftables or ufw | A separate bouncer (firewall, nginx, Cloudflare and others) |
| Shared blocklist | No | Yes: with the default settings, it sends the addresses it bans to CrowdSec and receives their community blocklist |
| Footprint | Small Python daemon | A Go daemon with a local API, plus the bouncer |
| Good for | SSH on one server, with nothing to learn | Several services (SSH, nginx, WordPress) and several servers |
If all you need is to slow down SSH password guessers on one server, fail2ban is simpler and we cover it in a short guide. Pick one: running both on the same logs only bans everyone twice. If your SSH only accepts keys (it does on a new VPSNine server), neither is protecting a door that's open; they keep the logs quiet and stop scanners early.
The shared blocklist means CrowdSec sends the addresses it acts on, the scenario that triggered and a timestamp to CrowdSec's central API. Their documentation describes what is shared. If that doesn't suit you, fail2ban never sends anything.
Install the engine
Add the official repository and install the package:
curl -s https://install.crowdsec.net | sudo sh
sudo apt install -y crowdsecThe script only writes an apt source and its key under /etc/apt/. If you would rather read it first, run curl -s https://install.crowdsec.net -o crowdsec-repo.sh, read it, then sudo sh crowdsec-repo.sh.
During installation, CrowdSec looks at what is running and writes one log source per service into /etc/crowdsec/acquis.d/ (setup.sshd.yaml, setup.nginx.yaml, setup.linux.yaml), then installs the matching collections from the Hub.
Check it worked
sudo systemctl is-active crowdsec
sudo cscli collections listThe service is active, and the list includes crowdsecurity/linux and crowdsecurity/sshd, plus crowdsecurity/nginx and the HTTP scenarios if nginx was installed.
Install the firewall bouncer
On its own, CrowdSec only detects. The firewall bouncer turns its decisions into nftables rules:
sudo apt install -y crowdsec-firewall-bouncer-nftablesIt registers itself with the local API and starts. Ubuntu 24.04 and Debian 12 and 13 use nftables underneath, ufw included, so the nftables bouncer is the right one; the -iptables package exists for older systems.
Check it worked
Ban a test address from the documentation range for five minutes, and look for it in the kernel's rules:
sudo cscli bouncers list
sudo cscli decisions add --ip 192.0.2.77 --duration 5m --reason "test"
sudo nft list set ip crowdsec crowdsec-blacklists-cscliThe bouncer is listed as valid, and after a few seconds the set contains 192.0.2.77 with a timeout. Remove the test ban:
sudo cscli decisions delete --ip 192.0.2.77Allowlist your own addresses
Before anything bans you, put your own addresses on an allowlist. CrowdSec already ignores private ranges and localhost:
sudo cscli allowlists create my_ips -d "office and home"
sudo cscli allowlists add my_ips 198.51.100.0/24Use your real address or range; curl -4 https://icanhazip.com from your computer shows it.
Add nginx if you installed it later
If you install nginx after CrowdSec, add its collection and log source yourself:
sudo cscli collections install crowdsecurity/nginx
sudo tee /etc/crowdsec/acquis.d/nginx.yaml <<'EOF'
filenames:
- /var/log/nginx/*.log
labels:
type: nginx
source: file
EOF
sudo systemctl reload crowdsecCheck it worked
Load a page or two on the server, then:
sudo cscli metrics show acquisitionfile:/var/log/nginx/access.log appears with lines read and parsed. The same table shows the SSH journal source.
CrowdSec also has an nginx bouncer, a Lua module that answers banned visitors with a block page or a captcha instead of dropping their packets. The firewall bouncer is enough for most servers; the nginx bouncer docs cover it if you want it.
See what it's doing
sudo cscli alerts list # what was detected, and when
sudo cscli decisions list # who is banned right now, and for how long
sudo cscli metrics # lines read, parsed, and bans by bouncerOn a server with a public address, SSH scanners show up quickly, often on the first day. A ban lasts four hours by default (duration: 4h in /etc/crowdsec/profiles.yaml).
To check how CrowdSec reads a particular log line, ask it to explain:
sudo cscli explain --type syslog --log "Oct 21 10:00:00 web1 sshd[123]: Failed password for invalid user admin from 192.0.2.50 port 4242 ssh2"The output ends with the scenarios the line feeds, such as crowdsecurity/ssh-bf.
Keep it updated
The packages update with apt upgrade. The Hub's parsers and scenarios update separately:
sudo cscli hub update
sudo cscli hub upgrade
sudo systemctl reload crowdsecThe package also installs crowdsec-hubupdate.timer, which runs a Hub update once a day, so doing it by hand is only needed when you want a fix right away.
Troubleshooting
installed crowdsec package post-installation script subprocess returned error exit status 1. The setup step downloads from the Hub during installation, and a failed download stops it. Run sudo dpkg --configure -a to retry; it finished the setup the second time when we hit this.
You banned yourself. From another address (a phone's mobile data) or the serial console, run sudo cscli decisions delete --ip YOUR.IP, then add it to the allowlist.
Nothing shows up in cscli alerts list. Check sudo cscli metrics show acquisition: if a source reads no lines, its path or journal filter is wrong. On Ubuntu and Debian the SSH unit is ssh.service, which is what the generated setup.sshd.yaml filters on.
cscli bouncers list shows the bouncer but nothing is blocked. sudo systemctl status crowdsec-firewall-bouncer and journalctl -u crowdsec-firewall-bouncer -n 30. A bouncer installed before the engine can't register itself; reinstall it with sudo apt install --reinstall crowdsec-firewall-bouncer-nftables.
Next steps
- Make SSH keys-only and limit who can log in with the SSH hardening checklist.
- Read CrowdSec's own logs and the SSH journal with journalctl.
- Prefer something smaller? fail2ban does the SSH part in ten minutes.
Doing it on VPSNine
On a VPSNine server, CrowdSec's bans happen on the server itself. To keep traffic from reaching it at all, add deny rules or allow-only rules in the panel firewall, which filters before the server sees a packet. Runs on Ubuntu 24.04 and Debian 13 on every plan; CrowdSec and the bouncer used about 170 MB of memory together in our test, which fits comfortably on the Budget plan's 2 GB.