Skip to content

How to Install and Configure Fail2Ban on a Linux Server

7 min read

Applies to: Fail2Ban 1.1.0 (Debian 13, Ubuntu 26.04, AlmaLinux 10 from EPEL) and Fail2Ban 1.0.2 (Ubuntu 24.04)

Fail2Ban is a free, open-source tool that watches your server's logs for repeated failed logins and blocks the IP addresses behind them with a firewall rule for a set time. Its best-known use is stopping SSH password-guessing bots: after, say, five wrong passwords in ten minutes, the IP cannot reach SSH for an hour. Install it with apt install fail2ban (Debian, Ubuntu) or from EPEL with dnf install fail2ban (AlmaLinux, Rocky Linux), put your settings in /etc/fail2ban/jail.local, and check it with fail2ban-client status sshd.

The Fail2Ban project itself points out that it reduces the rate of password guessing but cannot make weak passwords safe. Use it together with SSH keys, not instead of them.

How Fail2Ban works

  • Jail: one protected service, such as sshd. A jail combines a filter and an action.
  • Filter: patterns that recognise a failed login in the log. Fail2Ban ships filters for SSH, Apache, Nginx, Postfix, Dovecot, vsftpd and many more in /etc/fail2ban/filter.d/.
  • Action: what to do with a banned IP, usually a firewall rule (nftables, iptables, firewalld or UFW).
  • maxretry, findtime, bantime: an IP is banned after maxretry failures within findtime, for bantime. The built-in defaults are 5 failures, 10 minutes and a 10-minute ban.
  • backend: where Fail2Ban reads from: a log file, or the systemd journal (backend = systemd).

Step 1: Install Fail2Ban

Ubuntu and Debian:

sudo apt update
sudo apt install fail2ban

On Debian 13, Ubuntu 24.04 and Ubuntu 26.04 the package already turns on the SSH jail. Its file /etc/fail2ban/jail.d/defaults-debian.conf enables [sshd], reads SSH failures from the systemd journal and bans with nftables. The package also starts the service and enables it at boot. Check that it runs:

sudo systemctl status fail2ban
sudo systemctl enable --now fail2ban   # only if it is not running

AlmaLinux and Rocky Linux (from the EPEL repository):

sudo dnf install epel-release
sudo dnf install fail2ban
sudo systemctl enable --now fail2ban

On AlmaLinux 10 this installed Fail2Ban 1.1.0 together with fail2ban-firewalld and firewalld itself. That package sets banaction = firewallcmd-rich-rules, so bans only work while firewalld is running. Unlike Debian and Ubuntu, no jail is enabled after installing and the service is disabled, so you must do step 2 before it protects anything. If you start firewalld for the first time, open your other ports first: see how to open a port in firewalld.

Step 2: Create jail.local

