So you’ve set up your self-hosted services — maybe a WordPress site, an SSH server, or a WireGuard VPN. You’re feeling good. But somewhere out there, bots are already hammering your server with thousands of login attempts per hour. If that thought makes you slightly uneasy, good — it should. This is where Fail2Ban comes in.
Fail2Ban is a lightweight intrusion-prevention tool that monitors your server’s logs for suspicious activity and automatically bans offending IP addresses using firewall rules. It’s free, open-source, and takes about 15 minutes to set up. Once it’s running, it quietly does its job in the background — like a very patient bouncer at the door of your server.
In this guide, I’ll walk you through installing Fail2Ban on Ubuntu, configuring it to protect SSH (the most common attack vector), and customizing it to protect other services. Let’s go.
What You’ll Need
- A running Ubuntu server (20.04, 22.04, or 24.04 all work)
- SSH access with sudo privileges
- About 15 minutes
Step 1: Install Fail2Ban
First, update your package list and install Fail2Ban from Ubuntu’s repositories:
sudo apt update
sudo apt install fail2ban -y
Once installed, verify the service is running:
sudo systemctl status fail2ban
You should see active (running) in green. If it’s not running, start and enable it:
sudo systemctl enable --now fail2ban
Step 2: Create Your Local Configuration
Here’s a critical rule that trips up most newcomers: never edit /etc/fail2ban/jail.conf directly.
That file gets overwritten every time Fail2Ban is updated. Instead, you create a jail.local file that overrides the defaults without touching the original:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
Find the [DEFAULT] section and update these key values:
[DEFAULT]
# Ban IPs for 10 minutes (600 seconds)
bantime = 10m
# Look back over the last 10 minutes for failures
findtime = 10m
# Ban after 5 failed attempts
maxretry = 5
# Use ufw (Uncomplicated Firewall) — perfect for most Ubuntu setups
banaction = ufw
# Your email for notifications (optional but recommended)
# Change "root@localhost" to your real email
# Then set action = %(action_mwl)s below
destemail = root@localhost
sender = [email protected]
action = %(action_)s
A few notes on these values:
- bantime: How long an IP stays banned. Start with 10 minutes. If you're seeing repeat offenders, bump this to 1h or even 24h.
- findtime: The time window Fail2Ban checks for failures. If an IP accumulates
maxretryfailures within this window, it gets banned. - maxretry: The threshold. 5 is reasonable for SSH — it lets you fat-finger your password a few times without locking yourself out.
If you run ufw (Ubuntu's default firewall), set banaction = ufw. If you prefer raw iptables, you can leave it at the default iptables-multiport.
Step 3: Enable SSH Protection
Scroll down in jail.local to the [sshd] section and make sure it's enabled:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 10m
This tells Fail2Ban to watch /var/log/auth.log for failed SSH login attempts. When an IP hits 5 failures within 10 minutes, it gets banned for 10 minutes. Simple and effective.
If you've changed your SSH port from the default 22 (which I recommend), update the port line accordingly:
port = 2222
Step 4: Restart and Verify
Restart Fail2Ban to apply your changes:
sudo systemctl restart fail2ban
Now check that the SSH jail is active:
sudo fail2ban-client status sshd
You should see output like:
Status for the jail: sshd |- Filter | |- Currently failed: 0 | |- Total failed: 0 | `- File list: /var/log/auth.log `- Actions |- Currently banned: 0 |- Total banned: 0 `- Banned IP list:That means Fail2Ban is watching. Let's see if it's actually working.
Step 5: Test It (Optional but Fun)
From another machine (or another terminal session if you're feeling adventurous), deliberately fail SSH logins:
ssh wronguser@your-server-ip # Enter wrong password 5+ timesThen check the jail status again:
sudo fail2ban-client status sshdYou'll see your test IP in the banned list. To unban it manually:
sudo fail2ban-client set sshd unbanip YOUR_IPStep 6: Protect Other Services
Fail2Ban comes with filters for dozens of services. Here are two common ones for self-hosters:
Nginx (protect your web server)
Create a custom filter for nginx at
/etc/fail2ban/filter.d/nginx-login.conf:[Definition] failregex = ^.* "(GET|POST) .*" (401|403|404) .* Then add a new jail section in your
jail.local:[nginx-login] enabled = true port = http,https filter = nginx-login logpath = /var/log/nginx/access.log maxretry = 10 findtime = 60 bantime = 3600Protect Against Nginx Bot Abuse
For blocking bots that scan for common vulnerabilities:
[nginx-botsearch] enabled = true port = http,https filter = nginx-botsearch logpath = /var/log/nginx/access.log maxretry = 2 bantime = 86400After adding new jails, restart Fail2Ban:
sudo systemctl restart fail2banCommon Pitfalls
1. Locking yourself out
This is the #1 fear, and it's valid. Before enabling Fail2Ban on SSH, make sure you have console access (VPS providers like DigitalOcean, Linode, and Vultr offer a web console). You can also whitelist your home IP:
[DEFAULT] ignoreip = 127.0.0.1/8 ::1 YOUR_HOME_IPPut your trusted IPs here and they'll never get banned, no matter how many failed attempts.
2. Editing jail.conf instead of jail.local
I mentioned this above, but it bears repeating: your changes will vanish on the next update. Always use
jail.local.3. Log file location mismatch
If you're running Ubuntu 24.04 with
systemd-journald, authentication logs might be in the journal instead of/var/log/auth.log. Check with:sudo journalctl -u sshd --no-pager | tail -20If that's your log source, set
backend = systemdin the[sshd]jail config.4. UFW not enabled
If you set
banaction = ufwbut UFW isn't active, bans won't work. Check with:sudo ufw statusIf it's inactive, enable it (carefully — make sure your SSH port is allowed first!):
sudo ufw allow ssh sudo ufw enableUseful Commands Cheat Sheet
# Check overall status sudo fail2ban-client status # Check a specific jail sudo fail2ban-client status sshd # Unban an IP sudo fail2ban-client set sshd unbanip 192.168.1.100 # Ban an IP manually sudo fail2ban-client set sshd banip 192.168.1.100 # View Fail2Ban logs sudo tail -f /var/log/fail2ban.logWhat You've Accomplished
In about 15 minutes, you've turned your server from an open door into something with actual security. Fail2Ban will now:
- Monitor your logs in real-time
- Automatically ban IPs that brute-force your SSH
- Protect your web services from bots and scanners
- Free up resources that were being wasted on junk traffic
It's not a silver bullet — you should still use SSH keys instead of passwords, keep your software updated, and follow other security best practices. But Fail2Ban is one of the highest-impact, lowest-effort improvements you can make. It's the seatbelt of server security: simple, and it saves you when things go wrong.
Your future self, the one who's not debugging a compromise at 3 AM, will thank you.
Leave a Reply