Back to tutorials
Tutorial

Set Up UFW Firewall on Ubuntu for a Web Server

Set up UFW firewall on Ubuntu safely: allow SSH + web ports, add admin access, verify rules, and avoid lockouts on a VPS.

By Anurag Singh
Updated on Oct 16, 2026
Category: Tutorial
Share article
Set Up UFW Firewall on Ubuntu for a Web Server

Most firewall lockouts on a VPS happen in the first minute. People enable UFW before confirming that SSH is allowed, and the server goes dark.

This guide shows you how to set up UFW firewall on Ubuntu with a sensible web-server baseline (SSH + HTTP/HTTPS). Then you’ll add “admin-only” ports in a way that won’t strand you.

The steps below assume Ubuntu Server 22.04 LTS or 24.04 LTS on a VPS or dedicated server. For production sites, work from a stable network. Keep your provider’s console (out-of-band) access ready.

What you’ll build (and what it protects)

  • Default deny incoming traffic, allow outgoing.
  • Allow SSH (with a safer “allow from your IP” option).
  • Allow web traffic (80/443) for Nginx/Apache/LiteSpeed on a public IP.
  • Optional admin ports (like 8443, 2087, 10000) restricted to your IP range.
  • Verification using UFW status, real connection tests, and log checks.

Prerequisites and a quick safety checklist

Before you touch firewall rules, make sure these basics are true:

  • You have SSH access working now (don’t start from a flaky or half-broken session).
  • You know your SSH port (default 22 unless you changed it).
  • You know your public admin IP (home/office IP or your VPN egress IP).
  • You can reach a provider console for emergencies (most VPS providers offer a web console).

If you’re setting up HTTPS for the first time, pair this firewall baseline with our guide: SSL certificate setup with Let’s Encrypt.

Step 1: Identify what’s actually listening (don’t open ports blindly)

Start by checking what the server is listening on. Note which processes own those sockets:

sudo ss -tulpn

On a typical web server you’ll usually see:

  • nginx on :80 and :443
  • apache2 on :80 and :443
  • sshd on :22 (or another port)

If something unexpected is listening on a public interface, deal with that first.

A firewall is a backstop. It is not a reason to leave stray daemons exposed.

Step 2: Install and reset UFW to a known baseline

UFW is often present on Ubuntu, but don’t guess. Install it, then check the current state:

sudo apt update
sudo apt install -y ufw
sudo ufw status verbose

If you inherited this server, you may not know what rules exist. In that case, reset to a clean slate:

sudo ufw reset

Resetting clears UFW rules. By itself, it won’t lock you out.

Lockouts happen when you enable UFW without an SSH allow rule in place.

Step 3: Set safe defaults (deny inbound, allow outbound)

Apply the baseline defaults:

sudo ufw default deny incoming
sudo ufw default allow outgoing

This gives you a predictable posture. Nothing inbound works unless you explicitly permit it.

Step 4: Allow SSH first (two safe options)

Choose one approach. For production systems, restricting SSH to your admin IP is usually the right trade-off.

Option A (simple): allow SSH from anywhere

sudo ufw allow OpenSSH

Confirm the profile exists on your system:

sudo ufw app list | grep -i ssh

Option B (safer): allow SSH only from your IP

Find your current public IP from your workstation (not from the server). Then allow only that source:

sudo ufw allow from 203.0.113.10 to any port 22 proto tcp

If your SSH daemon runs on a non-standard port (example 2222), allow that port instead:

sudo ufw allow from 203.0.113.10 to any port 2222 proto tcp

Common mistake: restricting SSH to an IP that changes.

If your ISP rotates your address, use a VPN with static egress or a stable IP range you control.

Step 5: Allow web traffic (HTTP and HTTPS)

Public web servers need 80 and 443. You can use UFW’s application profiles, or open the ports directly.

If you use Nginx profiles

sudo ufw app list | grep -i nginx
sudo ufw allow 'Nginx Full'

