New articles: UFW firewall management, Fail2ban Apache 404 scanner jail, SELinux Fail2ban execmem fix, updating n8n Docker, Ansible SSH timeout during dnf upgrade, n8n proxy X-Forwarded-For fix, macOS mirrored notification alert loop. Updated dca→dcaprod reference in network overview. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.5 KiB
title, domain, category, tags, status, created, updated
| title | domain | category | tags | status | created | updated | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| UFW Firewall Management | selfhosting | security |
|
published | 2026-04-02 | 2026-04-02 |
UFW Firewall Management
UFW (Uncomplicated Firewall) is the standard firewall tool on Ubuntu. It wraps iptables/nftables into something you can actually manage without losing your mind. This covers the syntax and patterns I use across the MajorsHouse fleet.
The Short Answer
# Enable UFW
sudo ufw enable
# Allow a port
sudo ufw allow 80
# Block a specific IP
sudo ufw insert 1 deny from 203.0.113.50
# Check status
sudo ufw status numbered
Basic Rules
Allow by Port
# Allow HTTP and HTTPS
sudo ufw allow 80
sudo ufw allow 443
# Allow a port range
sudo ufw allow 6000:6010/tcp
# Allow a named application profile
sudo ufw allow 'Apache Full'
Allow by Interface
Useful when you only want traffic on a specific network interface — this is how SSH is restricted to Tailscale across the fleet:
# Allow SSH only on the Tailscale interface
sudo ufw allow in on tailscale0 to any port 22
# Then deny SSH globally (evaluated after the allow above)
sudo ufw deny 22
Rule order matters. UFW evaluates rules top to bottom and stops at the first match.
Allow by Source IP
# Allow a specific IP to access SSH
sudo ufw allow from 100.86.14.126 to any port 22
# Allow a subnet
sudo ufw allow from 192.168.50.0/24 to any port 22
Blocking IPs
Insert Rules at the Top
When blocking IPs, use insert 1 to place the deny rule at the top of the chain. Otherwise it may never be evaluated because an earlier ALLOW rule matches first.
# Block a single IP
sudo ufw insert 1 deny from 203.0.113.50
# Block a subnet
sudo ufw insert 1 deny from 203.0.113.0/24
# Block an IP from a specific port only
sudo ufw insert 1 deny from 203.0.113.50 to any port 443
Don't Accumulate Manual Blocks
Manual ufw deny rules pile up fast. On one of my servers, I found 30,142 manual DENY rules — a 3 MB rules file that every packet had to traverse. Use Fail2ban for automated blocking instead. It manages bans with expiry and doesn't pollute your UFW rules.
If you inherit a server with thousands of manual blocks:
# Nuclear option — reset and re-add only the rules you need
sudo ufw --force reset
sudo ufw allow 'Apache Full'
sudo ufw allow in on tailscale0 to any port 22
sudo ufw deny 22
sudo ufw enable
Managing Rules
View Rules
# Simple view
sudo ufw status
# Numbered (needed for deletion and insert position)
sudo ufw status numbered
# Verbose (shows default policies and logging)
sudo ufw status verbose
Delete Rules
# Delete by rule number
sudo ufw delete 3
# Delete by rule specification
sudo ufw delete allow 8080
Default Policies
# Deny all incoming, allow all outgoing (recommended baseline)
sudo ufw default deny incoming
sudo ufw default allow outgoing
UFW with Fail2ban
On Ubuntu servers, Fail2ban and UFW operate at different layers. Fail2ban typically creates its own nftables table (inet f2b-table) at a higher priority than UFW's chains. This means:
- Fail2ban bans take effect before UFW rules are evaluated
- A banned IP is rejected even if UFW has an ALLOW rule for that port
- Add trusted IPs (your own, monitoring, etc.) to
ignoreipin/etc/fail2ban/jail.localto prevent self-lockout
# /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 100.0.0.0/8
The 100.0.0.0/8 range covers all Tailscale IPs, which prevents banning fleet traffic.
UFW Logging
# Enable logging (low/medium/high/full)
sudo ufw logging medium
Logs go to /var/log/ufw.log. Useful for seeing what's getting blocked, but medium or low is usually enough — high and full can be noisy.
Fleet Reference
UFW is used on these MajorsHouse servers:
| Host | Key UFW Rules |
|---|---|
| majortoot | SSH on tailscale0, deny 22 globally |
| majorlinux | SSH on tailscale0, deny 22 globally |
| tttpod | SSH on tailscale0, deny 22 globally |
| teelia | SSH on tailscale0, deny 22 globally, Apache Full |
The Fedora servers (majorlab, majorhome, majormail, majordiscord) use iptables or firewalld instead.
See Also
- Linux Server Hardening Checklist — initial firewall setup as part of server provisioning
- Fail2ban & UFW Rule Bloat Cleanup — what happens when manual blocks get out of hand