# How to secure an Ubuntu VPS: 10 steps for the first hour

> Secure an Ubuntu VPS (24.04) step by step: SSH keys, no password logins, UFW, Fail2ban, automatic updates and backups, with exact commands and traps to avoid.

Source: https://zopanel.net/blog/secure-ubuntu-vps  
Updated: 2026-10-09

## Key takeaways

- The single most important step is SSH key login with password authentication turned off.
- Enable UFW with only the ports you need, and allow SSH before you enable it.
- Ubuntu Server installs security updates automatically by default; Debian needs unattended-upgrades installed.
- Docker bypasses UFW for published ports, so control container ports yourself.

To secure an Ubuntu VPS, do four things first: log in over SSH with a key instead of a password, stop logging in as root, turn on a firewall that only opens the ports you use, and keep the system patched. Those four steps take about fifteen minutes and shut out most of the automated attacks that hit every new server.

This guide walks through ten concrete steps for Ubuntu 24.04 (most apply unchanged to Ubuntu 22.04 and Debian 12), with the exact commands, a way to check that each step took effect, and the mistakes that lock administrators out of their own servers. At the end we list what ZoPanel sets up for you, so you know which steps are still yours.

## Why secure a VPS the moment it is created?

A VPS with a public IP gets port-scanned and sees SSH login attempts almost as soon as it boots. You can see it yourself: run `sudo journalctl -u ssh` after a day and you will find attempts for `root`, `admin`, `test` and other names, from addresses you have never heard of.

None of this is personal. Bots try weak passwords, forgotten services and unpatched software on millions of machines at once. The goal is not "nobody can ever attack me"; it is **leave nothing easy for automated tools to exploit**.

## The Ubuntu VPS security checklist

| Step | What to do | Priority |
| --- | --- | --- |
| 1 | Update the system and turn on automatic security updates | Must |
| 2 | Create a sudo user; stop working as root | Must |
| 3 | Log in with an ed25519 SSH key | Must |
| 4 | Disable password and root logins over SSH | Must |
| 5 | Enable the UFW firewall | Must |
| 6 | Install Fail2ban | Should |
| 7 | Close services you do not need | Should |
| 8 | Sync the clock | Should |
| 9 | Back up off the server | Must |
| 10 | Watch logs and set alerts | Should |

Before you start, make sure you can reach the server's **out-of-band console** (VNC or web console in your provider's dashboard). If you break SSH, that is your way back in.

## Step 1: Update the system and enable automatic security updates

```bash
sudo apt update
sudo apt full-upgrade -y
```

Check whether a reboot is needed, usually after a kernel update:

```bash
[ -f /var/run/reboot-required ] && echo "Reboot required"
```