Do not edit jail.conf: the file itself says it will probably be overwritten in a distribution update. Fail2Ban reads jail.conf, then jail.d/*.conf, then jail.local, then jail.d/*.local, and later files win. Create /etc/fail2ban/jail.local with only the settings you want to change:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
# never ban these (your office IP, monitoring)
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

[sshd]
enabled  = true
maxretry = 3
  • ignoreip takes IP addresses and CIDR ranges, separated by spaces. Add your own fixed IP so a few mistyped passwords cannot lock you out.
  • Times are seconds or abbreviations such as 10m, 1h, 1d and 1w. Months are mo, because m means minutes.
  • Custom SSH port: if SSH listens on another port, add port = 2222 under [sshd]. In our test the nftables rule changed from tcp dport 22 to tcp dport 2222. Without it, Fail2Ban bans the wrong port. (Changing the port: the default SSH port and how to change it safely.)
  • Repeat offenders: bantime.increment = true makes each new ban of the same IP longer (by default 1, 2, 4, 8 times the bantime and so on, according to the comments in jail.conf). Fail2Ban keeps its bans in a database and restored them after a restart in our test (Restore Ban 203.0.113.77 in the log).

Do not add a logpath for SSH on these systems. Debian, Ubuntu and AlmaLinux packages already read SSH failures from the journal.

Step 3: Test the configuration and restart

$ sudo fail2ban-client -t
OK: configuration test is successful
$ sudo systemctl restart fail2ban

Small changes can also be applied with sudo fail2ban-client reload.

Step 4: Check bans with fail2ban-client

Lab example (test container, four failed root logins from a documentation IP with maxretry = 3):

$ sudo fail2ban-client status
Status
|- Number of jail:	1
`- Jail list:	sshd
$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed:	2
|  |- Total failed:	6
|  `- File list:	/var/log/auth.log
`- Actions
   |- Currently banned:	1
   |- Total banned:	1
   `- Banned IP list:	203.0.113.50

Our lab read a log file because the container has no systemd journal. With the journal backend on a real server, the last filter line is Journal matches instead of File list, according to the Fail2Ban source code. sudo fail2ban-client banned lists bans for all jails at once: [{'sshd': ['203.0.113.50']}].

The ban itself is a firewall rule. On Debian and Ubuntu, Fail2Ban adds its own nftables table:

$ sudo nft list ruleset
table inet f2b-table {
	set addr-set-sshd {
		type ipv4_addr
		elements = { 203.0.113.50 }
	}

	chain f2b-chain {
		type filter hook input priority filter - 1; policy accept;
		tcp dport 22 ip saddr @addr-set-sshd reject with icmp port-unreachable
	}
}

This table is separate from UFW's rules. If you would rather manage bans as UFW rules, Fail2Ban ships a ufw action: set banaction = ufw in [DEFAULT] and each ban is added with a ufw command. With firewalld (AlmaLinux and Rocky), bans are rich rules: sudo firewall-cmd --list-rich-rules.

Step 5: Unban or ban an IP

$ sudo fail2ban-client set sshd unbanip 203.0.113.50
1
$ sudo fail2ban-client unban 198.51.100.23
1
$ sudo fail2ban-client set sshd banip 198.51.100.23
1
  • set sshd unbanip removes the ban from one jail; unban removes it from every jail. The 1 means one IP was unbanned; 0 means it was not banned.
  • fail2ban-client set sshd addignoreip 198.51.100.0/24 whitelists a range at once, but only until the next reload or restart: after reload it was gone in our test. Put permanent entries in ignoreip in jail.local.
  • Locked out of your own server? Connect from another network or use the server console (the VPS panel's console, or IPMI on a dedicated server), then unban your IP and add it to ignoreip.

Common problems

  • "Have not found any log file for sshd jail" and Fail2Ban will not start: the jail is told to read /var/log/auth.log, but the system logs to the journal only (Debian 12 and 13 do not install rsyslog by default). We got this error by setting backend = auto under [sshd] on Debian 13. Remove that override so the package default backend = systemd applies, or install rsyslog.
  • Warning "'allowipv6' not defined in 'Definition'. Using default one: 'auto'" on Ubuntu 24.04 (Fail2Ban 1.0.2): it is only a warning. It disappeared in our test after creating /etc/fail2ban/fail2ban.local with the two lines [Definition] and allowipv6 = auto. Fail2Ban 1.1.0 on Debian 13 and Ubuntu 26.04 did not show it.
  • Nothing gets banned on AlmaLinux: check that the [sshd] jail is enabled in jail.local and that firewalld is running (sudo firewall-cmd --state).
  • Check a filter against a log: sudo fail2ban-regex /var/log/auth.log sshd shows how many lines matched (our lab log: Lines: 10 lines, 0 ignored, 10 matched, 0 missed).

Other jails worth knowing

  • recidive: reads Fail2Ban's own log and bans IPs that keep getting banned, across all ports (defaults in jail.conf: findtime = 1d, bantime = 1w). Enable it with [recidive] and enabled = true.
  • Web and mail: filters such as nginx-http-auth, apache-auth, postfix and dovecot are included. Enable only the jails for services you really run.
  • cPanel servers: cPanel has its own protection, cPHulk, which according to cPanel watches SSH, cPanel, WHM, mail and Pure-FTPd logins. Use cPHulk there rather than adding Fail2Ban on top.

Fail2Ban works on any Ucartz KVM VPS or dedicated server with root access. If you would rather have it set up as part of a full hardening job, see Linux server management.

Related articles: how to set up SSH keys for authentication, how to disable root login via SSH, how to set up the UFW firewall on Ubuntu, useful firewall-cmd examples.

Official documentation: Fail2Ban on GitHub, jail.conf(5) manual.

Was this answer helpful?

Still stuck? Open a ticket