Job for fail2ban.service failed because the control process exited with error code

Run sudo fail2ban-client -d. It dumps the full resolved configuration and stops at the first thing it cannot parse, naming the jail and the file. That is the diagnostic; the systemd message tells you nothing.

sudo fail2ban-client -d

# or run the server in the foreground and watch it fail
sudo fail2ban-server -f -x -v

The foreground run is worth knowing. fail2ban frequently dies before its own logging is configured, which is why the journal and /var/log/fail2ban.log can both be empty while the service refuses to start.

The cause, in most cases

A jail is enabled for a service whose log file does not exist. fail2ban treats a missing log path for an enabled jail as fatal and refuses to start the whole server, not just that jail. The message looks like this:

ERROR  No file(s) found for glob /var/log/mail.warn
ERROR  Failed during configuration: Have not found any log file for dovecot jail

This happens constantly after copying a jail.local between servers, because the file enables jails for software the new host does not run. Postfix, dovecot and apache jails on a machine that only runs nginx are the classic. Either disable the jail, or point logpath at a file that exists.

On a modern Ubuntu or Debian host there may be no log file at all, because sshd logs to the journal rather than to /var/log/auth.log. The fix there is not a log path but a backend:

[sshd]
enabled = true
backend = systemd

The other causes worth checking

  1. You edited jail.conf instead of jail.local. Package upgrades overwrite jail.conf, so changes vanish and may come back inconsistent. Put every change in jail.local or a file under jail.d/. This does not cause the failure directly, but it causes the configuration you are reading to differ from the one fail2ban loaded, which wastes a lot of time.
  2. A bad regex in a custom filter. fail2ban raises a Python traceback rather than a tidy error. The traceback names the filter file. Test a filter against a real log before enabling it:
    sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/myfilter.conf
  3. An action that needs a backend you do not have. Actions referencing iptables on a host running only nftables, or referencing a mail command that is not installed, fail at startup. The error names the action file.
  4. The runtime directory is missing. fail2ban needs /var/run/fail2ban for its socket. Because /run is a tmpfs it is empty after every boot, so this appears on reboot with nothing having been edited. A stale socket file from an unclean shutdown causes the same symptom: remove /var/run/fail2ban/fail2ban.sock and start again.

Reading the exit code

status=255 is the one you will usually see here, and for fail2ban it reliably means a configuration problem. Go straight to fail2ban-client -d. status=1/FAILURE covers most other startup rejections. The full table, which applies to any systemd unit, is in the nginx version of this error.

How to stop it happening again

sudo fail2ban-client -d > /dev/null && sudo systemctl reload fail2ban

The dump exits non-zero on a bad configuration, so a broken jail never reaches the running server. Worth building into any automation that writes jail files, because the common cause here is configuration management enabling a jail on a host that lacks the matching service, and that mistake is invisible until the next restart.

Related

Why does reload fail when restart works?

A reload asks the running server to re-read its configuration while jails are active, and it will refuse rather than drop a jail it can no longer satisfy. A restart tears everything down first, so a jail that is merely unsatisfiable on reload can appear to start cleanly. If restart works and reload does not, the new configuration is genuinely broken and you have simply hidden it. Run fail2ban-client -d and fix the jail it names.

Nothing is in the journal or in fail2ban.log

Then it died before logging was initialised, which is common for this service. Run sudo fail2ban-server -f -x -v to start it in the foreground with verbose output: the error prints to your terminal. Stop it with Ctrl+C once you have the cause, and start the unit normally after fixing it.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *