How to harden a new Ubuntu 24.04 VPS in the first 10 minutes
A fresh VPS is reachable from the entire internet the moment it boots, and automated scanners usually find a new IP address within minutes, not days. This guide covers the first ten minutes of work on a clean Ubuntu 24.04 server: a sudo user, key-only SSH, a firewall, fail2ban, automatic security updates and a final check of what is actually listening. It is aimed at anyone who deploys their own server and wants a sane, repeatable baseline before installing anything else.
Step 1: update the system
Log in as root and bring the package index and installed packages up to date. This matters because a template image can be weeks old, and the easiest attacks target vulnerabilities that already have published fixes.
apt update && apt -y upgrade apt -y autoremove
Reboot only if the file /var/run/reboot-required exists, otherwise continue.
Step 2: create a sudo user
Day-to-day work as root means every typo runs with unlimited privileges, so create a normal user and give it sudo rights instead.
adduser deploy usermod -aG sudo deploy
Replace deploy with any name you like. Verify that sudo works before going further:
su - deploy sudo whoami
The last command should print root. If it does not, fix it now while you still have a root session open.
Step 3: SSH keys, then disable password login
Password authentication can be brute-forced around the clock, while a modern SSH key effectively cannot, so this single change removes the most common attack against any VPS. On your local machine, generate a key if you do not have one and copy it to the server:
ssh-keygen -t ed25519 ssh-copy-id deploy@203.0.113.10
Test that ssh deploy@203.0.113.10 logs you in without a password. Only after that, disable password authentication on the server. On Ubuntu 24.04 the main config includes drop-in files from /etc/ssh/sshd_config.d/ in lexical order, and sshd keeps the first value it reads for each option, so the drop-in that sorts earliest wins. Cloud images ship a file such as 50-cloud-init.conf that sets PasswordAuthentication yes, so your file must sort before it: name it 00-hardening.conf.
printf 'PasswordAuthentication no\nKbdInteractiveAuthentication no\nPermitRootLogin prohibit-password\n' | sudo tee /etc/ssh/sshd_config.d/00-hardening.conf sudo sshd -t && sudo systemctl restart ssh sudo sshd -T | grep -i passwordauthentication
The last command prints the effective configuration, so confirm it says passwordauthentication no; if it still says yes, another drop-in is winning and you need to check /etc/ssh/sshd_config.d/. Keep your current session open and confirm in a second terminal that key login still works; a broken SSH config with no fallback session is the classic way to lock yourself out.
Step 4: firewall basics with ufw
A firewall guarantees that services you install later, such as a database listening on all interfaces by default, are not silently exposed to the internet. ufw is preinstalled on Ubuntu 24.04, so you only need to allow SSH and enable it:
sudo ufw allow OpenSSH sudo ufw enable sudo ufw status verbose
Allow SSH before enabling the firewall, otherwise the next dropped packet is your own connection. If the server will run a website, open the web ports too:
sudo ufw allow 80/tcp sudo ufw allow 443/tcp
Step 5: fail2ban and automatic security updates
fail2ban reads authentication logs and temporarily bans IP addresses that keep failing, which cuts brute-force noise and slows credential stuffing to a crawl.
sudo apt -y install fail2ban printf '[sshd]\nenabled = true\nbackend = systemd\n' | sudo tee /etc/fail2ban/jail.d/sshd.local sudo systemctl enable --now fail2ban sudo fail2ban-client status sshd
The backend = systemd line makes fail2ban read the systemd journal directly, so it works even on minimal installs without classic log files. Next, unattended-upgrades installs security patches automatically, which matters because most real-world breaches exploit vulnerabilities that were patched long before the attack.
sudo apt -y install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades
Choose Yes in the dialog. The default configuration applies only security updates, so it will not surprise you with major version jumps.
Step 6: timezone, hostname and a port check
Set the timezone so that log timestamps match your monitoring and your own memory of events:
sudo timedatectl set-timezone Europe/Riga timedatectl
Give the machine a real hostname, because six months from now "ubuntu-2404" in an alert tells you nothing:
sudo hostnamectl set-hostname web1.example.com
Finally, list every listening socket and decide consciously whether each one should be public:
sudo ss -tulpn
Read the Local Address column: entries on 127.0.0.1 or ::1 are reachable only from the server itself, while 0.0.0.0 or [::] means the port is open to the world unless ufw blocks it. On a clean install you should see little more than sshd and systemd-resolved; anything else deserves an explanation.
What you have after ten minutes
- A patched system that keeps patching itself
- A sudo user and key-only SSH, with password login disabled
- A default-deny firewall with only the ports you chose
- fail2ban banning brute-force sources automatically
- Correct time, a meaningful hostname and a known list of open ports
None of this replaces backups or monitoring, but it closes the gaps that automated scanners exploit in the first hours of a server's life. If you are still choosing where to run that server, our VPS plans run on our own hardware and network AS58269 in a Tier 3+ data centre in Riga, and everything above works exactly the same on them.