LinuxJuly 24, 2026 2 views

UFW: configure the firewall of your VPS Linux (Ubuntu/Debian)

UFW: configure the firewall of your VPS Linux (Ubuntu/Debian)

A well-configured server only exposes the strictly necessary services. Everything else should be closed, and that is precisely the role of a firewall. On Linux, network filtering relies on netfilter, historically driven by iptables, a powerful but notoriously dry syntax. UFW (Uncomplicated Firewall) is the official Ubuntu layer that makes this filtering accessible: a few readable commands are enough to lock down your machine.

This guide walks you through the steps to install and configure UFW on a Linux VPS running Ubuntu or Debian: default policies, allowing SSH without risking locking yourself out, opening web ports, advanced rules, logging, and the well-known pitfall of UFW being bypassed by Docker.

What is UFW and why use it?

UFW is not a full-fledged firewall: it is a simplified interface on top of iptables/nftables. Where iptables requires complex lines, UFW uses simple commands like ufw allow 443. It manages both incoming and outgoing traffic and allows filtering by port, protocol, named service, or source address.

The principle of a good firewall can be summed up in one sentence: block everything by default, then only open what is necessary. Specifically, we deny all incoming connections, allow all outgoing connections, and then add an exception for each service we want to make accessible (SSH, HTTP, HTTPS…).

Prerequisites

  • A VPS running Ubuntu 22.04/24.04 or Debian 11/12 with root access or a sudo user.
  • A functional SSH access and, most importantly, knowledge of the SSH port used (22 by default).
  • A warning to read before anything else: misconfiguring a firewall on a remote server is the best way to lock yourself out. Follow the order of the steps below to the letter: allow SSH before enabling UFW, never the other way around.

Installing UFW on Ubuntu and Debian

On Ubuntu, UFW is usually pre-installed. On Debian, it needs to be added. In both cases:

sudo apt update
sudo apt install -y ufw

Check the status of the service. Initially, UFW is inactive:

sudo ufw status

The response Status: inactive is normal: we will first set the rules, then activate it.

Setting default policies

We start with the basic rule: deny everything that comes in, allow everything that goes out. This is the foundation of a secure server.

sudo ufw default deny incoming
sudo ufw default allow outgoing

At this stage, if you were to enable UFW immediately, you would lose your SSH connection. That’s why the next step is imperative before activation.

Allow SSH (to be done BEFORE enabling UFW)

Allow the SSH service to avoid cutting off your access:

sudo ufw allow OpenSSH

OpenSSH is a predefined application profile that opens port 22. You can also specify the port directly:

sudo ufw allow 22/tcp

Have you changed the SSH port? This is a good security practice. In this case, replace 22 with your actual port, for example sudo ufw allow 2222/tcp. Check your port in /etc/ssh/sshd_config (directive Port) before enabling the firewall. To go further on hardening access, see the security path at the end of the article.

Enabling UFW

Once SSH is allowed, enable the firewall:

sudo ufw enable

UFW displays a warning indicating that the command may disrupt existing SSH connections. Since you allowed SSH just before, confirm with y. Your current connection remains open.

Check status and list rules

For a detailed status, including default policies and logging:

sudo ufw status verbose

To display the rules with their number necessary for deleting one later:

sudo ufw status numbered

You will get output like this:

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 443/tcp                    ALLOW IN    Anywhere

Opening ports for your services

This is the daily use of UFW: opening a port for each service you expose. UFW accepts several syntaxes.

By web service name (opens 80 and 443 at once):

sudo ufw allow 'Nginx Full'

This profile exists as soon as Nginx is installed; the equivalent for Apache is 'Apache Full'. If you are setting up a web server, complete it with our guide installing Nginx and PHP-FPM on a VPS.

By port number:

sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS
sudo ufw allow 25565/tcp   # example: game server

By port range:

sudo ufw allow 6000:6007/tcp

From a specific source address (only open a port to a trusted IP):

sudo ufw allow from 203.0.113.10 to any port 3306 proto tcp

This example only allows MySQL (port 3306) from the IP 203.0.113.10, ideal for a database that should never be exposed to the entire Internet. You can also target an entire subnet in CIDR notation (203.0.113.0/24).

Application profiles

UFW knows "profiles" that group the ports of an application, which avoids having to remember the numbers. List those available on your system:

sudo ufw app list

