Get started
Install fail2ban on Debian 12, Debian 13 and Raspberry Pi OS
On Debian 13 and Raspberry Pi OS Trixie fail2ban works straight after apt install. On Debian 12 and Pi OS Bookworm the same command leaves you with a service that won't start. Here's why, and the short fix.
To install fail2ban on Debian or Raspberry Pi OS, run sudo apt update && sudo apt install fail2ban. On Debian 13 (trixie) and Raspberry Pi OS Trixie the sshd jail is enabled and reads the systemd journal out of the box. On Debian 12 (bookworm) and Pi OS Bookworm there is no /var/log/auth.log, so fail2ban fails to start until you add backend = systemd to the [sshd] jail in /etc/fail2ban/jail.local.
sudo apt update
sudo apt install fail2ban python3-systemd nftablespython3-systemd lets fail2ban read the journal. It's a hard dependency on Debian 13 and a recommended package on Debian 12, so apt normally installs it anyway. Listing it explicitly protects you if you use --no-install-recommends.
fail2ban versions and defaults on Debian#
| Debian release | Raspberry Pi OS | fail2ban | Default ban action | sshd jail out of the box |
|---|---|---|---|---|
| 13 trixie | Trixie (from October 2025) | 1.1.0 | nftables | Works: journal, ssh.service |
| 12 bookworm | Bookworm | 1.0.2 | iptables-multiport | Fails: looks for /var/log/auth.log |
| 11 bullseye | Bullseye (legacy) | 0.11.2 | iptables-multiport | Works: /var/log/auth.log via rsyslog |
| testing / sid | — | 1.1.1 | nftables | Works: journal |
Check which release you have with grep VERSION_CODENAME /etc/os-release. The difference comes from /etc/fail2ban/jail.d/defaults-debian.conf, which the package installs:
[DEFAULT]
banaction = nftables
banaction_allports = nftables[type=allports]
[sshd]
backend = systemd
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd
enabled = trueDebian's 1.1.0 package also carries patches for the sshd-session process name used by OpenSSH 9.8 and later (trixie ships OpenSSH 10), so the stock sshd filter matches modern log lines.
[sshd]
enabled = trueThat's all. The sshd jail inherits backend = auto and logpath = /var/log/auth.log from jail.conf, and bans with iptables-multiport. Debian 12 no longer installs rsyslog, so that file doesn't exist.
Debian 12: fix "Have not found any log file for sshd jail"#
Right after apt install fail2ban on Debian 12 or Pi OS Bookworm, systemctl status fail2ban shows the service failed, and journalctl -u fail2ban contains Have not found any log file for sshd jail. Logs go to the systemd journal only. You have two fixes; the first is the right one.
Fix 1 — read the journal (recommended). Create /etc/fail2ban/jail.local:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
bantime = 1h
findtime = 10m
maxretry = 5
banaction = nftables
banaction_allports = nftables[type=allports]
[sshd]
enabled = true
backend = systemdThen:
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status sshdThe banaction lines switch Debian 12 from iptables to nftables, which is Debian's default firewall framework since Debian 10. It avoids a second failure later, when the first ban runs and the iptables command isn't installed. This file is also safe on Debian 13: backend = systemd and nftables are already its defaults.
Fix 2 — bring back auth.log. sudo apt install rsyslog recreates /var/log/auth.log and the stock config works. It also means every auth message is written twice (journal and file). Only do this if other tools need the text file.
More causes of this error, for other jails too, are on no log file found for jail.
Debian 13: check and tune the defaults#
Nothing is required on trixie; the service is running after install. Still create a jail.local so you control the policy instead of relying on the 10-minute stock ban:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 203.0.113.10
bantime = 1h
findtime = 10m
maxretry = 5
bantime.increment = true
bantime.maxtime = 1w
[sshd]
enabled = trueYou don't need to repeat backend or journalmatch here — defaults-debian.conf already sets them correctly for trixie's ssh.service. If SSH listens on a non-standard port, add port = 2222 to [sshd]. Then reload with sudo fail2ban-client reload. Incremental ban times explains the bantime.* lines.
fail2ban with nftables on Debian#
With banaction = nftables (the default on Debian 13, set by hand on Debian 12), fail2ban creates its own table, inet f2b-table, with one address set per jail. It doesn't touch /etc/nftables.conf or your existing ruleset, and you don't need the nftables service enabled. Only the nft command must exist.
sudo nft list table inet f2b-tableYou'll see a chain hooked into input at priority -1 and a set named after each jail containing the banned addresses. Because the chain runs before a typical inet filter table at priority 0, banned IPs are rejected even if your own rules accept the port. The nftables guide covers custom chains, drop vs reject, Docker forwarding and every action parameter.
If you run firewalld or UFW on Debian instead, use banaction = firewallcmd-rich-rules or banaction = ufw (see fail2ban with UFW and choosing a ban action).
Raspberry Pi OS#
Raspberry Pi OS is Debian with Raspberry Pi additions, so fail2ban comes from the Debian repositories and everything above applies: Bookworm behaves like Debian 12, Trixie like Debian 13. The Debian 12 jail.local works on both. Running Ubuntu on the Pi instead? Follow the Ubuntu page.
On a Pi, a few settings matter more than on a server:
ignoreip— set it to your home network's range (check withip -4 addr). Otherwise a mistyped password from your laptop can lock you out of a headless Pi. More options in whitelist IPs with ignoreip.backend = systemd— required on Bookworm, harmless on Trixie.banaction = nftables— Bookworm's fail2ban defaults to iptables, which may not be installed. Trixie already uses nftables.
Lighter on SD cards and low-memory Pis#
fail2ban is a Python daemon. It runs comfortably on a Pi Zero 2 W and is barely noticeable on a Pi 4 or Pi 5. A few settings keep it lean:
- Use the journal backend.
backend = systemdwaits for new journal entries; there's no polling loop and no duplicate text log written by rsyslog. Installing rsyslog just to getauth.logdoubles the writes to your SD card. - Enable only the jails you need. Each jail is a separate thread reading its own log source. SSH plus one or two exposed services is typical.
- Keep
maxretryandfindtimemodest. fail2ban keeps recent failures in memory forfindtime, so very long windows on a busy jail cost memory. - Optionally log to the journal instead of a file. In
/etc/fail2ban/fail2ban.local, setlogtarget = SYSTEMD-JOURNALunder[DEFAULT], then read fail2ban's messages withjournalctl -u fail2ban. If you use the recidive jail, give itbackend = systemdtoo, because its defaultlogpathis/var/log/fail2ban.log.
The ban database at /var/lib/fail2ban/fail2ban.sqlite3 is small and written only when bans change.
Raspberry Pi SSH security beyond fail2ban#
fail2ban slows down password guessing; it doesn't make a weak password safe. On a Pi reachable from the internet:
- Use SSH keys:
ssh-copy-id user@pi, then setPasswordAuthentication noin/etc/ssh/sshd_configandsudo systemctl restart ssh. - Don't use a default or reused username and password. Current Raspberry Pi Imager makes you create your own user.
- Forward SSH from your router only if you need it. A VPN such as WireGuard on the Pi exposes one UDP port instead of a login prompt.
- If you access the Pi through a tunnel (Cloudflare Tunnel, Tailscale Funnel, a reverse proxy), the logs may show
127.0.0.1instead of the attacker's address. fail2ban can only ban addresses it sees — read bans the proxy IP.
The SSH guide covers aggressive filter modes, custom ports and long bans for repeat offenders.
Verify fail2ban is protecting SSH#
$ sudo fail2ban-client ping
Server replied: pongsudo fail2ban-client status sshdOn Debian 12 (with the fix) and Debian 13 the filter section shows Journal matches: instead of File list:, because sshd uses the systemd backend. To prove the firewall side, ban a documentation address and look for it:
sudo fail2ban-client set sshd banip 192.0.2.15
sudo nft list table inet f2b-table | grep 192.0.2.15
sudo fail2ban-client set sshd unbanip 192.0.2.15To check that the filter matches real SSH failures in the journal, run fail2ban-regex against it:
sudo fail2ban-regex systemd-journal sshdOnce the machine has been reachable from the internet for a while, real bans appear in the jail status and in /var/log/fail2ban.log:
2026-10-25 18:36:11,027 fail2ban.actions [1997]: NOTICE [sshd] Ban 203.0.113.42Upgrading from Debian 12 to 13#
During the upgrade, apt may ask whether to keep your version of jail.conf or defaults-debian.conf if you edited them. Take the maintainer's version; your settings belong in jail.local. After the upgrade, remove any banaction and sshd backend lines you added for bookworm only if you want trixie's defaults — keeping them is harmless.
FAQ#
How do I install fail2ban on Debian 12?#
Run sudo apt install fail2ban python3-systemd nftables, then create /etc/fail2ban/jail.local with [sshd], enabled = true and backend = systemd, and set banaction = nftables under [DEFAULT]. Restart with sudo systemctl restart fail2ban. Without the backend line the service fails, because Debian 12 has no /var/log/auth.log.
Why does fail2ban fail to start on Debian 12 or Raspberry Pi OS Bookworm?#
The sshd jail looks for /var/log/auth.log, which Debian 12 and Pi OS Bookworm don't create because rsyslog isn't installed anymore. fail2ban stops with "Have not found any log file for sshd jail". Set backend = systemd for the sshd jail in jail.local, or install rsyslog.
Does fail2ban work on Debian 13 out of the box?#
Yes. Debian 13 ships fail2ban 1.1.0 with the sshd jail enabled, reading the systemd journal for ssh.service and banning with nftables. The same applies to Raspberry Pi OS Trixie. Add a jail.local only to set ignoreip, bantime and any extra jails.
Does fail2ban use nftables on Debian?#
On Debian 13, yes, by default. On Debian 12 the package still defaults to iptables-multiport; set banaction = nftables and banaction_allports = nftables[type=allports] in jail.local. fail2ban keeps its bans in its own inet f2b-table table, separate from your ruleset.
How do I install fail2ban on a Raspberry Pi?#
Run sudo apt install fail2ban python3-systemd nftables. Then create /etc/fail2ban/jail.local with your LAN in ignoreip, banaction = nftables, and an [sshd] section with enabled = true and backend = systemd. Restart with sudo systemctl restart fail2ban and check sudo fail2ban-client status sshd.
Does fail2ban slow down a Raspberry Pi?#
Not noticeably. fail2ban is a small Python daemon that sleeps until new log entries arrive. Using the systemd backend avoids polling and extra SD card writes. Enabling only the jails you need keeps memory use low, even on a Pi Zero 2 W.
Is fail2ban needed on a Raspberry Pi?#
If SSH or another login is reachable from the internet, it's a useful layer: it stops repeated guessing and keeps logs readable. On a Pi that is only reachable from your home network, SSH keys and a firewall matter more, and fail2ban is optional.
Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.