skip to content

System: Using systemd to bind fail2ban to nftables

 Tweet0 Tweets

In the past we've used an init script to initialise our firewalls, orginally using iptables, and more recently with nftables.

This involved an init script including code to start and stop Fail2Ban when the firewall was stopped an started. But this is not the systemd way...

Configuring Fail2Ban to start/stop with nftables

What we're trying to achieve is the following:

We can do all this by creating an override file for fail2ban telling it that it depends on nftables, and than nftables wants it to start:


[Unit] Requires=nftables.service PartOf=nftables.service [Install] nftables.service

Because we've modified the [Install] section, we need to re-enable the affected service in order for the relevant symlinks to be created. We're also making sure that nftables is installed as a service unit first:

# systemctl enable nftables.service Created symlink /etc/systemd/system/ → /lib/systemd/system/nftables.service. # systemctl enable fail2ban.service Created symlink /etc/systemd/system/nftables.service.wants/fail2ban.service → /lib/systemd/system/fail2ban.service. # systemctl daemon-reload

The 'Created symlink' output with nftables.service.wants tells us that our changes have worked and that nftables now 'wants' fail2ban to be started when it does.

How does it work exactly?

In our override file, or full configuration file (see below), we include the following settings:


starting this service will first start nftables.service.
causes this unit to stop or restart (but not start) with nftables.service.

[Install] nftables.service
causes this unit to start when any of the listed services are started.

As you can see we need to set Requires, PartOf and WantedBy to get the desired behaviour. You can find more details under References below.

Alternative configuration approach

Systemd keeps its main configuration files under /usr/lib/systemd/system/* and these should not be edited. Local configuration can instead be set up under /etc/systemd/system/* where it will take precedence over the default configuration on a per-file or per-service basis.

In the above example we've created an 'override' configuration file for Fail2Ban binding it to nftables. This takes the original configuration and just adds or replaces the lines that appear in the override. This way an APT upgrade can still affect other settings.

An alternative is to create a whole new configuration file, which can be done using:

# systemctl edit --full fail2ban.service

This will open /usr/lib/systemd/system/fail2ban.service in a text editor which, when saved, will create an override file /etc/systemd/system/fail2ban.service. In this case any APT upgrade cannot affect your configuration.

Confirming that it's working

Starting with both nftables and Fail2Ban running:

# systemctl list-units --type=service | egrep fail2ban\|nftables fail2ban.service loaded active running Fail2Ban Service nftables.service loaded active exited nftables

Stopping nftables:

# systemctl stop nftables.service

causes both services to disappear:

# systemctl list-units --type=service | egrep fail2ban\|nftable (no output)

And starting Fail2Ban causes them to reappear as before:

# systemctl start fail2ban.service

We can also stop and start fail2ban without affecting nftables, assuming it's already active.

Setting up an nftables firewall

We're not going to go into any details here. The point of the nftables service unit is to run the contents of /etc/nftables.conf when nftables is started, and to flush the ruleset when it's stopped.

You can find examples under /usr/share/doc/nftables/examples/.


< System

Send a message to The Art of Web:

used only for us to reply, and to display your gravatar.

<- copy the digits from the image into this box

press <Esc> or click outside this box to close

Post your comment or question