You will find, for example, OpenSSH, Nginx Full, Nginx HTTP, Nginx HTTPS, Apache Full… To know the details of the ports covered by a profile:

sudo ufw app info 'Nginx Full'

These profiles appear automatically as soon as compatible software is installed. They make your rules more readable: sudo ufw allow 'Nginx Full' is more understandable than sudo ufw allow 80,443/tcp.

Deleting a rule

Two methods. The safest way is through the number displayed by status numbered:

sudo ufw status numbered
sudo ufw delete 2

You can also delete a rule by rewriting it, preceded by delete:

sudo ufw delete allow 80/tcp

Advanced rules: limiting SSH connections

UFW offers built-in protection against brute force attacks: the limit rule. It temporarily blocks an IP that attempts too many connections in a short period (by default, more than 6 attempts in 30 seconds).

sudo ufw limit OpenSSH

This is a useful complement, but intentionally basic. For fine detection and lasting bans across all your services, combine UFW with Fail2ban (guide coming soon in this same path). The two tools are perfectly complementary: UFW decides which ports are open, Fail2ban decides which IPs deserve to be blocked.

Allow, deny, or reject: choosing the right action

UFW offers three main actions for incoming traffic, not to be confused:

  • allow allows the connection. This is what you use for your public services (SSH, web).
  • deny silently blocks the connection. The packet is ignored, with no response. The attacker does not know if the port is closed or filtered: this is the recommended behavior for an exposed server.
  • reject blocks the connection but sends a rejection message to the sender. Useful internally for quick diagnostics, less discreet against a scan.

In almost all cases on a public server, we keep the default policy deny incoming and add targeted allow rules. The reject remains reserved for specific situations where we want to explicitly signal that a port is closed.

The major pitfall: UFW and Docker

Here is the point that surprises the most administrators, and a real silent security flaw. Docker bypasses UFW. When you publish a container port (for example docker run -p 8080:80), Docker writes its own rules directly into iptables, upstream of those managed by UFW. The result: the port is accessible from the entire Internet even if ufw status claims to block it. Your firewall shows a protection that does not exist.

The reference solution is the open-source project ufw-docker, which reconciles the two. In summary:

  1. Add a dedicated configuration block at the end of /etc/ufw/after.rules (the repository provides the exact content to copy).
  2. Reload UFW: sudo ufw reload.
  3. Now manage access to containers with the dedicated syntax, for example:
sudo ufw route allow proto tcp from any to any port 8080

As long as this configuration is not in place, consider that any port published by Docker is open to the whole world. If you are using Docker on your server, treat this point as a priority.

Logging

To trace denied connections and diagnose a problem, enable logging:

sudo ufw logging on

Events are written to /var/log/ufw.log. You can adjust the level (low, medium, high, full) according to the desired volume. For a production server, low is usually sufficient and avoids saturating the logs.

Disabling or resetting UFW

To temporarily disable the firewall:

sudo ufw disable

To reset everything and start from a clean configuration (the rules are deleted):

sudo ufw reset

After a reset, remember to re-allow SSH before re-enabling UFW, or you risk locking yourself out.

Frequently Asked Questions

Does UFW replace iptables? No, it drives it. UFW generates iptables/nftables rules on your behalf. The two do not oppose each other: UFW is simply a more readable layer.

I locked myself out, what should I do? Use the rescue console (KVM/VNC) provided with your VPS to connect outside of SSH, then correct the rule or run sudo ufw disable. This is precisely to avoid this situation that you must allow SSH before enabling UFW.

Should I open ports in tcp or udp? Most services (SSH, HTTP, HTTPS) use TCP. Some services (WireGuard VPN, games, DNS) use UDP. Specify the protocol when you know it: sudo ufw allow 51820/udp.

Does UFW protect against DDoS attacks? Partially. It filters and can limit connections, but a volumetric attack is handled upstream, at the network level. UFW remains an essential building block of basic hygiene.

The path to securing your server

A properly configured firewall is the second step in a well-defended server. To complete the process on your Linux VPS, follow the complete path:

  1. SSH Keys replace the password with key-based authentication (guide coming soon).
  2. UFW close all unnecessary ports (you are here).
  3. Fail2ban automatically ban attackers who persist (guide coming soon).
  4. Certbot encrypt your services with a Let's Encrypt SSL certificate (guide coming soon).

Find all our tutorials in the Linux documentation. With UFW in place, your server only exposes what you have explicitly allowed, the foundation of any serious configuration.