Configure the firewall with UFW¶
Hardening runbook. Restricts inbound traffic to the services the server actually needs, using UFW (the simpler frontend to netfilter). For the choice between UFW, nftables, and the alternatives, see the firewall overview.
When to run¶
On a new server during setup, once the services it will run are known. On an existing server that has no firewall, or one with rules that have drifted from what the server actually needs.
Before starting¶
A list of the ports the server legitimately serves. For a web server: 80 and 443. For SSH: 22, or the port SSH was moved to. Anything not on the list is a candidate to leave closed.
Risk¶
A default-deny inbound policy applied before the SSH rule is in place drops the current SSH session and locks the server. Add the SSH allow rule first, then set the default policy. Keep the existing session open and test from a second one.
Steps¶
Install¶
sudo apt-get install ufw
Allow SSH first¶
Before any default-deny policy:
sudo ufw allow 22/tcp # or the port SSH was moved to
Set default policies¶
sudo ufw default deny incoming
sudo ufw default allow outgoing
Allow the services the server runs¶
sudo ufw allow 'Nginx Full' # opens 80 and 443
For a server moved to HTTPS only, allow Nginx Full then remove the redundant HTTP-only profile if it was added.
Enable¶
sudo ufw enable
UFW warns that enabling may disrupt existing SSH connections. With the SSH allow rule already in place, it will not.
Verify¶
sudo ufw status verbose
Confirm the listed allow rules match the intended port list and nothing else is open. From a second session, confirm SSH still connects. From outside the network, confirm a port that should be closed is in fact unreachable.
Done¶
Default inbound is deny. Only the intended ports are open. SSH still reachable. No unexpected ports in ufw status.
Rollback¶
sudo ufw disable
This removes all firewall rules and reverts to no filtering. Use it to recover access, then re-enable with the SSH rule in place. To remove a single rule rather than all of them, sudo ufw status numbered then sudo ufw delete <number>.
Follow-up¶
On a server running Docker, UFW rules may not reflect what is actually reachable: Docker inserts its own rules ahead of UFW. See the firewall overview and container stack.
Most firewall configurations leave outbound open. For servers holding sensitive data, scoped egress rules are worth considering.