What the Ubuntu package installs
On Ubuntu 22.04 apt installs fail2ban 0.11.2; on 24.04 it installs 1.0.2. Both ship the sshd jail already enabled through /etc/fail2ban/, so the package starts counting failed SSH logins before you edit a single file. The service is called fail2ban.service and it runs as root.
/etc/fail2ban/jail.confholds the package defaults and is replaced on upgrade./etc/fail2ban/enablesjail.d/defaults- debian.conf [sshd]withbackend = systemd./etc/fail2ban/jail.localis yours; it survives upgrades and overrides both files above./etc/fail2ban/holds the regex that recognises a failed password.filter.d/sshd. conf /var/log/fail2ban.logrecords every ban and unban, andjournalctl -u fail2banmirrors it.
The service reads configuration from four places in a fixed order: jail.conf, jail.d/*.conf, jail.local, then jail.d/*.local. Later files win, which is why every change below goes into a local file rather than the shipped one.
Install fail2ban and confirm the service
The package sits in the Ubuntu main repository on both releases, so no PPA or third-party source is needed. Four commands take you from a new server to a jail that is provably running.
- Run
sudo apt update, thensudo apt install fail2ban. The post-install script enables and starts the unit. - Check
sudo systemctl status fail2banfor Active: active (running) and a Python main PID. - Run
sudo fail2ban-client status. The Jail list line should already readsshd. - Read the last twenty lines of
sudo journalctl -u fail2ban. A healthy start logs the jail count, not a traceback.
If the status shows inactive, run sudo systemctl enable --now fail2ban. A start that dies after a second usually means a syntax error in a file you already edited, and sudo fail2ban-client -t names the file and line.
jail.local versus jail.conf: edit the file that survives
Never edit jail.conf. apt replaces that file on every fail2ban upgrade, and your jails vanish at the next unattended-upgrades run without an error message. Put only the lines you change in jail.local, and comment why each value was chosen.
The local file does not have to copy the whole default. fail2ban merges it over the package file, so three or four lines are enough for a working override. If you prefer per-service files, /etc/fail2ban/ behaves the same way and keeps the override next to the jail it changes.
Test before you restart. sudo fail2ban-client -t parses every file and exits with OK: configuration test is successful. Then apply the change with sudo systemctl restart fail2ban and confirm the jail is still listed in sudo fail2ban-client status.
Configure the sshd jail for port 22 or a custom port
The shipped jail reads the systemd journal, matches failed password and invalid user lines, and bans on the port it detects. You only need an override when a value differs from that default.
enabled = trueis kept explicit so a future change todefaults-debian.confcannot switch the jail off silently.port = sshis correct for 22. Replace it with the number when sshd listens elsewhere, for exampleport = 2222.backend = systemdreads the journal on both releases and needs no log file on disk.maxretry,findtimeandbantimeinside the jail override the[DEFAULT]block for SSH only.ignoreiplists the addresses that must never be banned, and it belongs under[DEFAULT].
Everything you do not list is inherited, so a correct [sshd] block is four lines plus your ban values. After the restart, sudo fail2ban-client status sshd should print Filter: sshd, the port, and an empty banned list.
Pick bantime, findtime and maxretry values
The three values work together: maxretry failures inside findtime trigger a ban that lasts bantime. Ubuntu ships five attempts, ten minutes and a ten-minute ban, which is short enough that a bot simply waits and retries.
| Setting | Ubuntu default | Web server preset | What it controls |
|---|---|---|---|
| maxretry | 5 | 3 | Failed attempts allowed inside the window |
| findtime | 10m | 10m | Period in which those failures must happen |
| bantime | 10m | 1h, then 1d | How long the address stays blocked |
| ignoreip | 127.0.0.1/8 ::1 | plus your office IP | Addresses exempt from every jail |
Units are m, h, d and w, and a bare number means seconds. Reserve bantime = -1 for an address you are certain about, because a permanent ban has to be lifted by hand from a console.
Repeat offenders deserve their own jail. The packaged [recidive] jail watches the fail2ban log itself and bans any address banned three times in a day, so enable it in jail.d/recidive.local with bantime = 1w and a longer findtime.
Test a ban and unban an IP with fail2ban-client
Do not test with your own login. Ban the documentation address 198.51.100.7, confirm it appears in the list, then remove it. The check takes four commands and cannot lock you out.
- Run
sudo fail2ban-client status sshdand note Currently banned, Total banned and the Banned IP list. - Ban the test address with
sudo fail2ban-client set sshd banip 198.51.100.7. The command echoes the address when the action ran. - Run the status command again. The list now holds 198.51.100.7, and
sudo iptables -S f2b-sshdshows the matching rule; on a host without the iptables binary usesudo nft list ruleset | grep f2b. - Remove it with
sudo fail2ban-client set sshd unbanip 198.51.100.7and confirm the list is empty again.
To release your own address after a real ban, the same command works from a second session or the provider console: sudo fail2ban-client set sshd unbanip 203.0.113.10. If SSH already refuses the connection, the web console is the only way in, and sudo fail2ban-client unban --all clears every jail at once.
UFW, cloud firewalls and key-only SSH
fail2ban and ufw both write to the host firewall and they do not fight. fail2ban creates its own chain, f2b-sshd, and hooks it into INPUT; ufw keeps its rules in ufw-before-input. A packet is dropped by whichever rule it reaches first.
The default ban action is iptables-multiport, so bans do not appear in sudo ufw status. When ufw is your single view of the firewall, add banaction = ufw under [DEFAULT], restart, and every ban becomes a numbered ufw rule you can delete by hand.
A cloud firewall or a proxy CDN changes the picture. Traffic is filtered or forwarded before it reaches the instance, so fail2ban sees the proxy address or sees nothing, and a ban on the VM never reaches the provider edge. Keep the provider security group for the ports you expose and let fail2ban handle repeat offenders at the host.
Key-only SSH removes most of the value of guessing, but the attempts still arrive. Set PasswordAuthentication no and PermitRootLogin prohibit-password in a file under /etc/ssh/sshd_config.d/, reload sshd, and fail2ban's job shrinks to cutting log noise and CPU cost.
Common mistakes, starting with banning yourself
Six problems account for almost every failed fail2ban setup on Ubuntu. Match the symptom in the left column, apply the fix in the right, and retest before touching anything else.
| Symptom | Cause | Fix |
|---|---|---|
| SSH hangs or refuses your address | A burst of failed logins banned your admin IP | Unban from the console, then add the address to ignoreip |
| Jail changes vanish after an upgrade | Edits were written into jail.conf | Move them to jail.local or jail.d/*.local |
| Have not found any log file for sshd jail | 24.04 minimal has no rsyslog, so there is no auth.log | Keep backend = systemd and install python3-systemd |
| status lists no jails at all | File saved but the service was never restarted | fail2ban-client -t, then systemctl restart fail2ban |
| No bans for SSH on port 2222 | The jail still watches port ssh | Add port = 2222 under [sshd] |
| Failed to execute ban jail action | iptables binary missing on a minimal image | apt install iptables, or set banaction = nftables |
The self-ban is the one that costs an afternoon. Before you enable the jail, open a second SSH session, add your office address to ignoreip, and leave the provider console tab open until a test ban and a test unban have both worked.
Where fail2ban belongs in a WebJi VPS setup
fail2ban needs root, a systemd unit and its own firewall chain, so it belongs on a server you control rather than on shared hosting. A WebJi® VPS server gives you that root access, and a Linux VPS is the usual home for one site plus this jail.
Plans are quoted by email at support@webji.services before payment, in INR before 18% GST. Support answers in Hindi and English, 24/7 by email, with an average first reply under 60 minutes. If a ban has locked you out of a panel-managed server instead, our guide to unblocking an IP in cPanel covers that firewall, and the contact page reaches the team directly.
Frequently Asked Questions
How do I install fail2ban on Ubuntu 22.04 or 24.04?
Run sudo apt update and sudo apt install fail2ban. The package is in the Ubuntu main repository on both releases, and the post-install script enables and starts fail2ban.service. Confirm with systemctl status fail2ban, then run sudo fail2ban-client status to see the sshd jail already loaded.
Is the sshd jail enabled by default after install?
Yes. Ubuntu ships /etc/fail2ban/jail.d/defaults-debian.conf with [sshd] enabled = true and backend = systemd, so failed SSH logins are counted as soon as the service starts. Check the Jail list line in sudo fail2ban-client status before you change anything.
Should I edit jail.conf or jail.local?
Edit jail.local, never jail.conf. fail2ban reads jail.conf, then jail.d/*.conf, then jail.local, then jail.d/*.local, and later files win. apt replaces jail.conf on upgrade, so anything you wrote there is lost. Put only your overrides in jail.local and test them with sudo fail2ban-client -t.
What are good bantime, findtime and maxretry values for SSH?
Use maxretry = 3, findtime = 10m and bantime = 1h to start, then raise bantime to 1d once you know your own addresses are in ignoreip. Ubuntu defaults to 5 attempts and a 10-minute ban, which a bot that retries for hours barely notices.
How do I unban my own IP in fail2ban?
From a second session or the provider console, run sudo fail2ban-client set sshd unbanip 203.0.113.10, or sudo fail2ban-client unban --all to clear every jail. Add the address to ignoreip in jail.local so the same mistake cannot repeat.
Does fail2ban work with UFW?
Yes, and they do not conflict: fail2ban builds its own f2b-sshd chain inside INPUT while ufw uses ufw-before-input. The default ban action is iptables-multiport, so bans do not show in ufw status. Set banaction = ufw in jail.local if you want every ban as a numbered ufw rule.
Why does fail2ban say it found no log file for the sshd jail?
A minimal Ubuntu 24.04 image has no rsyslog, so /var/log/auth.log does not exist. Keep backend = systemd, which reads the journal instead, and install python3-systemd if the journal socket cannot be opened. Ubuntu 22.04 usually has rsyslog, so the file is there.

