Why Most VPS Servers Are Just Waiting to Be Hacked
I spun up my first VPS and did nothing for a day. When I checked the auth logs, there were already hundreds of failed login attempts — all targeting root on port 22. The bots don't wait. They're scanning the internet constantly, and a fresh unprotected server is exactly what they're looking for.
The good news? Blocking the vast majority of these attacks doesn't require expert-level knowledge. It requires doing the basics in the right order. That's what this guide is about.
Step 1: Stop Using Root
Root is the superuser account on every Linux system. It has no restrictions. If someone gets in as root, they own your machine completely. I've seen people run entire production apps as root — it's an accident waiting to happen.
Create a regular user and give it sudo access:
adduser username
usermod -aG sudo usernameFrom this point forward, log in as this user. Use sudo only when you need elevated privileges. Root stays locked away.
Step 2: Switch to SSH Key Authentication
Passwords can be brute-forced. SSH keys cannot — at least not practically. Think of it like a physical deadbolt versus a combination lock that anyone can stand there and try forever.
On your local machine, generate a key pair:
ssh-keygen -t ed25519 -C "your_email@example.com"
cat ~/.ssh/id_ed25519.pubOn the VPS, add your public key:
mkdir -p ~/.ssh
nano ~/.ssh/authorized_keys
# paste your public key here
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R username:username ~/.sshThe permissions matter. SSH will silently refuse to use your key if the folder or file permissions are too open.
Step 3: Move SSH Off Port 22
Port 22 is the default SSH port — every automated scanner on the internet probes it constantly. Moving to something like 8997 won't stop a determined attacker, but it cuts out nearly all the automated noise immediately.
Edit your SSH config:
sudo nano /etc/ssh/sshd_configAdd both ports temporarily:
Port 22
Port 2222Important Ubuntu gotcha: Modern Ubuntu uses ssh.socket which can override your config changes. Fix it before restarting:
sudo systemctl disable ssh.socket
sudo systemctl stop ssh.socket
sudo systemctl enable ssh
sudo systemctl restart sshStep 4: Configure UFW Firewall
UFW (Uncomplicated Firewall) is exactly what the name says. Never enable it without allowing your SSH port first — otherwise you'll lock yourself out entirely.
sudo ufw allow 2222/tcp
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enableIn my experience, people skip the firewall step thinking it's optional. It isn't. Without it, every port on your machine is open to the world by default.
Step 5: Test Before You Lock Down
Open a new terminal window — don't close your current session — and test the new port:
ssh -p 2222 username@your_server_ipIt must connect without asking for a password. Only once you've confirmed this do you move to the next step. Skipping this test is the single most common way people get locked out of their own server.
Step 6: Disable Password and Root Login
Now that key login is confirmed working, disable the weaker methods:
sudo nano /etc/ssh/sshd_configSet these values:
PasswordAuthentication no
PermitRootLogin noRestart SSH:
sudo systemctl restart sshStep 7: Remove Port 22 Entirely
Once everything is confirmed working on your custom port, clean up the defaults:
sudo ufw delete allow OpenSSH
sudo ufw delete allow 22/tcpRemove Port 22 from /etc/ssh/sshd_config, then restart SSH one final time. Your server now only accepts connections on your custom port, via key, from a non-root user.
What You've Actually Achieved
After following these steps your server rejects root logins, ignores password attempts, sits on a non-standard port, and has a firewall blocking everything that isn't explicitly allowed. Most automated attacks fail at step one — they try root on port 22 with a password and immediately hit a wall.
Security isn't one command. It's doing several simple things in the right order, testing each one before moving on, and not skipping steps because they seem unnecessary. The servers that get compromised almost always skipped something basic.
