DEV Community

Cover image for How to Secure a VPS: The Complete Ubuntu Hardening Guide
Wade Thomas
Wade Thomas

Posted on

How to Secure a VPS: The Complete Ubuntu Hardening Guide

The moment a VPS gets a public IP, it's already being scanned. Automated bots start hammering the default root account with password guesses within minutes of the server going online — before you've even finished your first apt update.

This guide walks through the baseline hardening I run on every fresh Ubuntu server before deploying anything to it: creating a proper user account, locking down root, setting up a firewall, quieting bot noise on SSH, and auto-banning repeat offenders.

Prefer to follow along on video?

1. Stop Using the Root User

Every Linux server in the world ships with an account named root. That's the problem — hackers already know the username, so they only need to guess the password or find one exploit to get full control. A custom username forces an attacker to guess two unknowns instead of one.

A few other reasons to move off root:

  • No safety net. Root executes destructive commands instantly, no confirmation. Run rm -rf / as root and it's gone. A standard user needs sudo, which at least forces a pause and a password prompt.
  • Bots target root specifically. The moment a VPS goes online, automated bots start brute-forcing the root account with thousands of password guesses per minute. Disable root login and that entire attack surface disappears.
  • No accountability. If more than one person has server access, a shared root login makes it impossible to tell who did what. Individual sudo accounts get logged to /var/log/auth.log, so every command is tied to a specific user.

Create a sudo user

adduser your_username
usermod -aG sudo your_username
Enter fullscreen mode Exit fullscreen mode

-aG breaks down into two flags: -G adds the user to the group that follows (sudo), and -a (append) makes sure the user is added to that group rather than having all their other group memberships wiped out. Together, -aG says: add this user to sudo, keep everything else as-is.

Verify it worked:

groups your_username
Enter fullscreen mode Exit fullscreen mode

Lock down root

Log out of root and back in as your new sudo user first, then:

# Lock the root password
sudo passwd -l root

# Disable root login over SSH
sudo nano /etc/ssh/sshd_config
# set: PermitRootLogin no
sudo systemctl restart sshd

# Confirm root is locked
sudo passwd -S root
Enter fullscreen mode Exit fullscreen mode

2. Set Up a Firewall (UFW)

A firewall closes off everything you're not explicitly using. On a fresh VPS, that means:

  • Blocking brute-force attempts on ports you don't need exposed
  • Keeping internal-only services (databases, admin tools) off the public internet
  • Restricting sensitive ports like SSH to specific IPs, if needed
  • Dropping unexpected traffic, which softens basic DoS attempts
  • Closing the door on any hidden vulnerability in something you're running

Ubuntu ships with UFW (Uncomplicated Firewall), which blocks all incoming traffic by default and only opens what you explicitly allow:

# Allow SSH first so you don't lock yourself out
sudo ufw allow OpenSSH
# or: sudo ufw allow 22/tcp

# Allow web traffic if you're hosting a site
sudo ufw allow http
sudo ufw allow https

# Turn it on
sudo ufw enable

# Check status
sudo ufw status verbose
Enter fullscreen mode Exit fullscreen mode

3. Change the Default SSH Port

Within minutes of going live, bots start hammering port 22 — not targeted attacks, just scripts sweeping the internet for the default SSH port. Moving to something non-standard, like 2222, makes those scanners skip right past you.

sudo nano /etc/ssh/sshd_config
# uncomment #Port 22 and change it:
# Port 2222

sudo ufw allow 2222/tcp
sudo ufw reload
sudo systemctl restart sshd
Enter fullscreen mode Exit fullscreen mode

Worth being honest about this one: security researchers call this "security through obscurity," and on its own it's a weak measure — it doesn't make the server harder to break into. What it does do is keep your auth logs from being flooded with bot noise, which makes real suspicious activity much easier to spot. Pair it with SSH keys, disabled password auth, and Fail2Ban for actual hardening.

4. Install Fail2Ban

Fail2Ban watches your logs for repeated failed login attempts and temporarily bans the offending IP at the firewall level.

Why it's worth running:

  • Free, open-source, and quick to set up
  • Highly configurable — ban duration, whitelisted IPs, which services to watch
  • Bans happen at the firewall, so malicious traffic doesn't eat server resources
  • Can integrate with notifications for real-time alerts

Where it falls short:

  • Reactive, not preventive — it only acts after a set number of failed attempts have already happened
  • Can lock out legitimate users who fat-finger a password a few times in a row
  • Weak against distributed attacks, since it bans by IP and botnets rotate through thousands of them
  • Vulnerable to IP spoofing
  • Can conflict with Docker's iptables rules on a Docker host, causing bans to fail or hit the wrong container

Install it:

sudo apt update
sudo apt install fail2ban -y
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
Enter fullscreen mode Exit fullscreen mode

(The -y flag auto-confirms every prompt during install — only use it once you're already certain about the package.)

Wrap-Up

None of these steps make a server unbreakable on their own — a sudo user, a firewall, an obscure SSH port, and Fail2Ban are each individually beatable. Stacked together, they cut off the low-effort, automated attacks that hit every public IP within minutes of going live, and they keep your logs clean enough that you'd actually notice something that isn't normal.

If you found this useful, the video above walks through each step live. Let me know in the comments if you run into anything setting this up on your own box.

Top comments (0)