HostleloBlogExplore hosting

Protect Your VPS from SSH Brute Force with fail2ban

Install fail2ban on Ubuntu or Debian, enable the sshd jail in jail.local, prove it works with a safe test ban, and learn how to unban yourself fast.

On this page

The short answer

Install fail2ban with apt, create /etc/fail2ban/jail.local with an [sshd] section that says enabled = true, and reload with sudo fail2ban-client reload. By default an IP that fails 5 logins within 10 minutes is banned for 10 minutes, and you can tune that. Add your own IP to ignoreip, keep one SSH session open while testing, and use sudo fail2ban-client set sshd unbanip <IP> if you ban yourself.

Yes, you can stop most SSH password guessing on a small VPS in about 20 minutes with fail2ban. You install it, turn on its sshd jail in a file called jail.local, and it starts blocking any IP address that fails to log in too many times. The out-of-the-box rule is simple: 5 failures within 10 minutes earns a 10 minute ban.

Here is the part that surprises most new VPS owners: the default OpenSSH server setting for PasswordAuthentication is yes. So unless you or your provider changed it, anyone on the internet can keep trying passwords against your server, and many people do, all day long.

By the end of this guide you will have fail2ban installed, the SSH jail enabled and tested, and you will know exactly how to unban yourself if you trip it by accident.

What fail2ban actually is

fail2ban is a small program that reads your log files, looks for patterns like "failed password", and tells your firewall to block the IP address behind them for a while. A "jail" is one rule set: which log to watch, which pattern counts as a failure, and what to do about it.

Think of it like a doorman. He does not change the lock. He just notices the person who tried the wrong key five times and asks them to wait outside for a while.

Why this matters: fail2ban does not make a weak password strong. It slows attackers down and cuts the noise in your logs. The real fix for SSH is key login, which I cover in setting up SSH key login. Use both together.

Before you start

Run through this list first. It saves you from the classic "I locked myself out" evening.

  • A VPS running Ubuntu or Debian, with root or sudo access over SSH.
  • Your provider's web console (sometimes called VNC or serial console) login. This is your back door if SSH stops answering you.
  • Your own public IP address. Search "what is my IP" in a browser, or ask your router. In this guide I use 203.0.113.25 as the example.
  • A second device on a different network for the test ban, like a phone on mobile data with an SSH app. Optional, but nice.
  • About 20 to 30 minutes.
  • Risk level: low to medium. The main risk is banning yourself, and every step below has a way out.

Heads up: keep your current SSH session open for the whole guide. A ban blocks new connections from your IP, and you want one working session left to undo mistakes. Open a second terminal for testing instead of closing the first one.

If you are still picking a server, my guide on choosing a VPS plan for your workload helps. fail2ban itself is light, so it runs fine on the smallest plans.

Set up fail2ban for SSH, step by step

All commands below run on the VPS over SSH. If you are logged in as root, you can drop the sudo part.

Step 1: Update the package list and install fail2ban

This updates your package lists and installs fail2ban from your distribution's own repository.

sudo apt update
sudo apt install fail2ban

The official fail2ban install notes for Debian and Ubuntu say the service starts automatically after install. You should see apt finish without errors.

This prints the installed version, which proves the client works.

sudo fail2ban-client version

At the time of writing (16 October 2026), the newest upstream release on GitHub is fail2ban 1.1.1, released on 15 August 2026. Your distribution may ship an older version. For example, Debian 12 (bookworm) packages 1.0.2. That is fine for this guide, because the settings we use exist in both.

Quick tip: the fail2ban project says to always use fail2ban-client to control it. Do not start fail2ban-server by hand.

Step 2: Check which port SSH really uses

fail2ban needs to block the port SSH actually listens on. The OpenSSH default is port 22, but some providers or past you may have changed it.

This asks the SSH server to print its effective settings, filtered to the port line.

sudo sshd -T | grep -i '^port'

You should see something like port 22. If you see another number, such as port 2222, write it down. You will need it in Step 4.

Why this matters: if fail2ban bans port 22 but SSH listens on 2222, the attacker is "banned" from a door they never used. Nothing breaks, but nothing is protected either.

Step 3: Back up and look at the default config

fail2ban keeps its defaults in /etc/fail2ban/jail.conf. The top of that file says, in capital letters, "YOU SHOULD NOT MODIFY THIS FILE." The reason is that package updates can overwrite it. Your own changes go in jail.local instead.

This copies the whole config folder to a dated backup, so you can always compare or roll back.

sudo cp -a /etc/fail2ban /etc/fail2ban.backup-$(date +%F)

You should now have a folder like /etc/fail2ban.backup-2026-10-16. Check it with ls /etc/ | grep fail2ban.

If a jail.local already exists (some providers ship one), read it before you change anything.

sudo cat /etc/fail2ban/jail.local

If the file does not exist, good. You will create it in the next step.

Heads up: do not copy all of jail.conf into jail.local. The fail2ban manual says .local files should contain only the settings you want to change. A full copy freezes old defaults and makes updates confusing.

Step 4: Create jail.local and enable the sshd jail

Here is what the defaults in jail.conf look like, so you know what you are changing:

  • bantime = 10m: how long a ban lasts.
  • findtime = 10m: the time window fail2ban counts failures in.
  • maxretry = 5: how many failures in that window trigger a ban.
  • ignoreip is commented out: no extra addresses are protected from bans.
  • enabled = false: every jail is off until you turn it on.

The [sshd] section in jail.conf already sets port = ssh and points to the right log with logpath = %(sshd_log)s and backend = %(sshd_backend)s. You only need to switch it on.

Open a new file in the nano editor.

sudo nano /etc/fail2ban/jail.local

Paste this into the file. It protects localhost and your own IP (replace 203.0.113.25 with yours), makes bans a bit longer, and enables the SSH jail.

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.25
bantime = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true
port = ssh

Save with Ctrl+O, press Enter, then exit with Ctrl+X.

The [sshd] plus enabled = true pattern comes straight from the example in the comments of the official jail.conf. Still, test it on a test VPS first if you have one, especially if your provider added its own files under /etc/fail2ban/jail.d/.

If SSH listens on a custom port from Step 2, change the port line to that number. This version is for a server on port 2222.

[sshd]
enabled = true
port = 2222

A few "but what if" answers:

  • What if my home IP changes? Then ignoreip will not match anymore. That is fine, it just means you are treated like anyone else. Key login protects you there, and you can always unban yourself (Step 8).
  • What if I have more than one IP to protect? Add them on the same line, separated by spaces. CIDR ranges like 192.0.2.0/24 work too.

Quick tip: fail2ban also has an ignoreself setting that is true by default. It already ignores the server's own addresses, so you only need to list your remote IP.

