Commands
fail2ban logs: location, levels and how to read them
fail2ban writes its own log of every failure it finds and every ban it makes. This page shows where that log lives, how to read it, and the grep one-liners worth keeping.
fail2ban logs to /var/log/fail2ban.log by default on Debian, Ubuntu and most other distributions. Read it with sudo tail -f /var/log/fail2ban.log. Service start-up errors go to the systemd journal instead: sudo journalctl -u fail2ban. To confirm where your install writes, run sudo fail2ban-client get logtarget; the log level (default INFO) is shown by sudo fail2ban-client get loglevel.
$ sudo fail2ban-client get logtarget
Current logging target is:
`- /var/log/fail2ban.log
$ sudo fail2ban-client get loglevel
Current logging level is 'INFO'How to check fail2ban logs#
# follow new entries live
sudo tail -f /var/log/fail2ban.log
# last 100 lines
sudo tail -n 100 /var/log/fail2ban.log
# service messages and start-up errors
sudo journalctl -u fail2ban -e
# both together if logtarget is the journal
sudo journalctl -u fail2ban -fIf /var/log/fail2ban.log is empty or missing, check get logtarget: some setups send fail2ban's log to the journal or syslog instead.
Reading fail2ban log lines#
2026-10-25 18:36:10,238 fail2ban.filter [1997]: INFO [sshd] Found 203.0.113.42 - 2026-10-25 18:36:10
2026-10-25 18:36:10,239 fail2ban.filter [1997]: INFO [sshd] Found 198.51.100.7 - 2026-10-25 18:36:10
2026-10-25 18:36:11,027 fail2ban.actions [1997]: NOTICE [sshd] Ban 203.0.113.42
2026-10-25 18:36:11,033 fail2ban.filter [1997]: INFO [recidive] Found 203.0.113.42 - 2026-10-25 18:36:11
2026-10-25 19:36:11,031 fail2ban.actions [1997]: NOTICE [sshd] Unban 203.0.113.42Each line is: timestamp, the fail2ban component, process ID, level, [jail] and the message.
| Message | Meaning |
|---|---|
Found <IP> - <time> |
The filter matched a failure line. The time is the timestamp from the service's log. |
Ban <IP> |
The IP reached maxretry within findtime (or was banned by hand) and the action ran. |
Unban <IP> |
The ban expired or was lifted with unbanip. |
Restore Ban <IP> |
A ban re-applied from the database after a start or jail restart. |
Repeal Ban <IP> |
Firewall rule removed because the jail stopped; the ban itself is kept. |
<IP> already banned |
A failure from an address that's already blocked — often a sign the firewall isn't actually dropping its traffic. |
Note the [recidive] Found line: the recidive jail reads this very log and treats each Ban of another jail as a failure, so repeat offenders get a longer ban.
Found lines with no Ban after them are normal: the IP hasn't reached maxretry yet. Lots of Found and never a Ban points at findtime/maxretry or ignoreip — see fail2ban not banning.
Useful grep recipes#
# all bans (excludes Restore/Repeal lines)
sudo grep '\] Ban ' /var/log/fail2ban.log
# bans today
sudo grep "^$(date +%F).*\] Ban " /var/log/fail2ban.log
# number of bans per jail
sudo grep -oP '\[\K[^]]+(?=\] Ban )' /var/log/fail2ban.log | sort | uniq -c | sort -rn
# top 20 banned IPs, including rotated and compressed logs
sudo zgrep -h '\] Ban ' /var/log/fail2ban.log* | awk '{print $NF}' | sort | uniq -c | sort -rn | head -20
# everything about one IP
sudo zgrep -h '203.0.113.42' /var/log/fail2ban.log*
# errors and warnings only
sudo grep -E 'ERROR|WARNING' /var/log/fail2ban.logFor charts and per-jail breakdowns without the shell work, paste the log into the log analyzer. For current bans rather than history, use list banned IPs.
fail2ban log level#
The log level is set in fail2ban.local and can be changed live:
| Level | What you see |
|---|---|
CRITICAL, ERROR |
Failures only |
WARNING |
Plus warnings (missing logs, DNS lookups with usedns = warn) |
NOTICE |
Plus Ban, Unban, Restore Ban |
INFO (default) |
Plus Found, jail start/stop, monitored files |
DEBUG |
Plus each processed line and action command — very verbose |
TRACEDEBUG, HEAVYDEBUG |
Internal tracing for developers |
Change it until the next reload:
sudo fail2ban-client set loglevel DEBUG
# …reproduce the problem…
sudo fail2ban-client set loglevel INFOMake it permanent:
[DEFAULT]
loglevel = NOTICENOTICE is a good choice on busy servers if you only care about bans; it drops the Found lines. Keep INFO while you're tuning jails.
Log targets: file, journal, syslog#
logtarget in fail2ban.local decides where the log goes:
| Value | Destination |
|---|---|
/var/log/fail2ban.log |
A file (the default) |
SYSTEMD-JOURNAL |
The journal, via the python-systemd module (journalctl -t fail2ban) |
SYSOUT |
Standard output without timestamps — the journal adds its own when run under systemd |
STDOUT, STDERR |
Standard output / error with timestamps |
SYSLOG |
The local syslog daemon (facility daemon; SYSLOG[facility=local0] to change it) |
[DEFAULT]
logtarget = SYSTEMD-JOURNALChange it at runtime with sudo fail2ban-client set logtarget SYSTEMD-JOURNAL. If you stop writing to the file, remember that the recidive jail reads /var/log/fail2ban.log by default — point its logpath elsewhere or give it backend = systemd. More settings on fail2ban.conf and fail2ban.local.
fail2ban journalctl commands#
sudo journalctl -u fail2ban # the service: start/stop, errors, tracebacks
sudo journalctl -u fail2ban -b # since last boot
sudo journalctl -u fail2ban --since "1 hour ago"
sudo journalctl -t fail2ban -f # fail2ban's own log when logtarget = SYSTEMD-JOURNALWhen the service fails to start (status=255/EXCEPTION), the journal has the reason. See exit code 255.
Log rotation#
Debian and Ubuntu packages install /etc/logrotate.d/fail2ban, which rotates /var/log/fail2ban.log weekly, keeps four compressed copies and runs fail2ban-client flushlogs afterwards so fail2ban reopens the new file. Check yours:
cat /etc/logrotate.d/fail2banIf you write your own rule, keep the flushlogs step:
/var/log/fail2ban.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
postrotate
fail2ban-client flushlogs >/dev/null || true
endscript
}Without it, fail2ban keeps writing to the rotated file. Raising rotate gives recidive and your grep recipes a longer history.
fail2ban logs in Docker#
Containerised fail2ban usually logs to stdout or to a file in its mounted config volume. Try:
docker logs -f fail2ban
docker exec fail2ban fail2ban-client get logtargetThen read the file that get logtarget reports. More on this setup in fail2ban with Docker.
How fail2ban reads service logs#
Each jail watches either log files or the systemd journal:
[nginx-http-auth]
enabled = true
logpath = /var/log/nginx/error.log
[sshd]
enabled = true
backend = systemd- File backends (
auto,pyinotify,polling) read the files inlogpath. Wildcards work (/var/log/nginx/*error.log); list several files one per line. Check withsudo fail2ban-client get <jail> logpath. - systemd backend reads the journal using the filter's
journalmatch;logpathis ignored. Check withsudo fail2ban-client get <jail> journalmatch.
On 1.1.1, backend = auto switches to the journal automatically when no file matches logpath and the filter has a journalmatch. Debian 12 needs backend = systemd for sshd because it has no /var/log/auth.log. Details on backends and the systemd journal and no log file found for jail.
FAQ#
Where is the fail2ban log file?#
/var/log/fail2ban.log on Debian, Ubuntu and most distributions, as set by logtarget in /etc/fail2ban/fail2ban.conf. Run sudo fail2ban-client get logtarget to see the active target. If it says SYSTEMD-JOURNAL or SYSLOG, read the log with journalctl -t fail2ban or in your syslog files.
How do I check fail2ban logs?#
Run sudo tail -f /var/log/fail2ban.log to watch live, or sudo grep '\] Ban ' /var/log/fail2ban.log for bans only. Start-up errors and crashes are in the journal: sudo journalctl -u fail2ban -e. Each Found line is a detected failure and each Ban line a block.
How do I change the fail2ban log level?#
Run sudo fail2ban-client set loglevel DEBUG for an immediate, temporary change. To keep it, add loglevel = DEBUG (or NOTICE, WARNING…) under [DEFAULT] in /etc/fail2ban/fail2ban.local and reload. The default is INFO.
Why is fail2ban not logging?#
Check sudo fail2ban-client get logtarget — the log may be going to the journal or syslog. If it's a file, make sure the service runs and the file is writable by root. After manual rotation without fail2ban-client flushlogs, fail2ban keeps writing to the old file; run that command or reload.
Can fail2ban log to the systemd journal?#
Yes. Set logtarget = SYSTEMD-JOURNAL in fail2ban.local (requires the python3-systemd package) and read it with journalctl -t fail2ban. Alternatively logtarget = SYSOUT sends plain output that systemd stores under journalctl -u fail2ban.
Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.