Guide VPS & Servers

How to set up Fail2ban

Installing Fail2ban to automatically block repeated failed logins, configured safely so you do not end up banning yourself.

Updated 8 min read Intermediate

Fail2ban watches your server's log files for repeated failed login attempts and, once a threshold is crossed, temporarily blocks the offending IP address at the firewall. It is a defensive tool that reduces automated background noise against SSH and any other service you expose — it does not replace key-based login or a properly configured firewall, it complements both.

Install it

sudo apt install fail2ban -y      # Ubuntu / Debian
sudo dnf install fail2ban -y      # RHEL / Rocky / AlmaLinux
sudo systemctl enable --now fail2ban

Always configure jail.local, never jail.conf directly

Fail2ban ships a default configuration in /etc/fail2ban/jail.conf. Do not edit that file — it is overwritten whenever the package updates, silently taking your changes with it. Instead, create jail.local, which Fail2ban reads afterwards and which takes precedence over anything in jail.conf:

sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

What each setting controls:

  • bantime — how long an offending IP stays blocked. 1h is one hour; use -1 for a permanent ban, which is rarely a good idea on a dynamic IP address that could later belong to someone innocent.
  • findtime — the window within which failures are counted toward the threshold.
  • maxretry — how many failures within findtime trigger a ban.
  • ignoreip — addresses Fail2ban never bans, regardless of failures. Add your own static IP address here if you have one, so a mistyped password during testing cannot lock you out of your own server.

Apply the configuration:

sudo systemctl restart fail2ban

Check it is actually working

sudo fail2ban-client status

Lists the active jails. Check a specific one for its current ban count and banned IP list:

sudo fail2ban-client status sshd

Unbanning an IP address

If you, or someone you did not intend to block, ends up banned — most commonly from testing your own login and getting the password wrong too many times — unban it directly:

sudo fail2ban-client set sshd unbanip 203.0.113.10
Test from a session you know is safe

While setting this up, keep one working SSH session open and add your own IP address to ignoreip before testing anything that might trigger a ban. Testing failed logins from the only connection you have to the server is how people end up needing the console recovery process covered in what to do when you are locked out of your VPS.

Adding jails for other services

Fail2ban ships filters for many common services beyond SSH — enable whichever you are actually running by adding a matching section to jail.local. For a website with a login form protected by Nginx or Apache, for example:

[nginx-http-auth]
enabled = true

[apache-auth]
enabled = true

Only enable a jail for a service that is actually installed and logging in the format that jail expects — an enabled jail with no matching log file to watch does nothing useful and can generate errors in Fail2ban's own log.

Reading what Fail2ban itself is doing

sudo tail -f /var/log/fail2ban.log

This is worth watching for a few minutes after first setting up a new jail, to confirm it is actually parsing the target log file correctly rather than silently matching nothing.

What actually happens when an IP is banned

Fail2ban does not intercept traffic itself — it watches logs, and when a jail's threshold is crossed, it inserts a rule into the server's own firewall (iptables, nftables, or ufw/firewalld depending on your setup) that drops traffic from that address. This is why Fail2ban needs to run as root, and why a ban is enforced at the network layer rather than by the service being protected — SSH itself never even sees the connection attempt from a banned address once the rule is in place.

Choosing sensible thresholds

The defaults above are a reasonable starting point, but tune them to your own risk tolerance:

  • A lower maxretry catches automated scanning faster but increases the chance of banning a legitimate user who mistypes a password a few times in a row.
  • A longer bantime is more of a deterrent but risks blocking a legitimate, dynamically-assigned IP address for longer than the actual threat justified.
  • Fail2ban also supports escalating repeat offenders to progressively longer bans using its bantime.increment setting, which rewards persistent scanners with longer blocks each time without needing you to tune a single fixed value for every scenario.

What Fail2ban does not do

It does not stop a targeted, low-and-slow attack that stays under the failure threshold, and it does not protect a service that is vulnerable rather than merely guessable. Treat it as one layer among several — alongside key-based SSH login, a properly scoped firewall (see setting up a firewall on your VPS), and keeping the system patched (see securing a new Linux server) — rather than a single fix for server security on its own.

Related reading