Skip to content
Serverküche
Search

Loading search … (only available on the published site).

Security Difficulty: Beginner

Setting up a firewall with UFW

Set up a host firewall in minutes with UFW: block everything except SSH, HTTP and HTTPS on your server – without ever locking yourself out.

· 4 min read ·Duration: approx. 15 minutes
Table of contents

By default, your server accepts connections on all open ports. A firewall turns that around: it blocks everything and only lets through what you explicitly allow. UFW (“Uncomplicated Firewall”) does this with a few, readable commands – the perfect first line of defense.

What are we building?

By the end, UFW runs on your Debian 13 with the base rule “block all incoming”, with only SSH (your access) plus HTTP/HTTPS (ports 80/443, which you’ll need later for Traefik) open. Outgoing connections stay allowed. The key part: we proceed in a way that ensures you don’t lock yourself out.

Prerequisites

  • A hardened server with a sudo user
  • You know which port your SSH runs on (default: 22)

Step by step

Step 1: Install UFW

Terminal
sudo apt update
sudo apt install -y ufw

Check the version – UFW is inactive at first, which is intended:

Terminal
ufw version

Step 2: Define the base rules

First the default direction: deny everything incoming, allow everything outgoing.

Terminal
sudo ufw default deny incoming
sudo ufw default allow outgoing
Ausgabe
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)
Default outgoing policy changed to 'allow'
(be sure to update your rules accordingly)

These rules don’t take effect yet – UFW is still inactive. So the exceptions come now, before we switch it on.

Step 3: Allow SSH – first, or you’ll lock yourself out

Allow SSH first, then activate

If you enable UFW with the “deny incoming” rule without having allowed SSH first, the next command cuts your own connection – and you can no longer get in via SSH. This order is non-negotiable.

If your SSH runs on the default port 22 (and openssh-server is installed), there’s a ready-made profile for it:

Terminal
sudo ufw allow OpenSSH

If you changed the SSH port (e.g. to 2222), allow exactly that port instead:

Terminal
sudo ufw allow 2222/tcp

Step 4: Allow HTTP and HTTPS

For the later reverse proxy with Traefik you need the web ports. Open them right away:

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

UFW confirms each rule with Rules updated and Rules updated (v6) (the IPv6 variant).

Step 5: Activate the firewall and check it

Now switch it on:

Terminal
sudo ufw enable
Ausgabe
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Check the result:

Terminal
sudo ufw status verbose
Ausgabe
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
443/tcp (v6)               ALLOW IN    Anywhere (v6)

Status: active and your three allowances – done. To be safe, test in a second SSH session that you can still connect before closing the first one.

When things go wrong

After ufw enable you can no longer get in via SSH. The SSH rule was missing or targeted the wrong port. Connect via the console in the netcup SCP (VNC, independent of SSH), allow your SSH port there (sudo ufw allow …) and test again. That’s exactly what step 3 warns about.

ERROR: Could not find a profile matching 'OpenSSH'. The OpenSSH profile only exists if openssh-server is installed. Use the port number instead: sudo ufw allow 22/tcp (or your port). sudo ufw app list shows the available profiles.

A Docker container is reachable from outside even though UFW doesn’t open the port. Not your mistake – Docker bypasses UFW. Docker writes its rules directly into iptables and inserts them ahead of the UFW chains. A published container port (ports: in the compose.yaml) is thus open, no matter what UFW says. The clean solution is a second firewall layer in front of the server – at netcup the firewall in the SCP as an upstream perimeter. On the host it also helps to bind container ports only to 127.0.0.1 instead of 0.0.0.0.

Maintenance & backups

  • View and delete rules: sudo ufw status numbered numbers all rules; sudo ufw delete 3 removes rule 3. That’s how you tidy up when a service goes away.
  • New services: For every additional public port, one targeted rule – never “just open everything”. What doesn’t need to be open stays closed.
  • No backup needed, but note down your allowances (or keep them in the same document as your DNS records). The rule set is retyped in seconds.
  • Know the limits: UFW protects the host, but not against the Docker gap above. An upstream perimeter firewall like the netcup firewall in the SCP complements UFW into two layers that secure each other – ideal once containers with open ports are running.

Last updated: Jul 19, 2026

What's next?

You might also like

Installing Docker on Debian
Containers Beginner

Installing Docker on Debian

Install Docker Engine and Docker Compose cleanly from the official repository – the foundation for most self-hosting …

· 3 min read
First steps with a netcup VPS
Basics Beginner

First steps with a netcup VPS

From a freshly ordered netcup server to a ready-to-use system: SSH login, system updates, a sudo user and the most …

· 4 min read
Restic backups: encrypted and off-site
Security Intermediate

Restic backups: encrypted and off-site

Off-site backups with Restic: set up encrypted, restore snapshots, prune with retention and automate via a systemd …

· 11 min read