By Shaun Lewis and Manikandan Kurup

Setting up a functioning firewall is crucial to securing your cloud server. Previously, setting up a firewall was done through complicated or arcane utilities. Many of these utilities, such as iptables, have a lot of functionality built into them, but they require extra effort from the user to learn and understand.
Another option is UFW, or Uncomplicated Firewall. UFW is a front-end to the kernel’s netfilter system that aims to provide a more user-friendly interface than other firewall management utilities. UFW is well-supported in the Linux community and is installed by default on Ubuntu, where it ships disabled until you enable it.
In this tutorial, you will set up a firewall using UFW to secure an Ubuntu or Debian cloud server. You will install UFW where it is not already present, set default rules to allow or deny connections, open ports for specific services and IP addresses, use application profiles, enable logging, delete rules, and reset everything back to default settings.
Key takeaways
netfilter firewall, sparing you the complexity of raw iptables or nftables rules.sudo apt install ufw.nftables backend on current Ubuntu and Debian through the iptables-nft compatibility layer, while the commands you type stay the same.sudo ufw allow OpenSSH or sudo ufw allow ssh) before running sudo ufw enable, or you risk locking yourself out of a remote server.sudo ufw limit ssh adds basic brute-force protection by capping new connections at six per 30 seconds from a single IP address.sudo ufw status verbose shows the active rules, default policies, and logging level in one place.IPV6=yes is set in /etc/default/ufw, which is the default on modern systems.sudo ufw reset backs up and removes all user-defined rules, disables the firewall, and resets the default policies to deny incoming and allow outgoing.To follow this tutorial, you will need a server running either Ubuntu or Debian. Your server should have a non-root user with sudo privileges.
The steps in that guide apply equally to Debian 12 and Debian 13. Both of these initial server setup guides help you create a secure environment that you can use to practice creating firewall rules.
Once you have a sudo user ready, you can move on to understanding what UFW does before you configure it.
UFW does not replace the firewall in the Linux kernel; it manages it. The kernel filters network traffic through its netfilter framework, which administrators traditionally configure with iptables or, more recently, nftables. Writing those rules by hand is powerful but error-prone. UFW sits on top of that machinery and translates short, readable commands such as sudo ufw allow ssh into the lower-level rules the kernel enforces.
On current Ubuntu and Debian releases, UFW 0.36.x uses the nftables backend through the iptables-nft compatibility layer, so even when you think in iptables terms, the rules are applied through nftables under the hood. This change is transparent: the UFW commands in this guide are identical regardless of the backend.
To see which version is installed, run the following:
- sudo ufw version
The command reports the UFW version and license, similar to the following:
ufw 0.36.2
Copyright 2008-2023 Canonical Ltd.
UFW is not the only option, so the following table compares it with the two other common Linux firewall tools to help you choose the right one for your environment.
| Tool | Interface | Default On | Best For |
|---|---|---|---|
| UFW | Simple command line (ufw allow ssh) |
Ubuntu (easily added to Debian) | Single servers and straightforward rule sets |
| firewalld | Zone-based, firewall-cmd |
RHEL, Rocky Linux, Fedora | Dynamic environments with multiple network zones |
| iptables / nftables | Low-level rule syntax | All distributions | Fine-grained control, complex routing or NAT |
For most single Ubuntu or Debian cloud servers, UFW is the simplest choice that still gives you complete control. Choose firewalld if you are on a Red Hat family system or need zone-based management, and reach for raw nftables only when you need advanced features that the front-ends do not expose.
On Ubuntu, UFW is installed by default, so you usually do not need to install anything. You can confirm it is present by checking its status:
- sudo ufw status
If UFW is installed but not yet enabled, the output is simply:
Status: inactive
On Debian, UFW is available in the standard repositories but is not installed by default. Install it with apt:
- sudo apt update
- sudo apt install ufw
Note for Debian users: Installing the ufw package does not enable the firewall automatically. UFW stays inactive until you run sudo ufw enable, which gives you time to add an SSH rule first so you do not lock yourself out. The rest of this guide applies identically to Ubuntu and Debian unless a step says otherwise.
With UFW installed, the next step is to make sure it handles IPv6 traffic correctly.
If your Virtual Private Server (VPS) is configured for IPv6, ensure that UFW is set to support IPv6 so it configures both your IPv4 and IPv6 firewall rules. To do this, open the UFW configuration file in your preferred text editor. This example uses nano:
- sudo nano /etc/default/ufw
Confirm that IPV6 is set to yes. On modern Ubuntu and Debian this is already the default:
# /etc/default/ufw
#
# Set to yes to apply rules to support IPv6 (no means only IPv6 on loopback
# accepted). You will need to 'disable' and then 'enable' the firewall for
# the changes to take effect.
IPV6=yes
…
After you make your changes, save and exit the file. If you are using nano, press CTRL + X, then Y, and then ENTER.
For any change to /etc/default/ufw to take effect, restart the firewall by first disabling it:
- sudo ufw disable
Disabling the firewall returns the following confirmation:
Firewall stopped and disabled on system startup
Then enable it again:
- sudo ufw enable
Re-enabling the firewall confirms it is active:
Firewall is active and enabled on system startup
Your UFW firewall is now set up to handle both IPv4 and IPv6. Next, you will adjust the default rules that apply to connections.
You can improve your firewall’s efficiency by defining default rules for allowing and denying connections. UFW’s default is to deny all incoming connections and allow all outgoing connections. This means anyone trying to reach your server cannot connect, while any application within the server can still connect out. To set these rules explicitly, first address the incoming connections rule:
- sudo ufw default deny incoming
Setting the incoming policy returns the following:
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)
Next, address the outgoing connections rule:
- sudo ufw default allow outgoing
Setting the outgoing policy returns a similar confirmation:
Default outgoing policy changed to 'allow'
(be sure to update your rules accordingly)
Note: If you want to be more restrictive, you can deny all outgoing requests. This option is based on personal preference. For example, on a public-facing cloud server it can help prevent unwanted outbound connections such as remote shells. It does make your firewall more cumbersome to manage, because you have to add rules for every outgoing connection you want to allow. You can set this as the default with the following:
- sudo ufw default deny outgoing
Allowing connections requires changing the firewall rules, which you do by issuing commands in the terminal. If you enabled your firewall right now, it would deny all incoming connections. If you are connected over SSH, this would be a problem because you would be locked out of your server. Prevent this by allowing SSH connections before you enable UFW:
- sudo ufw allow ssh
If your change was successful, you receive the following output:
Rule added
Rule added (v6)
UFW understands some service names out of the box, such as the ssh keyword used above. Alternatively, you can allow incoming connections to port 22/tcp, which uses Transmission Control Protocol (TCP) to accomplish the same thing:
- sudo ufw allow 22/tcp
If you run this after you have already run allow ssh, UFW tells you the rule already exists:
Skipping adding existing rule
Skipping adding existing rule (v6)
If your SSH server runs on a non-standard port such as 2222, allow connections with the same syntax but the different port. If you specify the port number by itself, the rule applies to both tcp and udp, so naming the protocol is more precise:
- sudo ufw allow 2222/tcp
Allowing the custom port returns the same confirmation as before:
Rule added
Rule added (v6)
To reduce the risk of brute-force login attempts, you can rate-limit SSH instead of simply allowing it. The limit command caps new connections at six within 30 seconds from any single IP address:
- sudo ufw limit ssh
Web servers such as Apache and Nginx listen for HTTP requests on port 80 and HTTPS requests on port 443. To serve unencrypted traffic, allow connections to port 80/tcp:
- sudo ufw allow 80/tcp
To serve encrypted HTTPS traffic, also allow port 443/tcp:
- sudo ufw allow 443/tcp
UFW provides named application profiles for common web servers, which is often cleaner than remembering port numbers. For example, if Nginx is installed you can allow HTTP traffic using its profile name:
- sudo ufw allow 'Nginx HTTP'
If Apache is installed instead, use the Apache profile:
- sudo ufw allow 'Apache'
If you prefer to allow by port number regardless of which web server is installed, the equivalent command is:
- sudo ufw allow 80/tcp
File Transfer Protocol (FTP) is unrelated to web traffic and uses its own ports: 21 for control and 20 for data transfer. If you specifically need an FTP server, allow the control port by name:
- sudo ufw allow ftp
Allowing by name is equivalent to allowing port 21/tcp directly:
- sudo ufw allow 21/tcp
For active-mode FTP connections, you also need to allow the data port 20:
- sudo ufw allow 20/tcp
Note: Most modern FTP deployments use passive mode rather than active mode. Passive mode requires opening an additional range of high-numbered ports beyond 20 and 21. The exact range is configured in your FTP server (for example, pasv_min_port and pasv_max_port in vsftpd.conf, or PassivePorts in proftpd.conf). Once you know that range, open it with a rule such as sudo ufw allow 49152:65535/tcp. Consult your FTP server’s documentation for the correct values before exposing a passive port range.
Your adjustments depend on which ports and services you need to open, and some testing may be necessary. Remember to leave your SSH connection allowed as well.
You can specify ranges of ports to allow or deny with UFW. To do this, specify the port at the low end of the range, follow it with a colon (:), then the high end of the range, and finally the protocol (either tcp or udp).
For example, the following command allows TCP access to every port from 1000 to 2000, inclusive:
- sudo ufw allow 1000:2000/tcp
Likewise, the following command denies UDP connections to every port from 1234 to 4321:
- sudo ufw deny 1234:4321/udp
Many important services use UDP rather than TCP. DNS, NTP, and VPN protocols such as WireGuard all rely on UDP, so you need to specify udp explicitly when writing rules for them. The following examples show how to allow the WireGuard VPN port and the DNS port over UDP:
- sudo ufw allow 51820/udp
- sudo ufw allow 53/udp
You can allow connections from a specific IP address. Be sure to replace the example address with your own:
- sudo ufw allow from your_server_ip
To restrict that allowance to a single port, append to any port and the port number, which is a common pattern for limiting SSH to a trusted address:
- sudo ufw allow from your_server_ip to any port 22
As these examples show, you have a lot of flexibility when adjusting firewall rules by selectively allowing certain ports and IP addresses. Check out our guide to learn more about allowing incoming connections from a specific IP address or subnet.
When you install network software, it often registers a UFW application profile, which is a named bundle of the ports that service needs. Using profiles keeps your rules readable. To see which profiles are available on your system, list them:
- sudo ufw app list
The output shows the registered profiles, which vary depending on what you have installed:
Available applications:
Apache
Apache Full
Apache Secure
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
To see exactly which ports a profile opens, ask for its details:
- sudo ufw app info 'Nginx Full'
The profile description lists the ports it covers, in this case both HTTP and HTTPS:
Profile: Nginx Full
Title: Web Server (Nginx, HTTP + HTTPS)
Description: Small, but very powerful and efficient web server
Ports:
80,443/tcp
Once you know what a profile does, allow it by name to open all of its ports at once:
- sudo ufw allow 'Nginx Full'
Using the OpenSSH profile is the recommended way to permit SSH, since it is clearer than a bare port number and is the form most initial-server-setup guides use.
When a package is upgraded, its application profile may change to reflect new or updated ports. To make sure UFW is using the latest version of a profile, run ufw app update with the profile name after upgrading the corresponding package:
- sudo ufw app update 'Nginx Full'
To refresh all registered profiles at once, omit the profile name:
- sudo ufw app update all
You can confirm the current list of registered profiles at any time with:
- sudo ufw app list
If you wanted to open all of your server’s ports, which is not recommended, you could allow all connections and then deny only the ports you want to block. The following example denies access to port 80:
- sudo ufw deny 80/tcp
You can deny by service name or application profile in the same way, for example sudo ufw deny ftp. Denying is also useful for temporarily blocking a service without deleting its allow rule permanently.
If you want to delete some of the rules you created, use delete and specify the rule you want to remove:
- sudo ufw delete allow 80/tcp
Removing the rule returns the following:
Rule deleted
Rule deleted (v6)
If the rules are long or complex, there is an alternative two-step approach. First, generate a numbered list of current rules:
- sudo ufw status numbered
The numbered list lets you see each rule and the index you will use to delete it:
Status: active
To Action From
-- ------ ----
[ 1] OpenSSH ALLOW IN Anywhere
[ 2] 22/tcp ALLOW IN Anywhere
[ 3] 2222/tcp ALLOW IN Anywhere
[ 4] 80 ALLOW IN Anywhere
[ 5] 20/tcp ALLOW IN Anywhere
…
With the numbered list in front of you, delete a rule by referring to its number. For example, if port 80 is number 4 on the list, use the following. You may be prompted to confirm with y (yes) or n (no):
- sudo ufw delete 4
Confirming the prompt deletes the rule:
Deleting:
allow 80
Proceed with operation (y|n)? y
Rule deleted (v6)
Once you have defined all the rules you want to apply to your firewall, you can enable UFW so it starts enforcing them. If you are connecting via SSH, make sure you have allowed your SSH port, commonly port 22, before enabling. Otherwise, you could lock yourself out of your server:
- sudo ufw enable
Enabling the firewall confirms it is now active and will start on boot:
Firewall is active and enabled on system startup
To confirm your changes went through, check the status to review the list of rules:
- sudo ufw status
The status output lists each active rule and the action UFW takes:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
22/tcp ALLOW Anywhere
2222/tcp ALLOW Anywhere
20/tcp ALLOW Anywhere
80/tcp DENY Anywhere
…
For a more comprehensive view that also shows the default policies and logging level, use verbose:
- sudo ufw status verbose
To disable UFW at any time, run the following:
- sudo ufw disable
Disabling the firewall stops it and removes it from startup:
Firewall stopped and disabled on system startup
Logging records the traffic UFW handles, which is invaluable for spotting blocked connection attempts and debugging your rules. Turn logging on with the following:
- sudo ufw logging on
UFW supports several logging levels, so you can balance detail against log volume. Set a level by name:
- sudo ufw logging medium
The available levels are low (logs blocked packets that do not match the policy), medium (adds logging of new connections and some matched packets), high (logs with rate limiting and more detail), and full (logs everything with no rate limit). On most cloud servers, low or medium is a good balance. UFW writes its entries to /var/log/ufw.log, where you can review them:
- sudo tail /var/log/ufw.log
To confirm that logging is active and to see which level is currently set, run:
- sudo ufw status verbose
The output includes a Logging: line such as Logging: on (medium) that shows the active level alongside your rules and default policies.
If for some reason you need to clear your server’s rules and start over, you can do so with the ufw reset command. You receive a prompt to confirm with y or n before resetting, since doing so can disrupt existing SSH connections:
- sudo ufw reset
UFW backs up your current rule files before clearing them, then disables itself:
Resetting all rules to installed defaults. This may disrupt existing ssh
connections. Proceed with operation (y|n)? y
Backing up 'user.rules' to '/etc/ufw/user.rules.20220217_190530'
Backing up 'before.rules' to '/etc/ufw/before.rules.20220217_190530'
Backing up 'user6.rules' to '/etc/ufw/user6.rules.20220217_190530'
Backing up 'before6.rules' to '/etc/ufw/before6.rules.20220217_190530'
Resetting disables UFW and deletes any rules you previously defined. It also restores the default policies (deny incoming and allow outgoing). After a reset, re-allow required services (especially SSH) and then re-enable the firewall.
A few problems come up often when you first work with UFW. The following subsections cover each one with its specific fix.
This is the most common UFW problem, and it happens when you run sudo ufw enable without first allowing your SSH port, so the default deny-incoming policy blocks your own session. If you still have an open terminal, add the SSH rule immediately with sudo ufw allow OpenSSH and the existing session will continue to work. If you have already been disconnected, use your provider’s web console or recovery console to log in locally, then run sudo ufw allow OpenSSH before reconnecting over SSH. To avoid this entirely, always allow SSH before enabling the firewall.
UFW rules are saved to disk and reloaded on boot once the firewall is enabled, so persistence problems usually mean UFW itself is not enabled to start at boot. Confirm the service is active and enabled with sudo ufw status verbose, which should report Status: active. If it reports inactive after a reboot, run sudo ufw enable (which also registers it for startup) and, on systems using systemd, confirm the unit is enabled with sudo systemctl enable ufw.
If your IPv4 rules work but IPv6 traffic is not being filtered as expected, the cause is almost always that IPv6 support is turned off in the configuration. Open /etc/default/ufw and confirm that IPV6=yes is set, then reload the firewall by running sudo ufw disable followed by sudo ufw enable, since changes to that file only take effect after a restart. After re-enabling, rule confirmations should show both Rule added and Rule added (v6).
If sudo ufw status reports inactive even though you added rules, the firewall was never enabled or its startup unit is disabled. Enabling UFW with sudo ufw enable both activates it now and configures it to load on every boot. On a minimal Debian install, also verify the service is enabled in systemd with sudo systemctl is-enabled ufw; if it returns disabled, enable it with sudo systemctl enable --now ufw.
The minimal sequence is to set your default policies, allow SSH, then enable the firewall. Run sudo ufw default deny incoming, sudo ufw default allow outgoing, sudo ufw allow OpenSSH, and finally sudo ufw enable. After that, open any additional ports your services need, such as sudo ufw allow 80/tcp for a web server, and confirm everything with sudo ufw status verbose. The relevant steps are covered in the “Setting up UFW defaults” and “Enabling UFW” sections above.
Yes, UFW works on Debian. The difference from Ubuntu is that UFW is not installed by default on Debian, so you install it with sudo apt update followed by sudo apt install ufw. Once installed, every command behaves the same as on Ubuntu, and the firewall remains inactive until you run sudo ufw enable.
Neither is universally better; the right choice depends on your system and needs. UFW is simpler and is the natural fit for single-server setups on Ubuntu and Debian, where you mostly open a handful of ports. firewalld is better suited to Red Hat family systems such as Rocky Linux and Fedora, and to environments that need dynamic zone management for different network interfaces. For a straightforward Ubuntu or Debian cloud server, UFW is usually the easier and quite capable option.
Always allow SSH before enabling the firewall, keep the default policy set to deny incoming and allow outgoing, and open only the ports your services actually require. Use sudo ufw limit ssh to slow down brute-force attempts, turn on logging with sudo ufw logging on, and review your rules periodically with sudo ufw status numbered. Where possible, restrict sensitive services such as SSH to known IP addresses rather than leaving them open to the entire internet.
Use sudo ufw allow followed by the port number and protocol, for example sudo ufw allow 8080/tcp to open TCP port 8080. Naming the protocol (tcp or udp) is more precise; if you provide only the port number, the rule applies to both protocols. You can confirm the rule was added with sudo ufw status.
There are two ways to delete a rule. You can delete by rule specification, which mirrors how you created it, for example sudo ufw delete allow 80/tcp. Alternatively, run sudo ufw status numbered to list the rules with index numbers, then delete by number, for example sudo ufw delete 2. Deleting by number is easier when rules are long or complex, and UFW prompts you to confirm.
Run sudo ufw status verbose. If the firewall is on, the first line reads Status: active, followed by the default incoming and outgoing policies, the logging level, and the full list of rules. If it reads Status: inactive, UFW is installed but not currently enforcing any rules, and you enable it with sudo ufw enable.
Yes, as long as IPv6 support is enabled in UFW, which it is by default on modern systems through the IPV6=yes setting in /etc/default/ufw. When IPv6 is enabled, each rule you add applies to both IPv4 and IPv6, which is why rule confirmations show both Rule added and Rule added (v6). If you change that setting, you must run sudo ufw disable and sudo ufw enable for it to take effect.
In this tutorial, you installed and configured UFW to allow or restrict access to a subset of ports and IP addresses on an Ubuntu or Debian cloud server. You set default policies, opened ports for SSH and web traffic, worked with application profiles, enabled logging, deleted rules, and learned how to reset the firewall and troubleshoot the most common problems.
With these fundamentals in place, you have a solid, secure baseline for any cloud server. To read more about what is possible with UFW, check out our guide on UFW Essentials: Common Firewall Rules and Commands.
To deepen your knowledge of Linux firewalls, explore these related DigitalOcean tutorials:
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
With over 6 years of experience in tech publishing, Mani has edited and published more than 75 books covering a wide range of data science topics. Known for his strong attention to detail and technical knowledge, Mani specializes in creating clear, concise, and easy-to-understand content tailored for developers.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Great article, glad I found this because looking at the iptables firewall option was way over my head as a noob. Quick question, aside from having this firewall setup, should I still use the iptables firewall option as well or is there another form of server security I should be using as well. Thanks for the info here and the help.
@james: UFW is an iptables wrapper, you’re indirectly using iptables while using ufw. ;]
This works in Debian too; you might want to change the title so as not to imply that it’s just for Ubuntu.
So to allow ssh should I use:
sudo ufw allow ssh
AND
sudo ufw allow 22/tcp ?
Thanks
What’s the easiest way to add a whole range of specific IP addresses, such as https://www.cloudflare.com/ips?
Thanks for this. Made it pretty quick for me to get started. Used iptable setups before, but they can be annoying to setup, and have remember the rules etc.
On my debian/wheezy64 i keep having problems with ufw: trying to enable it causes the error “ERROR: problem running ufw-init” and it will not autostart at boot, does anyone know how to solve this? On my local wheezy installation everything works fine, but my box at digitalocean won’t do it :(
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Scale up as you grow — whether you're running one virtual machine or ten thousand.

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.
