How to set up a firewall with UFW on Ubuntu or Debian
A firewall makes sure only the doors you choose are open. For most web servers that is three: SSH, HTTP and HTTPS. UFW makes this a few commands.
1. Install UFW
Ubuntu usually has it already. On Debian, install it:
sudo apt update
sudo apt install ufw
2. Choose the defaults
Block everything coming in, allow everything going out:
sudo ufw default deny incoming
sudo ufw default allow outgoing
Nothing changes yet. The firewall is still off.
3. Allow SSH first
sudo ufw allow OpenSSH
If UFW says it can't find a profile called OpenSSH, use the port number instead: sudo ufw allow 22/tcp. If your SSH runs on another port, allow that port, for example sudo ufw allow 2222/tcp.
4. Allow your websites
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Port 80 is HTTP and 443 is HTTPS. Keep 80 open even if you only use HTTPS: it redirects visitors, and Let's Encrypt uses it to renew certificates.
5. Turn it on
sudo ufw enable
UFW warns that this may disconnect SSH. Because you allowed SSH in step 3, answer y. Then check:
sudo ufw status verbose
You should see Status: active, deny (incoming), and your three rules, each twice (once for IPv4, once for IPv6). The firewall stays on after a restart.
6. Test from a new window
Open a new terminal and log in with SSH. Open your website in a browser. If both work, you're done.
Everyday commands
- See rules with numbers:
sudo ufw status numbered - Remove a rule:
sudo ufw delete allow 80/tcp, or by number:sudo ufw delete 2 - Allow one address only (for example your office, for a database port):
sudo ufw allow from 203.0.113.10 to any port 3306 proto tcp - Behind Cloudflare? Allow ports 80 and 443 only from Cloudflare's addresses, with the script in our guide to locking your server to Cloudflare.
- Slow down password guessing on SSH:
sudo ufw limit OpenSSHblocks an address that opens 6 or more connections in 30 seconds. It replaces the plain allow rule. Skip it if your deploy tools open many SSH connections at once.
Don't open these to everyone
Databases (MySQL/MariaDB 3306, PostgreSQL 5432), Redis (6379) and Memcached (11211) should only listen on the server itself. If something outside must reach them, allow only that one address, as above. See our guides for MySQL and MariaDB and Redis, and how to find which ports are open.
Two things that catch people out
- Docker skips UFW. Ports published by Docker containers (
-p 8080:80) are reachable even when UFW says they're blocked, because Docker adds its own rules. Publish only to the server itself (-p 127.0.0.1:8080:80) and put a web server in front, or follow Docker's firewall guide. - Your hosting provider may have a firewall too. Many cloud providers have one in their control panel. A port must be open in both places to work. That's fine, and it adds a second layer.
If you get locked out
Use your hosting provider's web console (sometimes called VNC, rescue or serial console), log in there and run sudo ufw allow OpenSSH, or sudo ufw disable to switch the firewall off while you fix it.
Official sources
Next steps: use SSH keys and turn off password login, then work through the security checklist for a new PHP server.
ServerNest is being built to show your firewall rules in a dashboard and change them safely, with automatic undo if a change cuts off the connection. Join early access to try it first.