According to [Ubuntu's documentation](https://ubuntu.com/server/docs/how-to/software/automatic-updates/), Ubuntu Server ships with `unattended-upgrades` installed and applies security updates automatically from the start. By default it does **not** reboot, so kernel fixes only take effect after you restart. Schedule a regular reboot in a quiet hour.

On Debian 12, install it yourself:

```bash
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
```

## Step 2: Create a separate sudo user

Working as root means every typo runs with full power. Create your own user:

```bash
sudo adduser ops
sudo usermod -aG sudo ops
```

Open a new terminal, run `ssh ops@SERVER-IP`, then `sudo -v` to confirm the account has sudo before you go further.

## Step 3: Log in with an SSH key

On **your own computer** (not the VPS), create an ed25519 key pair, the type Ubuntu's OpenSSH documentation recommends:

```bash
ssh-keygen -t ed25519 -C "work-laptop"
ssh-copy-id ops@SERVER-IP
```

Give the key a passphrase so a stolen laptop does not mean an open server. Run `ssh ops@SERVER-IP` again: if you get in without being asked for the user's password, the key works.

## Step 4: Disable password and root logins over SSH

This is the most valuable step and also the easiest one to lock yourself out with. **Keep your current SSH session open** until you have tested the result.

Ubuntu reads the files in `/etc/ssh/sshd_config.d/` before the main config, and for sshd the **first** value it reads wins. Some cloud images ship a file such as `50-cloud-init.conf` that sets `PasswordAuthentication yes`, so give your file a name starting with `00-` to be read first:

```bash
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF
```

Check the syntax, confirm the effective values, then restart SSH:

```bash
sudo sshd -t
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication'
sudo systemctl restart ssh
```

Open a **second terminal** and log in with your key. Only close the old session once that works.

### Should you change the SSH port?

Moving SSH off port 22 cuts log noise, but it does not replace key authentication. If you do it, remember that Ubuntu 24.04 uses **socket activation** for SSH, so restarting `ssh` after editing `Port` is not enough. Following [Ubuntu's notes on socket activation](https://discourse.ubuntu.com/t/sshd-now-uses-socket-based-activation-ubuntu-22-10-and-later/30189):

```bash
sudo ufw allow 2222/tcp          # open the new port FIRST
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
sudo ss -tlnp | grep 2222
```

Connect on the new port, then remove the rule for port 22.

## Step 5: Enable the UFW firewall

Deny everything incoming, then allow only what you need. **Allow SSH before you enable UFW**, or your current session is cut off.

```bash
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
```

If your provider also has a cloud firewall or security group, configure it to match.

**A note on Docker:** the [Docker documentation](https://docs.docker.com/engine/network/packet-filtering-firewalls/) states plainly that Docker and UFW are incompatible: published container ports (`-p 8080:80`) are routed before UFW's rules apply. If an app should only be reached through a reverse proxy, publish it on `127.0.0.1:8080:80` instead of `8080:80`.

## Step 6: Install Fail2ban

Once SSH passwords are off, password guessing against SSH stops working, but Fail2ban still cuts noise and protects other services such as mail, FTP and login pages.

```bash
sudo apt install fail2ban python3-systemd
sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
backend = systemd
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
```

`backend = systemd` makes Fail2ban read the journal. That matters on Debian 12, which no longer installs `rsyslog` by default and therefore often has no `/var/log/auth.log`. Add your office IP to `ignoreip` so you never ban yourself.

## Step 7: Close services you do not need

List everything that listens on a port:

```bash
sudo ss -tulpn
```

For each line, ask whether it really needs connections from the internet. MariaDB, PostgreSQL and Redis should almost always listen on `127.0.0.1` only. Remove software you do not use (`sudo apt purge …`) rather than just blocking its port.

## Step 8: Sync the clock

Logs with the wrong time make incident investigation painful, and two-factor codes, licenses and certificates all depend on an accurate clock.

```bash
timedatectl
sudo timedatectl set-timezone UTC
```

`System clock synchronized: yes` means NTP is working.

## Step 9: Back up off the server

Security also means being able to recover. Backups stored on the VPS itself disappear with it, whether the cause is ransomware or a provider outage. At a minimum:

- regular snapshots at your VPS provider;
- encrypted backups of files and databases somewhere else (S3-compatible storage, another server);
- **a test restore**, at least once. A backup you have never restored is a hope, not a plan.

## Step 10: Watch logs and set alerts

A few commands worth knowing by heart:

```bash
sudo journalctl -u ssh --since today      # SSH logins
last -n 20                                # recent sessions
sudo fail2ban-client status sshd          # currently banned IPs
df -h                                     # disk filling up?
```

Better still, have alerts sent to you when a service stops, the disk fills or a certificate is about to expire, so nothing depends on you remembering to look.

## Securing an Ubuntu VPS with ZoPanel: what is already done

If the VPS is for hosting websites, the [ZoPanel installer](/docs/install) takes care of many of these steps. From the [security documentation](/docs/security):

- **Updates:** the installer upgrades all system packages and turns on automatic security updates (unattended-upgrades).
- **Firewall:** UFW is enabled at boot with only your SSH port, 80, 443 and 8888 (the panel) open. Optional components such as mail, DNS and FTP open their own ports when installed. Rules live under **Security → Firewall**.
- **Fail2ban:** an `sshd` jail (5 failures in 10 minutes, 1-hour ban) and a jail for panel logins (8 failures in 15 minutes, 1-hour ban).
- **Isolation between sites:** each account is its own Linux user with its own PHP-FPM pool, CPU/memory/process limits and disk quota, and `/proc` can be mounted with `hidepid` so customers cannot see each other's processes.
- **Security Center:** scores the server and the panel. It checks SSH root password login, SSH password authentication, Fail2ban, pending security updates and reboots, time sync, services exposed on public ports, extra UID 0 accounts and more, with a one-click **Fix** where a fix is safe. SSH fixes check that a key is set up first, so a fix cannot lock you out.
- **The panel itself:** two-factor authentication (which you can require for all admins), a panel IP allowlist, a tamper-evident activity log, a web application firewall (ModSecurity with the OWASP Core Rule Set) and a weekly malware scan.

What is still yours: creating the SSH key, keeping console access, and getting backups off the server. ZoPanel installs on a **fresh** server, so a sensible order is: create the VPS, add your SSH key, [check the requirements](/docs/requirements) and install ZoPanel, then open **Security Center** and work through anything still red.

For why the hosting panel itself should be designed to limit the damage of a compromise, see [Why a hosting control panel should never run as root](/blog/secure-hosting-panel-architecture).

## Mistakes that lock you out of your VPS

1. **Enabling UFW before allowing SSH.** Your session drops instantly. Always `ufw allow OpenSSH` first.
2. **Disabling passwords before testing the key.** Test key login in a second terminal first.
3. **Changing the SSH port without opening it** in UFW and the cloud firewall, or forgetting `restart ssh.socket` on Ubuntu 24.04.
4. **Closing the old SSH session too early.** Keep it until a new session works.
5. **Assuming UFW protects Docker containers.** It does not, for published ports.
6. **Keeping backups only on the same VPS.** They are gone when the VPS is.

## Conclusion

A secure Ubuntu VPS does not need expensive tools. SSH keys, no passwords, a firewall, automatic patches and off-server backups close most of the doors bots look for. The hard part is doing it in the right order so you do not lock yourself out, and keeping it up afterwards.

If the server will host websites, you can [install ZoPanel for free](/pricing) (the Free plan covers 3 hosting accounts, 10 websites and 10 databases, with no time limit) and get the firewall, Fail2ban, per-site isolation and a Security Center that keeps checking for you. Next read: [protecting your VPS from SSH brute force](/blog/ssh-brute-force-protection).

## Frequently asked questions

### What should I do first to secure an Ubuntu VPS?

Update the system, log in with an SSH key, disable password and root logins over SSH, and enable UFW with only SSH, 80 and 443 open. Then install Fail2ban and set up backups that leave the server.

### Should I change the default SSH port 22?

It reduces automated noise in the logs but adds little real security if you already use keys and have passwords off. If you change it on Ubuntu 24.04, run `systemctl daemon-reload` and `systemctl restart ssh.socket`, and open the new port in the firewall first.

### Does Ubuntu install security updates automatically?

Yes. Ubuntu Server installs and enables `unattended-upgrades` for security updates, but it does not reboot by default. Kernel fixes only apply after a restart, so schedule regular reboots.

### Why doesn't UFW block Docker ports?

Docker adds its own NAT rules that redirect traffic to containers before UFW's rules are evaluated. Publish container ports on `127.0.0.1` and put nginx in front as a reverse proxy.

### Does installing a control panel make a VPS less secure?

It can, if the panel runs as root and is exposed to the internet without protection. Choose a panel with privilege separation, two-factor authentication, an IP allowlist and a clear update policy, and keep it updated.
