How to set up a firewall on your VPS
How to enable and configure a firewall on your VPS with ufw or firewalld, without accidentally shutting yourself out over SSH.
A firewall on a VPS blocks every incoming connection except the ones you explicitly allow. A default VPS has no firewall active at all, which means every service you install is reachable from the entire internet the moment it starts — a firewall is what narrows that down to only what actually needs to be public.
The single most common way people lock themselves out of a VPS is enabling a firewall that has not been told SSH is allowed. Every command below allows SSH as the very first step, before the firewall is switched on. Do not reorder that.
Ubuntu and Debian use ufw (Uncomplicated Firewall), a simpler front end over the kernel's netfilter. RHEL, Rocky Linux and AlmaLinux use firewalld instead. Both do the same underlying job with different commands.
Setting up ufw (Ubuntu / Debian)
Install it if it is not already present, then allow SSH before anything else:
sudo apt install ufw -y
sudo ufw allow OpenSSH
OpenSSH is an application profile that expands to port 22/tcp. If SSH is running on a non-standard port, allow that port number directly instead — for example sudo ufw allow 2222/tcp — and skip the OpenSSH profile.
Now enable it:
sudo ufw enable
Confirm the rule is actually in place before you disconnect:
sudo ufw status verbose
Add rules for whatever else the server needs to expose, typically a web server:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Or, more readably, using the built-in profiles for common services:
sudo ufw allow 'Nginx Full'
sudo ufw allow 'Apache Full'
To remove a rule you no longer need:
sudo ufw status numbered
sudo ufw delete 3
Setting up firewalld (RHEL / Rocky / AlmaLinux)
firewalld is normally installed and running by default on these distributions. Check first:
sudo systemctl status firewalld
If it is not running, allow SSH before you start it:
sudo firewall-cmd --permanent --add-service=ssh
sudo systemctl enable --now firewalld
firewalld organises rules into named zones — public is the default and the one you want for a typical internet-facing server. Add services or ports to it:
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload
Note the --permanent flag on every change — without it, the rule applies immediately but is lost on the next reboot, and --reload is required to make a permanent change take effect right away without restarting the service. Check what is actually active at any time:
sudo firewall-cmd --list-all
To open a specific port rather than a named service, for example a custom application on 8080:
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Which ports you actually need
| Service | Port | Open it if… |
|---|---|---|
| SSH | 22/tcp (or your custom port) | Always — this is how you manage the server |
| HTTP | 80/tcp | You are running a website (also needed for Let's Encrypt validation) |
| HTTPS | 443/tcp | You are serving the site over SSL/TLS |
| MySQL/MariaDB | 3306/tcp | Almost never — only if a remote machine genuinely needs direct database access |
| Any control panel | Varies | Only while you are installing or using it; consider restricting the source IP |
The safest firewall is the one with the fewest open ports. Do not open a database port to the world just because it is convenient during setup — connect to the database from the application running on the same server instead, or restrict the rule to a specific source IP address if remote access is genuinely required.
Restricting a rule to a specific IP address
Rather than opening a management port to the entire internet, limit it to an address you actually connect from:
# ufw
sudo ufw allow from 198.51.100.20 to any port 8080
# firewalld
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="198.51.100.20" port port="8080" protocol="tcp" accept'
sudo firewall-cmd --reload
Confirming the firewall survives a reboot
Both ufw and firewalld are enabled as system services and persist across a reboot on their own once turned on — you do not need to re-run the enable step after every restart. It is still worth confirming after the server's first reboot following setup, rather than assuming:
sudo ufw status # should show "Status: active"
sudo systemctl is-enabled firewalld
If either shows the firewall is not active after a reboot, re-enable it explicitly rather than leaving the server unprotected until the next manual check.
If you get locked out anyway
If a firewall change does shut off your access, most VPS providers offer a browser-based console (VNC or similar) that connects directly to the server's virtual screen, bypassing the network entirely. Log in there and correct the rule — see what to do when you are locked out of your VPS for the full recovery process.
Once the firewall is in place, pair it with Fail2ban to automatically block IPs that repeatedly fail to log in — a firewall decides what is reachable, and Fail2ban decides who gets to keep trying.
Related reading
The concrete steps that actually matter for securing a fresh Linux server, in the order that keeps you from locking yourself out.
How to set up Fail2banInstalling Fail2ban to automatically block repeated failed logins, configured safely so you do not end up banning yourself.
How to connect to your VPS over SSHSSH is how you control a VPS from the command line, and setting it up properly the first time saves you a lot of trouble later.
How much RAM does my VPS need?It depends what is running, but free -h on an existing server and a look at what each extra service costs gets you a real answer fast.