Back to tutorials
Tutorial

Linux VPS Firewall Setup with nftables (2026 Tutorial): Secure SSH, Web, and Control Panels Safely

Linux VPS firewall setup with nftables in 2026: lock down SSH, allow web traffic, and keep cPanel/Plesk reachable with safe rules.

By Anurag Singh
Updated on Apr 25, 2026
Category: Tutorial
Share article
Linux VPS Firewall Setup with nftables (2026 Tutorial): Secure SSH, Web, and Control Panels Safely

A firewall isn’t a checkbox. On a VPS, one careless rule can lock you out of SSH. It can also derail Let’s Encrypt renewals or block mail in subtle ways. You may not notice until customers complain.

This Linux VPS firewall setup tutorial shows how to configure nftables on Ubuntu 24.04 LTS and AlmaLinux/Rocky Linux 9/10. You’ll also get validation steps and a rollback plan. That way, you can change rules without gambling on access.

If you want to run WordPress, a LAMP/LEMP stack, or a control panel, don’t leave random ports exposed. Start with a tight inbound policy. Then add only what you need.

For production work, a HostMyCode VPS gives you a clean baseline. You get predictable networking, root access, and enough headroom to apply security changes safely.

What you’ll build (and what this firewall will allow)

By the end, your VPS will:

  • Allow inbound SSH (with guardrails to reduce lockout risk)
  • Allow inbound HTTP/HTTPS for Apache or Nginx
  • Optionally allow ports for cPanel/WHM, Plesk, or DirectAdmin (ideally restricted by source IP)
  • Allow established/related traffic, drop invalid packets, and enforce a default-deny inbound policy
  • Log suspicious inbound attempts without spamming your disk

Assumptions: you have console access via your provider panel (or a “rescue console”). If you don’t, plan a maintenance window.

Confirm your recovery path before you touch firewall rules.

Before you touch rules: quick safety checklist

  • Open a second SSH session and leave it idle while you change rules.
  • Confirm your SSH port and listening address:
ss -tulpn | grep -E 'ssh|:22'
sshd -T | grep -E 'port|listenaddress'
  • Note your current public IP (from your laptop):
curl -s https://ifconfig.me
  • On the VPS, confirm your default interface name (often eth0 or ens3):
ip -br link

If the VPS already serves traffic, keep a troubleshooting reference nearby.

HostMyCode’s VPS hosting troubleshooting checklist is useful once you start tightening access. It also helps when you need quick sanity checks.

Linux VPS firewall setup on Ubuntu 24.04 with nftables

Ubuntu 24.04 ships with nftables. You’ll manage the service and keep your rules in one file: /etc/nftables.conf.

Step 1: Install and enable nftables

sudo apt update
sudo apt install -y nftables
sudo systemctl enable --now nftables
sudo systemctl status nftables --no-pager

Step 2: Create a ruleset with a safe default-deny inbound policy

Start by backing up whatever is there now.

sudo cp -a /etc/nftables.conf /etc/nftables.conf.bak.$(date +%F)

Edit /etc/nftables.conf:

sudo nano /etc/nftables.conf

This ruleset is intentionally small. Outbound stays open (typical for VPS hosting).

Inbound traffic is dropped unless you explicitly allow it.

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
  set admin_ips {
    type ipv4_addr
    elements = { 203.0.113.10 }  # Replace with your office/home public IP
  }

  chain input {
    type filter hook input priority 0;
    policy drop;

    # Always allow loopback
    iif "lo" accept

    # Drop clearly broken traffic
    ct state invalid drop

    # Allow established connections (SSH sessions, HTTP keep-alives, etc.)
    ct state established,related accept

    # ICMP for basic diagnostics (ping, PMTU)
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept

    # SSH (prefer: restrict to admin_ips; or open to 0.0.0.0/0 if you must)
    tcp dport 22 ip saddr @admin_ips accept

    # Web
    tcp dport { 80, 443 } accept

    # Optional: control panels (restrict to admin IPs)
    # cPanel/WHM: 2083,2087,2086,2096,2095
    # Plesk: 8443,8880
    # DirectAdmin: 2222
    # tcp dport { 2083, 2087, 2096, 8443, 2222 } ip saddr @admin_ips accept

    # Optional: mail server ports (only if you run Postfix/Dovecot here)
    # tcp dport { 25, 465, 587, 110, 995, 143, 993 } accept

    # Rate-limited logging for drops
    limit rate 10/minute burst 20 packets log prefix "nft-in-drop: " flags all counter
  }

  chain forward {
    type filter hook forward priority 0;
    policy drop;
  }

  chain output {
    type filter hook output priority 0;
    policy accept;
  }
}

Important: replace 203.0.113.10 with your real admin IP.

