CrowdSec vs Fail2ban vs Wazuh on a VPS in 2026: Which One Should Actually Defend Your Box?
Three years ago, when I was setting up the first generation of our aggregator stack at Warung Digital Teknologi, I made a mistake that quietly cost me about 40 hours of cleanup. I left a fresh Hostinger VPS exposed on port 22 with password auth temporarily enabled while I migrated keys from an old machine. Within six hours, auth.log had over 2,800 failed SSH attempts from 14 countries. I caught it before anything got compromised, but that night I made a rule for myself: never run a public-facing VPS without an active intrusion defense layer, no matter how short the window.
Since then, I've cycled through Fail2ban, CrowdSec, and Wazuh across the seven aggregator sites I currently run plus 50+ client projects we've shipped at wardigi.com. The seven public sites β including this one, HoroAura, Hirevane, and CyberShieldTips β collectively log somewhere between 18,000 and 35,000 abuse events per day depending on whether a botnet is having a fun week. That's not enterprise scale, but it's enough to feel the difference between these three tools when one of them starts choking.
If you're staring at this comparison trying to pick one for your own VPS, here's the version I'd give a friend over coffee: Fail2ban for tiny single-purpose boxes, CrowdSec for anything public-facing where you actually want to sleep at night, and Wazuh only if you have compliance pressure or a real SOC reading the alerts. The rest of this article is the long version, with the specific numbers I've measured and the mistakes I'd want you to skip.
The 60-Second Mental Model
All three tools sit roughly in the same neighborhood β they read logs, decide who's misbehaving, and block the offender β but they aim at different targets.
Fail2ban is the patriarch. It has been around since 2004, ships in every major distro repo, and works by tailing log files, matching regex patterns, and pushing iptables/nftables rules when a pattern fires. It's reactive, local-only, and brain-dead simple. That simplicity is its biggest virtue and its biggest limitation.
CrowdSec launched in 2020 as an explicit answer to "what would Fail2ban look like if it were rebuilt today." The detection engine is still log-driven, but scenarios are written in YAML and can express time-windowed behavior ("five 404s in two minutes from the same IP") rather than just single-line regex. The bigger shift is the community blocklist: every CrowdSec instance optionally reports anonymized attack signals, and pulls down a curated feed of IPs that other instances flagged. New machines start with several thousand known-bad IPs already blocked the moment the daemon comes up.
Wazuh is a different category entirely. It's an open-source SIEM/XDR β agent on each endpoint, central manager and indexer back home, dashboards on Wazuh Indexer (a fork of OpenSearch). It does file integrity monitoring, vulnerability scanning, log correlation, MITRE ATT&CK mapping, and yes, active response that can block IPs. Calling it an alternative to Fail2ban undersells what it actually does, but if all you want is brute-force protection, it's massive overkill.
Resource Footprint on a Real $6 VPS
The single biggest reason most home-lab and small-business operators reach for Fail2ban is that it barely shows up in top. I tested all three on the same Contabo VPS S (4 vCPU, 8 GB RAM, NVMe β running Ubuntu 24.04) over a 72-hour window. The machine was hosting an idle nginx with a static placeholder, so the load came almost entirely from the security tools themselves and the ambient internet noise.
| Tool | Idle RAM | RAM under load | CPU at peak | Cold-start time |
|---|---|---|---|---|
| Fail2ban 1.0.2 | ~22 MB | ~28 MB | 0.4% | 2 sec |
| CrowdSec 1.6.4 + bouncer | ~85 MB | ~140 MB | 1.8% | 4 sec |
| Wazuh agent only | ~95 MB | ~180 MB | 2.1% | 6 sec |
| Wazuh server (all-in-one) | ~3.4 GB | ~4.1 GB | 14% (indexer) | ~90 sec |
That last row is the one that catches people out. A self-hosted Wazuh manager pulls in OpenSearch (the indexer) and a Filebeat pipeline. The official documentation says 2 GB RAM minimum and 4 GB recommended, but in practice with even a few agents reporting in, 4 GB feels tight and 8 GB is where you actually want to be. On a $6/month VPS with 2 GB RAM, Wazuh server is a non-starter β the OOM killer will come for it within hours. You either need to size up to a 4 GB box (Hetzner CX22 at β¬4.51/month is what I use) or run a hosted Wazuh Cloud instance.
For comparison, Fail2ban will happily live on a $3.50 BuyVM Slice with 512 MB RAM. CrowdSec is comfortable on anything 1 GB and up. The bouncer (the component that actually pushes blocks to the firewall) adds another 30-50 MB on top of the agent.
Detection Quality: What Actually Gets Blocked
Resource cost matters, but only after you've established that the tool catches what you're paying it to catch. I ran a 30-day side-by-side on one of our staging VPS instances with all three configured to monitor SSH, nginx access logs, and a Laravel auth log. Here's the count of unique IPs blocked over that window:
| Source | Fail2ban | CrowdSec (local only) | CrowdSec (with community blocklist) | Wazuh (default rules) |
|---|---|---|---|---|
| SSH brute force | 1,847 | 1,901 | 1,901 + 41,233 pre-blocked | 1,612 |
| nginx scanner / 404 abuse | 0 (no jail by default) | 2,114 | 2,114 + 28,910 pre-blocked | 843 |
| WordPress wp-login probes | 0 | 1,476 | 1,476 + 18,002 pre-blocked | 211 |
| Credential stuffing on Laravel | 0 | 388 | 388 + 7,440 pre-blocked | 0 |
Fail2ban only handled SSH because that's the only jail enabled out of the box. It will absolutely catch the other categories if you write the regex and configure the jail, but I count "what works without me writing 200 lines of config" as part of the comparison. Wazuh's default rules are tuned for a different audience β they're fantastic for detecting privilege escalation, persistence techniques, and lateral movement, but they undercount basic web-layer noise unless you customize the decoders.
The community blocklist column is where CrowdSec earns its reputation. I'd estimate roughly 40-55% of the IPs hammering our public sites on any given day are already on the community feed before they ever hit our box. That's blocks happening at the edge with zero log entries, zero CPU, zero noise in your alert channel. After three years of running it, this is the single feature I miss when I move back to plain Fail2ban for a small project.
Configuration Effort: How Much of Your Saturday Disappears
Let me put a stake in the ground: the time-to-protected metric is the most underrated one when comparing these tools. I've timed my own setup work on each to give you a realistic picture.
Fail2ban first-time setup on a stock Ubuntu VPS: About 15 minutes for SSH protection. apt install fail2ban, copy jail.conf to jail.local, set enabled = true under [sshd], reload. Done. To get nginx and WordPress protection, you'll spend another 1-2 hours writing or sourcing filters, testing them with fail2ban-regex, and verifying jails actually trip. The official wiki has community filter examples, but quality varies and many haven't been touched since 2019.
CrowdSec first-time setup: About 25 minutes end to end. The installer (curl -s https://install.crowdsec.net | sudo sh, then apt install crowdsec) auto-detects services like SSH, nginx, and Apache and enables the relevant scenarios. The bouncer install (e.g., cs-firewall-bouncer-iptables) takes another 5 minutes. Subscribing to the community blocklist requires creating a free account and registering the machine β one extra minute and maybe two CLI commands. After that, you can install scenario "collections" from the hub: cscli collections install crowdsecurity/wordpress, crowdsecurity/laravel, crowdsecurity/sshd, and so on. This part is delightful β the hub is curated, the YAML is readable, and updates ship via cscli hub update.
Wazuh first-time setup: 2-4 hours for a single-node all-in-one, longer if you want it tuned. The Quickstart script is one command and it does work, but tuning rules, configuring agents, integrating with SMTP/Slack/Discord, and getting the dashboards to show what you actually care about is a real time investment. Plan for at least a half-day of focused work to feel comfortable with what you've built. If you've used ELK or any SIEM before, your prior experience transfers; if you haven't, the learning curve is steeper than CrowdSec's by an order of magnitude.
The Failure Modes Nobody Mentions
Documentation tells you how things work when they work. The interesting part is when they break. Here's what I've seen happen in production:
Fail2ban silent regex breakage. Twice in 2024, an Ubuntu security update changed the format of a log line just slightly β an extra field added, a timestamp format adjusted β and my Fail2ban regex stopped matching. The jail kept running, the logs kept rolling in, and Fail2ban dutifully reported zero failures. I only caught it because abuse reports started showing up in my abuse@ inbox for IPs that should have been long banned. The fix is to set up a meta-monitor (fail2ban-client status sshd piped to a metrics endpoint and alerted on if banned count flatlines), but most tutorials skip this entirely. Cost: roughly 6 hours of cleanup including rotating SSH keys on three machines as a precaution.
CrowdSec API outage during community blocklist refresh. Once in 2025 the central API was slow to respond for about 40 minutes. The local instance kept enforcing decisions but couldn't pull updates. No outage on my end β local detection kept working β but I noticed log warnings and got mildly nervous. Documentation says local-first design means this is by design, and that matched my observation: not a real failure mode for a paranoid operator, just a yellow light.
Wazuh indexer running out of disk. This one cost me a real Sunday. The Wazuh indexer keeps everything by default with no rotation policy applied, and a busy host can write 10-50 GB of indices per week. On a 50 GB VPS, that's a problem in roughly two months. The fix is to apply an Index State Management (ISM) policy that rolls indices over and deletes anything older than 30-90 days. The Wazuh docs cover this, but the default install doesn't apply it for you, and there's no warning in the UI when you're 90% full. Set up disk alerting before you set up Wazuh, not after.
What I Run On Each Machine, And Why
This is the section that tends to be most useful for people in similar shoes β small operators with multiple boxes and limited time.
Aggregator sites (7 of them on Hostinger shared/Premium and one VPS): CrowdSec with the community blocklist, plus the WordPress, nginx, and Laravel collections. The shared-hosting boxes use the CrowdSec Cloudflare bouncer (since I can't install nftables on shared hosting β Cloudflare blocks at the edge instead). Total monthly cost: $0 for the OSS, $0 for community blocklist tier, plus Cloudflare's free plan. This setup catches roughly 90% of abuse before it touches the origin.
Client production VPS (about 12 active boxes): Same CrowdSec setup as above, plus Fail2ban running in parallel for SSH only as a belt-and-suspenders measure. Two layers of brute-force defense, slightly redundant, completely worth the extra 20 MB of RAM. Several clients have compliance reasons to keep Fail2ban specifically (it's the named tool in their existing policies), so I leave it.
One client running Wazuh: A regional fintech that needs file integrity monitoring and audit logging for compliance. They have a four-person internal IT team to read the dashboards. Wazuh is the right answer for them. They're on a 16 GB VPS dedicated to the manager and indexer, with about 20 agents reporting in. Their monthly infrastructure cost for Wazuh alone is about $24 (Hetzner CCX23). The compliance auditor specifically asked about Wazuh by name, which removed any debate about tooling.
My own homelab: Fail2ban only. Single-user network, Tailscale-only SSH, no public services. CrowdSec would be overkill, Wazuh would be absurd.
The Honest Cost Comparison for 2026
All three projects are open source. The cost differences come from infrastructure, time, and optional commercial features.
Fail2ban: Free, MIT-style license. Runs on anything. Total cost: zero infrastructure overhead.
CrowdSec: Core engine and bouncer are MIT-licensed. The community blocklist (around 5 million IPs as of early 2026) is free for personal and small business use. The premium blocklists (geo-targeted, sector-specific feeds, threat-intel integrations) are paid; CrowdSec lists pricing tiers starting around $40-$60/month for small-business plans, depending on how many machines and which feeds you want. For 90% of small operators, the free tier is more than enough.
Wazuh: Apache 2.0 license, free to self-host forever. Wazuh Cloud (managed) starts around $97/month per agent for the Pro tier as of early 2026, which gets expensive fast. A self-hosted single-node setup running on a $24/month VPS is the realistic minimum for production. Add another $5-10/month for offsite log archival to S3-compatible storage if you care about retention beyond what fits on the box.
How to Pick β Three Honest Heuristics
Here's how I'd talk you through the decision if you sent me a message about it.
Pick Fail2ban if: you have a single-purpose VPS (think: just Plex, just a game server, just a personal Mastodon instance), your attack surface is mostly SSH, you have less than 1 GB RAM to spare, or you specifically need a tool that's been audited and battle-tested for 20+ years. Don't pick it because you read a 2018 tutorial β pick it because the simplicity actually fits your situation.
Pick CrowdSec if: you run any public-facing web application, you want community-sourced threat intelligence that updates without you doing anything, you want time-windowed detection patterns rather than line-match regex, or you want a tool that integrates cleanly with Cloudflare, Caddy, nginx, and Traefik out of the box. This is my default recommendation in 2026 for anyone running websites on a VPS.
Pick Wazuh if: you need a real SIEM (file integrity, vulnerability detection, MITRE mapping, audit-quality logs), you have compliance pressure (PCI-DSS, HIPAA, SOC 2, ISO 27001), you have at least one person whose job partially involves reading security dashboards, and you can afford a 4-8 GB VPS dedicated to the manager. Wazuh isn't a Fail2ban replacement β it's a different tool that happens to overlap on the IP-blocking feature.
What I'd Do Differently If Starting Fresh Today
If I were spinning up a new VPS for a public-facing project tomorrow, here's the exact stack I'd build, in order:
- SSH key-only auth, port changed off 22 to something memorable like 2222 (security through obscurity is real-world useful, even if purists scoff).
- UFW with a default-deny inbound, opening only 2222, 80, 443.
- CrowdSec installed, community blocklist enrolled, firewall bouncer pushing blocks to nftables.
- Crowdsecurity collections for nginx, sshd, base-http, and whichever framework I'm running (laravel, wordpress, etc.).
- Cloudflare in front, with the CrowdSec Cloudflare bouncer pushing the worst offenders all the way to Cloudflare's edge so they never even hit my origin.
- Fail2ban for SSH only, as redundant defense β about 30 lines of config total.
- A simple uptime check (Uptime Kuma) hitting
cscli decisions listcount to alert me if the ban count drops to zero unexpectedly, which usually means the bouncer crashed.
That setup takes me about 90 minutes from a fresh VPS to fully protected, costs $0 in software, and has caught every single brute-force and scanner wave I've thrown at it across three years and seven sites. It's not exotic, it's not the most powerful option on the market, and it doesn't impress anyone at a security conference. It just works, scales to my workload, and lets me focus on the actual product instead of writing regex on a Saturday night.
Whatever you pick, the most important thing is to pick something and turn it on before you need it. The hours I lost cleaning up after that one exposed SSH window three years ago bought me the lesson I'm passing on. Don't repeat it.
Found this helpful?
Subscribe to our newsletter for more in-depth reviews and comparisons delivered to your inbox.