Skip to main content

CrowdSec: a modern IPS defense system for VPS

Security · 19.04.2026 · 4 min read
Illustration for “CrowdSec: a modern IPS defense system for VPS”

CrowdSec is a modern open-source IPS (Intrusion Prevention System) that works as an improved replacement for fail2ban. The key difference: all CrowdSec users share information about attacking IPs, forming a collective threat database from millions of sources.

CrowdSec vs fail2ban

Featurefail2banCrowdSec
ArchitectureMonolithicAgent + Bouncer
Threat IntelligenceLocal logs onlyGlobal shared DB
Proactive blockingNoYes (known attackers)
Web dashboardNoYes (app.crowdsec.net)
Scenario collectionsRegex onlyYAML scenarios, Hub
LicenseGPLMIT (Community)

Installing CrowdSec

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

# Install the Nginx Bouncer (blocker)
apt install crowdsec-nginx-bouncer -y

# Or the firewall bouncer
apt install crowdsec-firewall-bouncer-nftables -y

Installing scenario collections

cscli collections list
cscli collections install crowdsecurity/nginx
cscli collections install crowdsecurity/wordpress
cscli collections install crowdsecurity/ssh-bf
cscli collections install crowdsecurity/linux-lpe
systemctl reload crowdsec

Managing blocks

cscli decisions list
cscli decisions add --ip 1.2.3.4 --duration 24h --reason "manual ban"
cscli decisions delete --ip 1.2.3.4
cscli alerts list --limit 20

Monitoring metrics

cscli metrics
cscli bouncers list
cscli machines list
CrowdSec Hub: app.crowdsec.net offers a free dashboard with attack graphs, a map of threat sources, and management of your agents.
CrowdSec doesn't replace firewall configuration and SSH hardening — it's an additional layer. Use it together with ufw/nftables and sshd_config rules.

Common problems when deploying CrowdSec

  • level=fatal msg="unable to run local API: listen tcp 127.0.0.1:8080: bind: address already in use" — port 8080 is already taken by default, usually by a Node.js app, a panel, or a test PHP server. Change api.server.listen_uri in /etc/crowdsec/config.yaml to a free port.
  • cscli decisions add runs without errors, yet the attacker's traffic still gets through — a decision is only a record in the LAPI database. Actual blocking is done by a bouncer, and without one installed and configured, nothing stops the traffic.
  • cscli bouncers list shows a bouncer with an empty Last Pull column — it is registered but not pulling decisions. The cause is almost always a wrong api_url or api_key in its config, for example /etc/crowdsec/bouncers/crowdsec-nginx-bouncer.yaml.
  • cscli metrics shows zero events for an installed scenario — the log source from acquis.yaml is not being read: either the path is wrong, or the user crowdsec runs as lacks permission to read the log.
  • The nginx-bouncer fails to run on a stock distro Nginx package — crowdsec-nginx-bouncer requires Nginx built with ngx_http_lua_module, or OpenResty; the standard apt build of Nginx does not include that module.

Bouncer types and what each one blocks

BouncerBlocking levelWhere it is installedLimitation
nginx-bouncerHTTP request (application level)On every Nginx serverNeeds the Lua module, has no effect on non-HTTP traffic
firewall-bouncer (nftables/iptables)Network packetOn the whole hostBlocks any traffic, but cannot see HTTP headers or URLs
cloudflare-bouncerCDN edgeInside a Cloudflare accountOnly works if all traffic already goes through Cloudflare
Custom bouncer via APIWhatever you implementYour own script calling the LAPIRequires you to build and maintain it

When CrowdSec is not the right fit

  • A single low-traffic server where fail2ban already covers the need — CrowdSec adds an agent, LAPI, and a bouncer, meaning more moving parts and memory for not much extra gain.
  • An isolated network with no internet access — sharing the collective attacker database with CrowdSec's CAPI requires reaching an external service; in a closed environment, only local scenario analysis remains, with no network effect.
  • A server with very limited memory (512 MB to 1 GB) — the CrowdSec agent, its local decision database, and a bouncer together are heavier on resources than fail2ban.
  • You need blocking based on complex post-login behavioral signals (device fingerprint, session anomalies) — that is an application-level or dedicated anti-fraud task, not an IPS at CrowdSec's level.

Verifying that blocking actually works

# Add a short-lived test block for YOUR OWN external IP
cscli decisions add --ip 1.2.3.4 --duration 1m --reason "test block"

# Confirm the decision landed in the LAPI database
cscli decisions list

# From the blocked IP, check that the connection is really refused
curl -I https://example.com

# Remove the test block before it expires on its own
cscli decisions delete --ip 1.2.3.4

Replace 1.2.3.4 with your own external address and run the check from that machine, not from the server itself — otherwise the third command only proves the server works locally and says nothing about whether the bouncer actually blocks someone else's traffic.

Was this article helpful?
← Back to Knowledge Base Ask Support