If your ISP rotates IPs often, use a stable VPN exit IP.

Or temporarily open SSH while you finish the rest of the setup.

Step 3: Validate the config before applying

sudo nft -c -f /etc/nftables.conf

If validation passes, apply it:

sudo nft -f /etc/nftables.conf
sudo nft list ruleset

Step 4: Verify you didn’t lock yourself out

  • From your laptop, open a new SSH connection.
  • Test web ports from outside (replace with your VPS IP):
curl -I http://YOUR_SERVER_IP
curl -Ik https://YOUR_SERVER_IP

If HTTPS fails because you don’t have a certificate yet, that’s expected.

You’re checking reachability, not browser trust.

Linux VPS firewall setup on AlmaLinux/Rocky Linux with nftables

On RHEL-family systems, firewalld is often enabled by default. You can absolutely stick with it.

This guide uses nftables directly, so the rules and workflow match the Ubuntu section.

If you already depend on firewalld zones and services, don’t swap tools casually. Plan the migration.

Step 1: Check what’s managing your firewall

sudo systemctl is-active firewalld || true
sudo systemctl is-active nftables || true

If firewalld is active, you have two safe paths:

  • Path A (recommended if you’re used to firewalld): keep firewalld and configure it (not covered here).
  • Path B: disable firewalld and run nftables directly (covered below).

Step 2 (Path B): Switch to nftables

sudo systemctl disable --now firewalld
sudo dnf install -y nftables
sudo systemctl enable --now nftables
sudo systemctl status nftables --no-pager

Then create /etc/nftables.conf (use the same ruleset as Ubuntu).

Validate it, then apply it:

sudo bash -lc 'cp -a /etc/nftables.conf /etc/nftables.conf.bak.$(date +%F) 2>/dev/null || true'
sudo nano /etc/nftables.conf
sudo nft -c -f /etc/nftables.conf
sudo nft -f /etc/nftables.conf
sudo nft list ruleset

Adding rules for Apache, Nginx, and Let’s Encrypt without surprises

For most VPS web hosting, inbound traffic only needs ports 80 and 443.

Let’s Encrypt HTTP-01 validation still relies on port 80, even if you force HTTPS everywhere.

Block 80 and renewals often break.

  • Keep tcp dport 80 open unless you use DNS-01 challenges.
  • If the VPS terminates TLS (typical for Nginx/Apache), keep tcp dport 443 open.

If you want DNS-based validation (common for wildcard certs), you’ll automate it at your DNS provider instead of exposing port 80. That’s a different workflow; see HostMyCode’s guide on ACME DNS challenge automation.

Control panels (cPanel/WHM, Plesk, DirectAdmin): restrict by IP

Control panels are high-value targets. Don’t leave panel logins open to the world unless you’re forced to.

The clean pattern with nftables is simple.

Allow panel ports only from your admin IP set.

Example: allow WHM/cPanel/Plesk/DirectAdmin from admin IPs only:

# In /etc/nftables.conf input chain

tcp dport { 2083, 2087, 2096, 8443, 2222 } ip saddr @admin_ips accept

If you manage multiple sites or client accounts, a panel can save hours—assuming you lock it down.

HostMyCode’s comparison of VPS control panels walks through the practical trade-offs.

Optional: mail ports (only if you run mail on the VPS)

Many site owners shouldn’t run mail on the same VPS as their app. Deliverability, DNS, rDNS, and reputation management take time. They also need ongoing attention.

If you do run Postfix/Dovecot, your firewall needs the right inbound ports.

Open them only if the services are actually listening.

Common inbound mail ports:

  • 25/tcp SMTP (server-to-server)
  • 587/tcp Submission (client sending)
  • 465/tcp SMTPS (legacy, still used)
  • 143/993 IMAP/IMAPS
  • 110/995 POP3/POP3S (less common)

Confirm the services are listening before you open anything:

ss -tulpn | grep -E ':(25|465|587|110|995|143|993)\b' || true

Then uncomment the mail ports line in the sample ruleset.

For the DNS and reputation side, use HostMyCode’s VPS email deliverability checklist before you expect consistent inbox placement.

Logging without filling your disk (and how to watch drops)

The sample config logs drops with rate limiting.

That’s the difference between useful signals and a brute-force attempt eating gigabytes overnight.

On Ubuntu, check logs with:

sudo journalctl -k -g 'nft-in-drop' --since '1 hour ago' --no-pager

On AlmaLinux/Rocky Linux, journald also works on most modern builds:

sudo journalctl -k -g 'nft-in-drop' --since '1 hour ago' --no-pager

To avoid “disk full” surprises, pair logging with rotation you’ve actually tested.

HostMyCode’s tutorial on Linux VPS log rotation is a solid baseline.

