HardStacked
Share:

Boot · systemd

Enabled is not the same as on

Published · HardStacked · 7 min

You enabled the firewall. You rebooted. ufw status says inactive. So you check the service, and systemd tells you it is enabled, active, and that it started with status=0/SUCCESS. Nothing is broken, nothing logged an error, and the machine has no firewall.

This is not a mistake you made. ufw has two separate switches that both use the word enabled, and every common way of checking reads only one of them.

Everything below was measured on a throwaway Debian 13 (trixie) aarch64 virtual machine on 2026-08-23, with ufw 0.36.2-9, iptables 1.8.11-2 and nftables 1.1.3-1. On Debian 13 the iptables command is provided by iptables-nft, so the rules land in nftables. The two switches are a property of the ufw package rather than of the release.

01. The two line verdict

ufw is started by a systemd unit, and that unit runs a script which reads ENABLED= in /etc/ufw/ufw.conf. If it reads no, the script does nothing at all and exits successfully. systemd records a clean start, because the script did exactly what it was told.

Two switches in series: the systemd unit decides whether the script runs, ENABLED= decides whether the script does anything. You need both, and either one can be right while the other is wrong.

02. The command that settles it

These commands are provided as is, without warranty. Test on a non critical machine or a snapshot first.

Three questions, three answers, one line:

bash
$ systemctl is-enabled ufw; grep '^ENABLED=' /etc/ufw/ufw.conf; ufw status | head -1

A machine that is actually protected prints this, and nothing else counts as protected:

expected
enabled ENABLED=yes Status: active

Any other combination names the switch that is off. enabled / ENABLED=no / Status: inactive means the unit runs and the configuration tells it to do nothing, so the fix is ufw enable. disabled / ENABLED=yes / Status: inactive means the configuration is right and nothing starts it at boot, so the fix is systemctl enable --now ufw.

Those three outputs, the healthy one and the two failures, came from the same machine in three states separated by real reboots. If you take one thing from this page, take that line: it tells the two failures apart, and they look identical everywhere else.

One combination is not covered here. If you get enabled, ENABLED=yes and Status: inactive together, both switches are on and the firewall is still down, which is a different fault: the rules failed to load. That one has its own page, ufw RULE_APPEND failed.

03. Why systemctl cannot see it

Start the service on a machine where ENABLED=no, and change nothing else:

bash
$ systemctl start ufw && systemctl status ufw
systemctl status ufw
● ufw.service - Uncomplicated firewall Loaded: loaded (/usr/lib/systemd/system/ufw.service; enabled; preset: enabled) Active: active (exited) since Sun 2026-08-23 23:15:48 EDT; 959ms ago Process: 1678 ExecStart=/usr/lib/ufw/ufw-init start quiet (code=exited, status=0/SUCCESS) Main PID: 1678 (code=exited, status=0/SUCCESS)

A green dot, enabled, active, and an exit status of zero. On the same machine, at the same moment:

ufw status verbose
Status: inactive

Read the Process: line again. The unit’s job is to run /usr/lib/ufw/ufw-init start quiet, and that program returned 0. It ran, it read ENABLED=no, it declined to load anything, and it exited without an error, because not loading a firewall you were told not to load is not an error. systemd reports on the script, and the script did its job. The question you were asking was about the firewall.

active (exited) deserves a word of its own, because it looks like a symptom and is not one. It only means the unit is a Type=oneshot: it ran something, that something finished, and no process is left behind. That is normal for ufw. A correctly running firewall reports active (exited) too, the same two words in the same place. It is not a light that lies. It is a light that shows the same colour whatever happens, which is worse, because you believe you have checked something.

04. What ufw enable actually changes

bash
$ ufw enable
ufw enable
Firewall is active and enabled on system startup

That sentence is the source of half the confusion. Read literally, enabled on system startup sounds like systemd. It is not. Measured before and after that exact command, the systemd link is untouched: same target, same timestamp, not recreated.

ls -l /etc/systemd/system/multi-user.target.wants/ufw.service
lrwxrwxrwx 1 root root 35 Aug 23 23:15 /etc/systemd/system/multi-user.target.wants/ufw.service -> /usr/lib/systemd/system/ufw.service

The single change is in ufw’s own configuration file, from ENABLED=no to ENABLED=yes. So ufw enable flips switch number two and reports it in words that describe switch number one. It is not lying: with both switches on, the firewall genuinely does come up at boot. It just says nothing about the switch it did not touch.

The other half of the confusion is that installing the package already flipped switch number one for you:

apt-get install -y ufw
Created symlink '/etc/systemd/system/multi-user.target.wants/ufw.service' -> '/usr/lib/systemd/system/ufw.service'.

Straight after apt install ufw, before any other command, systemctl is-enabled ufw answers enabled on a machine whose firewall has never been turned on. Which is why the usual advice, you forgot to run systemctl enable ufw, so often changes nothing. On Debian it was never missing.

05. The only valid test is a reboot

The two switches are independent, so no amount of inspection while the machine is up tells you what the next boot will do. Reboot, then look. A machine with both switches on:

after reboot, healthy
$ ufw status verbose Status: active $ systemctl is-enabled ufw; systemctl is-active ufw enabled active

A machine with ENABLED=no and the unit still enabled, after the same reboot:

after reboot, ENABLED=no
$ systemctl is-active ufw active $ ufw status verbose Status: inactive

Counting what the kernel actually holds separates them without any ambiguity:

bash
$ nft list ruleset | grep -c .

318 on the working machine. 0 on the second one. Not a reduced ruleset, not a partial one: nothing. Every port on that machine is open, and the service page is green.

06. The two halves of the failure

Both switches have to be on. Turning off either one gives you the same empty machine, and the two cases differ only in the one place you have to know to look.

measured across three reboots
ufw.conf systemd unit after reboot kernel rules ENABLED=yes enabled Status: active 318 ENABLED=no enabled Status: inactive 0 ENABLED=yes disabled Status: inactive 0

Row two is the one that catches people, because everything they check says yes. Row three is the honest failure: systemctl is-enabled ufw answers disabled, and for once the tool you reached for is the tool that knows.

How machines land in row two: a configuration manager writing ufw.conf from a template that carries ENABLED=no, an image built before the firewall was configured, a ufw disable run during a debugging session and never undone, a restore of /etc from a backup taken while the firewall was off. In all four the systemd unit stays enabled, because nobody touched it.

And this is where systemctl restart ufw misleads. Restarting re-runs the same script, which re-reads the same ENABLED=no, and reports success again. The service goes green in front of you. Restarting a unit tests the unit; it does not test the configuration the unit reads.

07. What this says beyond ufw

Every status command answers the question it was built for, not the one you had in mind. systemctl reports on units and on the exit codes of what they launch. It has no opinion on whether your machine is protected, and it never claimed to.

That gap is a whole family, and we have measured it three times before on this site: a WireGuard unit that reports active while no interface exists, a firewall that reports active with no rule loaded, and a hardened unit that runs as root and is refused with Permission denied. Same shape every time, a green light telling the truth about something narrower than what you read into it.

The habit worth keeping is small: check the thing itself, not the machinery that starts it. For a firewall that means ufw status and a count of the rules the kernel holds, after a reboot. It takes ten seconds, and it is the only answer that is about your machine.

Share: