Back to tutorials
Tutorial

UFW firewall setup tutorial (2026): Lock down a hosting VPS without breaking SSH, web, DNS, or email

UFW firewall setup tutorial for 2026: harden a hosting VPS safely with rules for SSH, web, DNS, and mail.

By Anurag Singh
Updated on Jul 28, 2026
Category: Tutorial
Share article
UFW firewall setup tutorial (2026): Lock down a hosting VPS without breaking SSH, web, DNS, or email

A firewall mistake is one of the fastest ways to take down a healthy server. This UFW firewall setup tutorial shows a safe, reversible rule set for a hosting VPS.

You’ll keep SSH access, serve web traffic, and expose DNS or email only when you actually run them.

If you manage client sites, reseller hosting, or a high-traffic WordPress install, you want a setup you can repeat. You also want it to behave the same way every time.

The goal is simple: reduce the exposed attack surface while keeping production services working.

What you’ll build (and what you should decide first)

By the end, UFW will enforce:

  • SSH allowed only from specific admin IPs (or a bastion/jump host), not from the whole internet.
  • HTTP/HTTPS open to everyone (your websites need it).
  • Optional: DNS (UDP/TCP 53) if your VPS is authoritative or recursive.
  • Optional: mail ports (25/465/587/110/995/143/993/4190) if you host email on the VPS.
  • Optional: control panel ports (cPanel/WHM) if you run them directly on the server.

Before you touch UFW, answer these:

  • Is this server public-facing for SSH, or do you have a jump host/VPN?
  • Do you run a panel (cPanel/WHM, Plesk, DirectAdmin), or is it a “plain” LEMP/LAMP stack?
  • Do you host DNS and email, or do you point MX/NS to another provider?

If you want a VPS where you can run a clean firewall and keep admin access consistent, start with a HostMyCode VPS.

If you’d prefer not to own every security detail yourself, managed VPS hosting is often a better fit for business-critical sites.

Prerequisites (Ubuntu/Debian; adjust if you’re on AlmaLinux/Rocky)

This tutorial assumes:

  • Ubuntu Server 24.04 LTS or 26.04 LTS, or Debian 12/13.
  • You have root access (or sudo) and console access via your provider panel as a safety net.
  • You know your current SSH port (default 22) and your admin IP(s).

Tip: If you don’t have an out-of-band console, stop here and add one.

Even a correct rule set can fail if your ISP changes your IP mid-session.

Step 1 — Identify what’s listening (don’t build rules on guesses)

Start by listing listening ports and which processes own them:

sudo ss -tulpn

On a typical hosting VPS you might see:

  • nginx or apache2 on 80/443
  • sshd on 22 (or another port)
  • named (BIND) on 53 if you host DNS
  • exim / postfix and dovecot for email
  • Panel services (cPanel/WHM uses several ports)

Now check your current firewall state. On fresh VPS installs, it’s often “nothing”:

sudo ufw status verbose

Step 2 — Install UFW and set safe defaults

Install UFW. On Ubuntu/Debian:

sudo apt update
sudo apt install -y ufw

Set the default policy first. This is the base layer you’ll open up on purpose:

sudo ufw default deny incoming
sudo ufw default allow outgoing

If you run Docker on the same VPS, be cautious. Docker can bypass UFW using iptables rules.

For most hosting stacks, it’s cleaner to avoid Docker unless you have a specific, tested reason to use it.

Step 3 — Allow SSH first (and test in a second session)

This step prevents the “locked out at 2 a.m.” situation. Add SSH rules before you enable the firewall.

If SSH is on port 22 and you want to allow it only from your office IP 203.0.113.10:

sudo ufw allow from 203.0.113.10 to any port 22 proto tcp

If your SSH runs on a custom port (example 2222):

sudo ufw allow from 203.0.113.10 to any port 2222 proto tcp

Best practice for teams: keep a small allowlist (office, home, VPN egress). Don’t open SSH to the world “just for convenience.”

If you want a clean model, put SSH behind a bastion. HostMyCode has a solid walkthrough here: SSH jump host setup tutorial.

Open a second SSH session now and confirm you can still connect.

Don’t move on until you’ve proven it works.

Step 4 — Allow web traffic (HTTP/HTTPS) for sites and renewals

Most hosting servers need 80/443 reachable publicly. Let’s Encrypt HTTP-01 challenges also rely on port 80.

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

If you use Let’s Encrypt, keep your renewal flow predictable.

