--- title: "wp-fail2ban Plugin Logpath on Debian/Ubuntu (auth.log, not syslog)" domain: selfhosting category: security tags: [fail2ban, wordpress, wp-fail2ban, debugging, gotcha, debian, ubuntu] status: published created: 2026-04-30 updated: 2026-04-30 --- # wp-fail2ban Plugin Logpath on Debian/Ubuntu (auth.log, not syslog) ## The Problem You install the [WP fail2ban](https://wordpress.org/plugins/wp-fail2ban/) WordPress plugin, configure the fleet-standard `wordpress-hard`, `wordpress-soft`, and `wordpress-extra` jails, and… nothing. Weeks pass. `fail2ban-client status wordpress-hard` reports `Total failed: 0, Total banned: 0`. Your site is being attacked, but the jails are dead. Meanwhile the `wordpress-login` jail (which reads Apache access logs for `POST /wp-login.php` directly) is happily catching brute-forcers. So the problem isn't fail2ban itself — it's specifically the wp-fail2ban-plugin-derived jails. ## The Cause The wp-fail2ban plugin emits events via PHP's `syslog()` call with facility `LOG_AUTH`. On Debian/Ubuntu, rsyslog routes the `auth` facility to **`/var/log/auth.log`**, NOT `/var/log/syslog`. On RHEL/Fedora it's `/var/log/secure`. A lot of tutorials, ansible-galaxy roles, and copy-paste config snippets specify: ```ini logpath = /var/log/syslog ``` That's wrong on Debian/Ubuntu. The events never land there, so the filter regex has nothing to match, so the jail catches zero events forever. Silently. ## Diagnostic Steps If a `wordpress-{hard,soft,extra}` jail shows `Total failed: 0` over a long window despite the plugin being active and the site getting attacked: **1. Check what the jail thinks it's watching:** ```bash sudo fail2ban-client status wordpress-hard | grep "File list" ``` **2. Check where wp-fail2ban events actually land:** ```bash sudo grep -c "wordpress(" /var/log/auth.log /var/log/syslog /var/log/secure 2>/dev/null ``` You'll see something like: ``` /var/log/auth.log:314 /var/log/syslog:0 ``` **3. If the jail's `File list` ≠ the file with events, fix the `logpath`.** A real event line on Debian/Ubuntu looks like: ``` 2026-04-18T23:28:21.027004-04:00 hostname wordpress(example.com)[719989]: XML-RPC authentication failure for someone from 1.2.3.4 ``` The `wordpress(domain)[pid]` syslog tag is the giveaway — those are wp-fail2ban events. ## The Fix Edit the jail blocks in `/etc/fail2ban/jail.local` (or your Ansible source for the jail) and set: ```ini [wordpress-hard] enabled = true port = http,https filter = wordpress-hard logpath = /var/log/auth.log maxretry = 1 findtime = 60 bantime = 30d backend = polling [wordpress-soft] enabled = true port = http,https filter = wordpress-soft logpath = /var/log/auth.log maxretry = 5 findtime = 60 bantime = 30d backend = polling [wordpress-extra] enabled = true port = http,https filter = wordpress-extra logpath = /var/log/auth.log maxretry = 5 findtime = 60 bantime = 30d backend = polling ``` Then: ```bash sudo fail2ban-client -t # validate sudo fail2ban-client reload sudo fail2ban-client status wordpress-hard | grep "File list" # should now show /var/log/auth.log ``` ## Verification You can prove the filter regex actually matches your real events without waiting for an attack — run `fail2ban-regex` against the rotated log: ```bash sudo fail2ban-regex /var/log/auth.log.1 /etc/fail2ban/filter.d/wordpress-hard.conf | grep -E "Failregex:|Lines:" ``` Healthy output looks like: ``` Failregex: 81 total Lines: 13008 lines, 0 ignored, 81 matched, 12927 missed ``` If you see `Failregex: 0 total`, the filter regex doesn't match what the plugin actually emits — which is a different bug (filter version skew vs. plugin version), not the logpath gotcha. Investigate `/etc/fail2ban/filter.d/wordpress-{hard,soft}.conf` against actual event lines. > **Note:** On a freshly-fixed jail, counters will sit at `Total failed: 0` for a while — the `polling` backend starts at the file's current EOF, so old events aren't retroactively counted. New events from the moment of `reload` onward will accumulate. Allow a few days of normal attack traffic before declaring the fix broken. ## Distribution Cheat Sheet | Distro family | wp-fail2ban events land in | |---|---| | Debian / Ubuntu | `/var/log/auth.log` | | RHEL / CentOS / Fedora | `/var/log/secure` | | systemd-journal-only systems | `journalctl SYSLOG_FACILITY=4` (use `backend = systemd` + `journalmatch = SYSLOG_FACILITY=4`) | If you have a mixed fleet, parameterize the path: ```yaml # Ansible vars wp_fail2ban_log_path: "{{ '/var/log/auth.log' if ansible_os_family == 'Debian' else '/var/log/secure' }}" ``` ## Why wordpress-login Is Unaffected The `wordpress-login` jail is a different beast — it reads `/var/log/apache2/access.log` directly and matches `^ -.*"POST /wp-login.php` via the `wordpress-login` filter. No plugin involved, no syslog facility involved. So a host can have `wordpress-login` working perfectly while `wordpress-{hard,soft,extra}` are silently dead. Don't let a healthy `wordpress-login` reassure you that the rest of the wp-fail2ban stack is also fine. ## Related - [[fail2ban-wordpress-login-jail]] — the access-log layer that catches WP brute force without any plugin dependency - [[fail2ban-apache-bad-request-jail]] - [[fail2ban-apache-php-probe-jail]] - [[clamav-fleet-deployment]]