If you prefer explicit ports

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

For most WordPress installs, PHP apps, and reverse-proxied services, that’s the full public surface area you want.

Step 6: Add admin ports without exposing them to the world

Admin panels and internal tooling often live on high ports. Treat those ports as private.

Allow them only from your admin IP (or a VPN range).

Examples you might actually run:

  • Plesk: 8443/tcp
  • Webmin: 10000/tcp
  • Custom app admin: 8080/tcp
  • Database remote access (usually avoid opening at all): 5432/tcp (Postgres), 3306/tcp (MySQL)

Restrict an admin panel to your IP:

sudo ufw allow from 203.0.113.10 to any port 8443 proto tcp

If you administer from multiple locations, add multiple rules. Or allow a VPN IP range:

sudo ufw allow from 198.51.100.0/24 to any port 8443 proto tcp

Don’t open database ports to the internet unless you have a clear reason and strong network controls.

For most site owners, keep MySQL/Postgres bound to localhost and connect over SSH tunneling.

Step 7: Enable UFW (only after SSH is allowed)

Once SSH is permitted, enable UFW:

sudo ufw enable

You’ll see a warning that existing SSH connections may be disrupted. If your SSH rule is correct, you should stay connected.

Then check status and rule order right away:

sudo ufw status verbose
sudo ufw status numbered

At a minimum, you should see SSH and 80/443 allowed.

Step 8: Verify from the outside (real tests that catch real mistakes)

Do three quick checks: web works, SSH works, and everything else is truly closed.

1) Test HTTP/HTTPS

From your workstation:

curl -I http://YOUR_SERVER_IP/
curl -Ik https://YOUR_DOMAIN/

A 200, 301, or 302 is fine.

If HTTPS fails, it’s usually TLS config or DNS, not UFW—unless 443 isn’t allowed.

2) Test SSH in a new session

Open a second terminal and connect fresh. Don’t trust the session you already have open:

ssh user@YOUR_SERVER_IP

If you used IP restriction, run this test from the IP you allowed. If it fails, fix the rule through console access.

3) Scan only the expected ports

If you have nmap locally:

nmap -Pn -p 1-10000 YOUR_SERVER_IP

On a basic web server, you should typically see only:

  • 22/tcp open (or your SSH port)
  • 80/tcp open
  • 443/tcp open
  • Any admin port open only if you intentionally exposed it

Step 9: Turn on logging (useful, but keep it controlled)

UFW logging helps you spot scans and misconfigurations. Start with “low” so you don’t drown in noise:

sudo ufw logging low

Check recent firewall messages:

sudo journalctl -u ufw --since "1 hour ago" --no-pager

On some systems, UFW logs show up through kernel logging instead. Search for blocks like this:

sudo journalctl -k --since "1 hour ago" | grep -i ufw

If logs grow fast, don’t just ignore it. Fix the cause.

It’s often bots hammering XML-RPC, wp-login, or random ports.

Also make sure log rotation is working. See our log rotation tutorial if /var fills up.

Step 10: Common UFW mistakes (and how to recover)

Mistake: enabling UFW before allowing SSH

Symptom: you get kicked out and can’t reconnect.

Fix: use your VPS provider console, log in, and run:

sudo ufw status numbered
sudo ufw allow OpenSSH
sudo ufw enable

Mistake: allowing the wrong SSH port

If SSH runs on 2222 but you allowed 22, UFW won’t help you.

Confirm your SSH daemon port:

sudo ss -tulpn | grep sshd
sudo grep -E '^Port ' /etc/ssh/sshd_config

Then allow the correct one:

sudo ufw allow 2222/tcp

Mistake: IPv6 traffic bypass assumptions

If your VPS has IPv6, firewall it too.

UFW can manage IPv6 if it’s enabled in /etc/default/ufw:

sudo sed -n '1,120p' /etc/default/ufw | grep -i ipv6

You generally want:

