TL;DR
Complete guide to installing and configuring fail2ban on Ubuntu and Debian covering SSH jails, nginx jails, custom filters, and operational management.
Key facts
- Topology
- Fail2ban on Ubuntu/Debian
TL;DR
fail2ban watches your log files for repeated authentication failures and automatically bans offending IP addresses using iptables or UFW. It is the simplest effective defence against brute-force attacks on SSH, web applications, and mail servers. This guide covers installation, jail configuration, custom filters, and day-to-day management.
Installation
sudo apt update && sudo apt install -y fail2ban
fail2ban starts automatically. Verify it is running:
sudo systemctl status fail2ban
Configuration structure
Never edit /etc/fail2ban/jail.conf directly — it gets overwritten on updates. Create a local override:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
All customisations go in jail.local or in individual files under /etc/fail2ban/jail.d/.
SSH jail customisation
The SSH jail is enabled by default. Tune it for your environment in /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = ssh,2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600
banaction = ufw
- maxretry: ban after 5 failed attempts
- findtime: within a 10-minute window
- bantime: ban for 1 hour (use
-1for permanent) - banaction: use
ufwif UFW is your firewall, otherwiseiptables-multiport
Restart after changes:
sudo systemctl restart fail2ban
Nginx jails
Protect your web server against common attack patterns.
nginx-http-auth — bans IPs that fail HTTP basic authentication:
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600
nginx-botsearch — bans bots probing for common vulnerability paths (wp-admin, phpmyadmin, etc.):
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400
Custom filters for application brute force
Create a custom filter for your application's login endpoint. First, define the filter in /etc/fail2ban/filter.d/app-login.conf:
[Definition]
failregex = ^<HOST> -.*"POST /login HTTP.*" 401
ignoreregex =
Then create the jail in /etc/fail2ban/jail.d/app-login.conf:
[app-login]
enabled = true
port = http,https
filter = app-login
logpath = /var/log/nginx/access.log
maxretry = 10
findtime = 300
bantime = 1800
Test the filter against your log file before enabling:
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/app-login.conf
Whitelisting IPs
Prevent your own office or monitoring IPs from being banned:
# /etc/fail2ban/jail.local — under [DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10 198.51.100.0/24
Operational commands
# Check status of all jails
sudo fail2ban-client status
# Check a specific jail
sudo fail2ban-client status sshd
# Manually ban an IP
sudo fail2ban-client set sshd banip 192.0.2.50
# Unban an IP
sudo fail2ban-client set sshd unbanip 192.0.2.50
# Check which IPs are currently banned
sudo fail2ban-client get sshd banned
Email notifications
Configure fail2ban to send email alerts on bans. In /etc/fail2ban/jail.local:
[DEFAULT]
destemail = admin@example.com
sender = fail2ban@example.com
mta = sendmail
action = %(action_mwl)s
The action_mwl action sends an email with the whois lookup and relevant log lines.
Log monitoring
Review fail2ban's own logs to verify it is working:
sudo tail -50 /var/log/fail2ban.log
Look for Ban and Unban entries to confirm jails are triggering as expected.
With Reflex
Reflex integrates with fail2ban to provide a centralised view of banned IPs across your entire fleet, alerts on unusually high ban rates that may indicate a coordinated attack, and tracks jail health so you know immediately if fail2ban stops running. See How it works.