If you haven’t automated renewals yet, follow: TLS certificate deployment tutorial.

Step 5 — Decide on DNS: authoritative nameserver vs “no DNS here”

If your VPS is not running BIND/PowerDNS and you aren’t serving zones, you usually don’t need inbound 53. For a web-only VPS, keeping DNS closed is often the right call.

If you are running a nameserver, allow both UDP and TCP on 53.

UDP handles most queries. TCP is used for large responses and zone transfers.

sudo ufw allow 53/udp
sudo ufw allow 53/tcp

Running cPanel nameservers has extra moving parts (glue, delegation, consistent IPs). If that’s your setup, read: cPanel nameserver setup guide.

Step 6 — Decide on email: only open what you actually use

Email is where misconfiguration turns into deliverability problems—or abuse complaints.

If your VPS doesn’t host mail, keep mail ports closed and point MX to a mail provider.

If you do host mail, this is a typical inbound set:

  • 25/tcp SMTP server-to-server (inbound mail)
  • 465/tcp SMTPS (implicit TLS) for clients (optional; still widely used)
  • 587/tcp Submission (recommended for authenticated clients)
  • 143/tcp IMAP (STARTTLS) and 993/tcp IMAPS
  • 110/tcp POP3 and 995/tcp POP3S (optional; many hosts disable POP)
  • 4190/tcp Sieve/ManageSieve (optional, for server-side mail filters)

Open only what your stack uses. Example (common IMAP + Submission):

sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp

If you run a cPanel mail stack (Exim + Dovecot), line up DNS authentication as well.

Ports get mail flowing; SPF/DKIM/DMARC/PTR keep it landing in inboxes. This companion guide covers the deliverability side: email authentication setup guide (SPF/DKIM/DMARC/PTR).

Step 7 — Control panel ports (cPanel/WHM) without exposing the world

If you’re running cPanel/WHM on a VPS or dedicated server, you’ll see traffic on these common ports:

  • 2087/tcp WHM over SSL
  • 2083/tcp cPanel over SSL
  • 2096/tcp Webmail over SSL

Decide what needs to be public. In most environments, WHM should never be open to the internet at large.

Even cPanel access is often limited to staff IPs, depending on your support model.

A safer default is to allow panel ports only from admin IPs.

Keep webmail public only if your users depend on it.

Example: allow WHM and cPanel only from your admin IP:

sudo ufw allow from 203.0.113.10 to any port 2087 proto tcp
sudo ufw allow from 203.0.113.10 to any port 2083 proto tcp

If your users rely on hosted webmail, you can keep 2096 public:

sudo ufw allow 2096/tcp

Need cPanel-focused hardening beyond firewalling? Pair this with: cPanel security hardening tutorial (account isolation, service exposure, and safer defaults).

Step 8 — Enable UFW safely (use the built-in grace check)

Before enabling, review the rules:

sudo ufw status numbered

Now enable:

sudo ufw enable

Keep your second SSH session open and test immediately:

  • SSH login from allowed IP works.
  • Website loads over HTTP and HTTPS.
  • If applicable: DNS answers queries; mail can receive; panel access works from allowed IPs.

Step 9 — Add rate-limiting for SSH (quick win, low drama)

UFW supports basic rate limiting. It’s not a replacement for Fail2Ban, but it does reduce noisy brute-force attempts:

sudo ufw limit 22/tcp

If you use a custom SSH port, apply it there instead:

sudo ufw limit 2222/tcp

Important: If you already restricted SSH with allow from <ip> rules, rate limiting the public port may not help much.

The strongest control is still “not reachable.”

Step 10 — Outbound mail and “why can’t my app send email?”

By default, we allowed all outgoing traffic. That’s practical for hosting.

Some admins still prefer to restrict outbound ports to reduce abuse risk.

If you choose to lock down outbound traffic, do it deliberately. Blocking outbound 25/587 commonly breaks:

  • WordPress contact forms (SMTP plugins)
  • Password reset emails
  • Transaction email relays

In many cases, monitoring and alerting is the safer first step.

If mail delivery goes sideways on cPanel, this tutorial works well as a runbook: cPanel mail queue troubleshooting tutorial.

Step 11 — Common hosting profiles (copy/paste templates)

Use these as starting points, not blind defaults.

Swap in your real admin IPs and your actual SSH port.

Profile A: “Web-only” VPS (Nginx/Apache + SSH allowlist)

sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing

# SSH from admin IP only
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp

# Web
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

sudo ufw enable

Profile B: Web + DNS (authoritative nameserver)

sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing

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

# DNS
sudo ufw allow 53/udp
sudo ufw allow 53/tcp

sudo ufw enable

Profile C: Web + Mail (basic inbound)

sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing

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

# SMTP + Submission + IMAPS
sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp

sudo ufw enable

Profile D: cPanel/WHM server (web public; panel restricted)

sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing

# SSH restricted
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp

# Web for sites and ACME
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# WHM/cPanel restricted to admin IP
sudo ufw allow from 203.0.113.10 to any port 2087 proto tcp
sudo ufw allow from 203.0.113.10 to any port 2083 proto tcp

# Webmail public only if needed
sudo ufw allow 2096/tcp

# Mail (adjust to your stack)
sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp

sudo ufw enable

Step 12 — Verification checklist (the part most people skip)

Run these checks after enabling UFW:

  • Firewall status: sudo ufw status verbose
  • Rule order sanity: sudo ufw status numbered
  • Confirm listening services: sudo ss -tulpn
  • From your laptop:
    • ssh user@server-ip (should work only from allowed IPs)
    • curl -I http://yourdomain
    • curl -I https://yourdomain

If a site suddenly throws 502/504 after firewalling, it’s rarely UFW. Those errors are usually upstream or app issues.

You still want a quick way to separate “network” from “stack.” Keep this nearby: VPS troubleshooting tutorial (502/504 on Nginx + PHP-FPM).

Fixes for the 5 mistakes that break hosting servers

1) You enabled UFW before allowing SSH

If you still have console access, disable UFW:

sudo ufw disable

Then add the SSH allow rule and re-enable.

2) You allowed SSH from the wrong IP (or your IP changed)

Temporary fix: allow SSH from anywhere, then narrow it back down after you regain access:

sudo ufw allow 22/tcp

3) DNS “randomly” fails because you allowed only UDP 53

Large DNS responses can require TCP. Add:

sudo ufw allow 53/tcp

4) Email clients can’t send mail because you forgot Submission (587)

Open it:

sudo ufw allow 587/tcp

5) You opened panel ports to the public internet

Remove the public rule and replace it with an allowlist. First find the rule number:

sudo ufw status numbered

Then delete (example rule 7):

sudo ufw delete 7

And add the IP-specific allow rule as shown earlier.

Operational habits: keep firewall changes boring

  • Change one thing at a time. Add a rule, test, then continue.
  • Keep a rollback path. Provider console access is non-negotiable for production.
  • Document intent. Maintain a short text file with why each non-obvious port exists.
  • Monitor after changes. A firewall is part of uptime, not a separate project.

If your hosting setup is expanding—more sites, more logins, more services—a managed platform can cost less than repeated incident response.

That’s exactly where managed VPS hosting tends to pay off.

If you want a VPS that’s predictable to harden and easy to operate, start with a HostMyCode VPS sized for real hosting workloads. If your team prefers guardrails—security updates, stability checks, and faster incident resolution—choose managed VPS hosting and keep your time focused on sites and clients.

FAQ

Should I use UFW on a cPanel/WHM server?

You can, but many cPanel servers standardize on CSF/LFD because it integrates tightly with WHM.

If you already run CSF, don’t stack two firewalls. Choose one and run it consistently.

Do I need to open port 80 if my sites are HTTPS-only?

Usually yes. Port 80 still matters for redirects and Let’s Encrypt validation.

If you only use DNS-01 challenges and enforce HTTPS everywhere, you can close 80—but test renewals first.

Why does DNS need TCP 53 if UDP works?

UDP handles most queries, but TCP is used for large responses and reliability cases.

Without TCP 53, some lookups fail intermittently, which is miserable to debug.

What’s the safest way to restrict SSH?

Use an IP allowlist plus SSH keys (no passwords), or put SSH behind a bastion host.

The key idea is reducing who can even attempt authentication.

Summary: a practical firewall posture for hosting in 2026

A good hosting firewall isn’t “deny everything.” It’s “deny everything you don’t run.”

Keep 80/443 open, restrict SSH and panel access to known IPs, and only open DNS/mail ports if the server actually provides those services.

If you’re building a clean hosting stack from scratch, a HostMyCode VPS gives you the control you need.

If you’d rather treat firewalling as one part of a broader managed posture, managed VPS hosting is the faster path to steady operations.