IPV6=yes

If you change it, reload rules:

sudo ufw disable
sudo ufw enable

Mistake: adding broad “allow 3306” or “allow 5432” rules

That invites credential stuffing and exploit scans. Keep databases private.

If you need remote access, use SSH tunnels or restrict access to a private network / fixed IP.

Optional: harden SSH along with UFW (recommended)

UFW reduces exposure. SSH hardening reduces the chance that a single weak setting turns into a real incident.

A solid minimum baseline:

  • Disable password logins; use SSH keys.
  • Disable root login; use a sudo user.
  • Limit who can SSH with AllowUsers.

If you want a clean, operator-friendly workflow for SFTP users too, follow our SFTP + SSH hardening tutorial.

Optional: rate-limit noisy traffic at the web layer

A firewall blocks ports. It won’t stop abusive requests on ports you intentionally allow.

If you’re seeing heavy traffic on /wp-login.php or API endpoints, add web-layer controls.

For Nginx, rate limiting is usually the quickest win: Nginx rate limiting tutorial.

UFW rules that work well for typical hosting stacks

These are “known good” patterns you can copy and adapt.

Basic web server (SSH + HTTP/HTTPS)

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Web server + restricted admin panel

sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.10 to any port 8443 proto tcp

Allow a health check endpoint source IP only (optional)

If an external uptime service checks your server from a fixed IP, you can restrict a dedicated status port (example 8081):

sudo ufw allow from 198.51.100.25 to any port 8081 proto tcp

Where this fits on real infrastructure (VPS vs dedicated vs shared)

On a VPS or dedicated server, UFW is your first network perimeter. It’s especially useful if you host multiple sites, run Docker, or keep admin services around.

On shared hosting, you don’t control the host firewall.

If you need custom ports, private admin access, or background app daemons, that’s usually the point where a VPS makes sense.

If you’re running production websites and want full root access without paying enterprise rates, start with a HostMyCode VPS. If you’d rather have patching, firewall baselines, and routine checks handled for you, managed VPS hosting is the calmer option.

Summary: your “don’t lock yourself out” UFW runbook

  1. Confirm what ports are listening with ss -tulpn.
  2. Reset UFW if rules are unknown: ufw reset.
  3. Default deny inbound / allow outbound.
  4. Allow SSH first (prefer allow-from-your-IP).
  5. Allow 80/443 for your web server.
  6. Restrict admin ports to your IP range.
  7. Enable UFW and verify from a new SSH session.
  8. Turn on low logging and watch for unexpected blocks.

If you need a production firewall with finer control (multiple interfaces, mail/DNS roles, explicit forwarding rules), see our iptables/nftables firewall tutorial.

If you want firewall control without guesswork, run your sites on a VPS where you own the network edge. HostMyCode offers predictable performance for common web stacks, plus optional help if you’d rather not manage security settings yourself.

Start with a HostMyCode VPS, or choose managed VPS hosting if you want a safer baseline from day one.

FAQ: set up UFW firewall on Ubuntu

Will UFW block Let’s Encrypt renewals?

Not if 80/tcp (for HTTP-01) or 443/tcp (for TLS-ALPN-01) is allowed. Most web servers keep 80 open and redirect to 443.

Should I allow “Nginx Full” or open 80/443 manually?

Either works. Profiles are convenient; manual ports are explicit.

If you’re troubleshooting, manual ports are often easier to reason about.

How do I remove a UFW rule safely?

List numbered rules, then delete by number:

sudo ufw status numbered
sudo ufw delete 3

Do I need to open ports for PHP-FPM, Redis, or MySQL?

No for typical single-server hosting. Those services should listen on localhost or a private interface and be reached by the web server locally.

What if I still get locked out?

Use your provider console to log in, run sudo ufw disable, then re-add an SSH allow rule and re-enable UFW.

If you want help migrating to a safer baseline, HostMyCode can assist via migrations for supported moves.