Common pitfalls (the stuff that causes midnight outages)

  • Locking out SSH: you restrict SSH to an IP, then your ISP changes it. Keep console access available, or use a stable VPN exit IP.
  • Blocking port 80: Let’s Encrypt HTTP-01 renewals fail. If you want to close 80, switch to DNS-01 and automate it properly.
  • Forgetting IPv6: if your VPS has IPv6 enabled, handle ICMPv6 and decide whether you’ll serve sites over IPv6. The sample ruleset supports basic IPv6 diagnostics.
  • Running multiple firewalls: firewalld plus direct nftables rules can produce confusing results. Choose one control plane.
  • Assuming “default allow outbound” is always fine: for sensitive apps, you may want outbound restrictions. Get inbound right first, then tighten per service.

Quick diagnostics: prove your firewall does what you think

Don’t rely on assumptions. Test from outside the VPS.

Then confirm counters move.

From your laptop: scan only the ports you care about

# Replace with your server IP or hostname
nmap -Pn -p 22,80,443 YOUR_SERVER_IP

On the VPS: confirm nftables is loaded and counters increase

sudo nft list ruleset
sudo nft list chain inet filter input

After you generate traffic (SSH login, curl to 80/443), you should see counters increment on accept/log rules.

Check that your services still listen

ss -tulpn | head
sudo systemctl --type=service --state=running | grep -E 'nginx|apache2|httpd|mysqld|mariadb|php-fpm|sshd' || true

If a site gets slow or starts throwing 502s after unrelated changes, don’t blame the firewall by default.

Use a structured checklist.

HostMyCode’s Linux VPS setup checklist helps you validate the rest of the stack.

Rollback plan: how to recover fast if you break access

Decide on your rollback before you apply any new rules.

You want a quick, boring recovery—especially if SSH drops.

  • Keep console access via your hosting provider panel.
  • Keep a known-good backup of /etc/nftables.conf.

Rollback commands (from console):

# Restore backup
sudo cp -a /etc/nftables.conf.bak.YYYY-MM-DD /etc/nftables.conf

# Apply
sudo nft -f /etc/nftables.conf

# Or flush everything (last resort; opens inbound until you reapply rules)
sudo nft flush ruleset

Where this fits in a real hosting baseline

A firewall is one layer, not the whole story. For a production VPS (WordPress, SaaS, client workloads), pair this with:

  • SSH hardening (keys, no root login, limited users)
  • Automatic security updates with controlled reboots
  • Backups with restore tests
  • Basic monitoring for disk, RAM, load, and HTTP status

If you start seeing OOM kills after adding services, the limit is usually memory. It’s not networking.

This tutorial on swap tuning with zram is a practical fix on smaller VPS plans.

Want to apply firewall rules, SSL, and performance tuning without dealing with noisy neighbors or unpredictable networking? Start with a VPS built for hands-on administration. Choose a HostMyCode VPS for full control, or step up to managed VPS hosting if you want experts handling day-2 operations.

FAQ

Should I use UFW instead of nftables on Ubuntu?

UFW works well for basic allow/deny needs. But nftables gives you clean sets (like admin_ips) and a consistent approach across Ubuntu and RHEL-family systems.

If UFW already works for you, there’s no need to switch just for the sake of it.

Do I need to open MySQL or PostgreSQL ports to the internet?

Usually no. Bind databases to localhost or a private network. If you truly need remote access, restrict by source IP and use TLS.

Public database ports get probed constantly.

What ports do I need for WordPress hosting?

WordPress only needs 80/443 reachable from the internet. Keep SSH (22) restricted to your admin IPs. On a single-server setup, database ports should not be public.

How do I allow Cloudflare or a load balancer to reach my VPS?

Allow 80/443 from the proxy IP ranges (Cloudflare publishes lists), and optionally block direct traffic to your origin.

That’s a stricter setup than the baseline here—test carefully so you don’t break health checks.

Why does ping work but my site is down?

ICMP only proves the host answers ping. HTTP/HTTPS may be blocked by firewall rules, the web service may be stopped, or the reverse proxy may be misrouted.

Verify listening ports with ss -tulpn and test with curl -I.

Summary: a safer default for internet-facing VPS hosting

You now have nftables enforcing a default-deny inbound policy. You also have explicit allows for SSH and web traffic. You have a simple pattern for IP-restricted control panel access.

That’s a sane perimeter for a VPS in 2026. It’s predictable, easy to audit, and straightforward to extend.

If you plan to host multiple sites, install a panel, or migrate customer workloads, put this baseline in first.

Then layer services on top.

When you’re ready, a HostMyCode VPS or dedicated server gives you the isolation and control you want for reliable hosting operations.