Why the order matters: the manual says files in jail.d/*.conf are read before jail.local, and later settings win. So your jail.local overrides a provider's jail.d/defaults-debian.conf or similar file if both set the same thing.

Step 5: Test the configuration before reloading

This checks the config files for mistakes without changing the running service.

sudo fail2ban-client -t

If it reports an OK result, move on. If it prints an error, it usually names the file and line. Fix that first. A typo in a section name like [ssdh] is the most common one.

Step 6: Reload fail2ban and check the jail

This tells fail2ban to reread its configuration without a full restart.

sudo fail2ban-client reload

Now check the overall status. This lists the active jails.

sudo fail2ban-client status

You should see sshd in the jail list. Then look at the SSH jail itself, which shows failure counts and banned IPs.

sudo fail2ban-client status sshd

If fail2ban is not set to start at boot, these two commands start it now and enable it for reboots. The official install notes list them in their CentOS and Fedora sections, and they are standard systemd commands on Debian and Ubuntu too.

sudo systemctl start fail2ban
sudo systemctl enable fail2ban

Step 7: Do a safe test ban

You want proof that the jail can actually block something. There are two ways. Start with the safe one.

Method A: manual ban of an example IP. This bans a documentation IP that nobody uses, so it cannot hurt you.

sudo fail2ban-client set sshd banip 192.0.2.10

Now list the banned IPs in the jail. You should see 192.0.2.10.

sudo fail2ban-client get sshd banip

Remove it again so your list stays clean.

sudo fail2ban-client set sshd unbanip 192.0.2.10

Method B: a real failed-login test from a second network. This is the honest end-to-end test. Use a phone on mobile data, or another server, but never the IP you put in ignoreip, because that one will never be banned.

From the second device, try to log in with a wrong password or a made-up user name at least 5 times within 10 minutes. This example uses a user that does not exist on your server.

ssh nosuchuser@example.com

Replace example.com with your server's IP address or host name, and add -p 2222 if you use a custom port. After the fifth failure, new connection attempts from that device should hang or get refused.

Back in your still-open first session, check the jail.

sudo fail2ban-client status sshd

You should see the second device's IP under the banned list.

Made-up example: Sam runs a small shop site on a VPS. He tests from his phone on mobile data, fails five logins, and watches the phone's mobile data IP appear in the banned list. His laptop at home, listed in ignoreip, keeps working the whole time. That is exactly the result you want.

Step 8: Unban yourself (or anyone)

This removes one IP from the SSH jail. Run it from your open session or the provider's web console.

sudo fail2ban-client set sshd unbanip 203.0.113.25

If you are not sure which jail banned an IP, this checks every jail for that address.

sudo fail2ban-client banned 203.0.113.25

And this removes the IP from all jails and from fail2ban's database in one go.

sudo fail2ban-client unban 203.0.113.25

Heads up: if you closed every SSH session and got banned, do not panic. Log in through your provider's web console, run the unban command above, and then add your IP to ignoreip. Without any action, a ban with our settings ends by itself after 1 hour.

Step 9: Optional, make sure the firewall allows SSH

fail2ban works with the system firewall, and the current upstream config for Debian systems tells it to use nftables, the newer Linux firewall framework. You do not need ufw for fail2ban to work. But if you also run ufw on Ubuntu, allow SSH before you enable it, or you will block yourself.

This allows port 22 (use your custom port if you changed it), then turns on ufw and shows the rules.

sudo ufw allow 22
sudo ufw enable
sudo ufw status

How to check it worked

Run these checks once now, and again after your next reboot.

  1. Run sudo fail2ban-client ping. It tests whether the server is alive, and you should get a reply instead of an error.
  2. Run sudo fail2ban-client status and confirm sshd is in the jail list.
  3. Run sudo fail2ban-client status sshd and confirm the failed and banned counters are present. On a public server they usually start climbing soon.
  4. Look at the fail2ban log for ban events. The default log file is /var/log/fail2ban.log.

This shows the last 20 ban or unban lines from that log.

sudo grep -E "Ban|Unban" /var/log/fail2ban.log | tail -n 20

You should see lines that mention the sshd jail and an IP address. If the log is empty, wait a while or repeat Method B from Step 7.

Troubleshooting

"Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?"

This message comes from fail2ban-client when it cannot find the server's socket file. In plain words: the fail2ban service is not running.

Likely cause: a config error stopped it from starting, or it never started. Run sudo fail2ban-client -t to find the broken line, fix it, then sudo systemctl start fail2ban.

The official install notes (in their CentOS section) mention an error about "no directory /var/run/fail2ban to contain the socket file". If you see that, create the folder with sudo mkdir /var/run/fail2ban and start the service again.

"Permission denied to socket: /var/run/fail2ban/fail2ban.sock, (you must be root)"

You ran fail2ban-client as a normal user. The fix is simple: put sudo in front of the command, or switch to root.

"Have not found any log file for 'sshd' jail."

fail2ban is looking for a log file such as /var/log/auth.log and it does not exist. Some newer systems only write SSH logs to the systemd journal, which is the system's built-in log store, and not to a text file.

Fix: tell the jail to read the journal. Add this line under [sshd] in your jail.local, then run sudo fail2ban-client -t and reload. Test this on a test VPS first.

[sshd]
enabled = true
port = ssh
backend = systemd

The current upstream Debian paths file already sets sshd_backend to systemd, so this matches what newer packages do anyway.

Symptom: sshd is not in the jail list

fail2ban-client status works, but sshd is missing, or status sshd gives an error about an unknown jail. This is a symptom description, not an exact message.

Check these, in this order:

  1. The file is named exactly /etc/fail2ban/jail.local, not jail.local.txt or saved in your home folder.
  2. The section header is exactly [sshd].
  3. The line reads enabled = true, not enable = true.
  4. You ran sudo fail2ban-client reload after saving.
  5. No file in /etc/fail2ban/jail.d/ sets enabled = false for sshd. Run sudo grep -rn enabled /etc/fail2ban/jail.d/ to check.

Symptom: the test ban from your phone never happens

You failed five logins from a second device, but the IP never shows up as banned. Again, this is a symptom, not an error message.

Likely causes: the test device's IP is inside a range in ignoreip, the failures were spread over more than 10 minutes, or the jail is watching the wrong port or log. Recheck Step 2 for the port, and the previous problem for the log backend. Also note that a device behind the same home router as your laptop shares its public IP, so it is ignored too.

Symptom: you banned yourself and every SSH attempt hangs

Your connection just sits there and times out. Use the provider's web console to log in, then run sudo fail2ban-client set sshd unbanip followed by your IP. Add your IP to ignoreip so it does not happen again, and consider switching to key login so you stop mistyping passwords.

Pro tips and when to ask for help

  • Use reload, not a full restart, for normal config changes. The man page also lists an --unban option, which only takes effect together with --restart (sudo fail2ban-client reload --restart --unban), handy when you want a clean slate.
  • Pair fail2ban with SSH keys and, once keys work, think about turning off password logins. The OpenSSH default for PermitRootLogin is already prohibit-password, which means root can only log in with a key, not a password.
  • OpenSSH also limits tries per connection with MaxAuthTries, default 6, and closes idle logins after LoginGraceTime, default 120 seconds. fail2ban adds the cross-connection memory these settings do not have.
  • If your server runs a control panel with its own firewall or brute-force tool, ask your host before adding fail2ban. Two tools fighting over the same firewall rules can cause odd bans.

The one message worth forwarding

If someone else manages your server, or you want a friend to double check your work, send this:

"Hi, could you please confirm fail2ban is protecting SSH on our VPS? I would like: 1) the sshd jail enabled in /etc/fail2ban/jail.local (not by editing jail.conf), 2) the jail port matching the real SSH port from sshd -T, 3) our office IP 203.0.113.25 in ignoreip, 4) the output of sudo fail2ban-client status sshd showing the jail is active. Please keep one SSH session open while testing so nobody gets locked out. Thanks!"

The takeaway: fail2ban is a doorman, not a lock, so turn it on in jail.local, test it from a second network, and keep SSH keys as your real protection.

Reader questions

Does fail2ban replace SSH keys?

No. fail2ban only slows down password guessing by banning IPs after repeated failures. SSH key login is the stronger protection, and the two work well together.

Should I edit jail.conf directly?

No. The file itself says you should not modify it because updates can overwrite it. Put only your changes in jail.local or a .local file under jail.d.

How long does a fail2ban ban last by default?

The default bantime in jail.conf is 10 minutes. You can change it with the bantime setting in jail.local, for example bantime = 1h.

Will fail2ban ban me if I mistype my password?

It can, if you fail maxretry times within findtime. Add your own IP to ignoreip to prevent that, and keep your provider's web console login handy as a backup.

Do I need ufw for fail2ban to work?

No. fail2ban adds its own firewall rules through its ban action. If you do enable ufw, allow your SSH port first so you do not cut off your own access.

Does fail2ban work if SSH runs on a custom port?

Yes, but you must set the port line in the [sshd] section of jail.local to that number. Check the real port with sudo sshd -T first.

Sources & further reading

  1. fail2ban releases on GitHub
  2. fail2ban README
  3. fail2ban default jail.conf
  4. fail2ban wiki: How to install fail2ban packages
  5. jail.conf(5) manual, Debian bookworm
  6. fail2ban-client(1) manual, Debian bookworm
  7. sshd_config(5) manual, Debian bookworm
  8. sshd(8) manual, Debian bookworm
  9. Ubuntu Server docs: Firewalls
  10. Debian package: fail2ban in bookworm

Originally published . About our editorial updates.

Your next project deserves a better foundation.

Explore hosting built for your next chapter.

Explore hosting