How I Secured My Ubuntu VPS After Seeing Constant SSH Attack Attempts
A few weeks after deploying my personal blog to a VPS, I noticed something interesting in the system logs.
Every few minutes, new entries appeared:
Failed password for root pam_unix(sshd:auth): authentication failure Disconnected from authenticating user root
At first, I thought someone was specifically targeting my server.
The reality was less dramatic.
The internet is constantly scanning public IP addresses looking for weak SSH credentials.
If your VPS is exposed to the internet, these attacks will arrive automatically.
In this article, I'll share the exact steps I took to harden my Ubuntu VPS without making administration painful.
The First Surprise: Your Server Is Already Being Scanned
Running:
journalctl -f
showed repeated login attempts from different IP addresses.
Examples:
Failed password for root authentication failure invalid user admin invalid user test
These are usually automated bots.
They continuously scan the internet and try common usernames such as:
root admin ubuntu test user
This is normal.
The important thing is ensuring those attempts never succeed.
Step 1: Create a Separate Administrative User
Using the root account for daily work is convenient.
It's also risky.
Instead, create a dedicated administrator account:
adduser nghia
Grant sudo access:
usermod -aG sudo nghia
Verify:
su - nghia sudo whoami
Expected result:
root
At this point, nothing changes for your applications.
Nginx, PostgreSQL, Spring Boot, Docker, and systemd services continue running normally.
Only the login method changes.
Step 2: Switch to SSH Keys
Passwords can be guessed.
SSH keys are dramatically harder to attack.
Generate a new key pair on your personal device:
ssh-keygen -t ed25519 -C "vps-access"
When prompted for a file name, I recommend creating a dedicated key such as:
~/.ssh/id_ed25519_vps
I recommend creating a dedicated key specifically for the VPS.
Do not reuse:
- GitHub keys
- GitLab keys
- Work laptop keys
Separate keys make revocation easier if one service is compromised.
Copy the public key to the server:
ssh-copy-id -i ~/.ssh/id_ed25519_vps.pub nghia@your-server-ip
Or manually add it to:
~/.ssh/authorized_keys
Verify that key-based login works:
ssh -i ~/.ssh/id_ed25519_vps nghia@your-server-ip
If you created a dedicated key, you may also want to add an SSH config entry:
Host app_name
HostName your-server-ip
User nghia
IdentityFile ~/.ssh/id_ed25519_vps
Then connect using:
ssh app_name
Before changing any SSH settings:
Open a second terminal window and verify that key-based login works.
Never proceed until you've confirmed this.
Step 3: Disable Root Login
Once key authentication works, edit:
sudo nano /etc/ssh/sshd_config
Find:
PermitRootLogin yes
Change to:
PermitRootLogin no
Restart SSH:
sudo systemctl restart ssh
Now even if attackers know your root password, they cannot log in through SSH.
Step 4: Disable Password Authentication
This is one of the biggest security improvements.
In:
sudo nano /etc/ssh/sshd_config
Set:
PasswordAuthentication no ChallengeResponseAuthentication no
Restart SSH:
sudo systemctl restart ssh
From this point forward:
Password login = impossible SSH key = required
Most automated attacks become completely ineffective.
What If I Lose My Laptop?
This was my biggest concern.
The solution is simple:
Store encrypted backups of your private key.
For example:
- Password manager
- Encrypted USB drive
- Secure cloud vault
Keep at least two backups.
Losing all copies of your SSH key is the real risk.
Not disabling password authentication.
Step 5: Change the SSH Port (Optional)
The default SSH port is:
22
Moving it won't stop attackers.
It only reduces noise.
Example:
Port 2222
After changing:
sudo systemctl restart ssh
Connect using:
ssh -p 2222 nghia@server-ip
Security through obscurity is not real security.
Treat this as a small bonus, not a primary defense.
Step 6: Install Fail2Ban
Fail2Ban automatically blocks IP addresses after repeated failed logins.
Install:
sudo apt update sudo apt install fail2ban
Enable:
sudo systemctl enable fail2ban sudo systemctl start fail2ban
Check status:
sudo fail2ban-client status sshd
Now attackers receive temporary bans after multiple failures.
Step 7: Keep the Firewall Simple
Ubuntu includes UFW.
Allow only required services:
sudo ufw allow 80 sudo ufw allow 443 sudo ufw allow 22
Enable:
sudo ufw enable
Verify:
sudo ufw status
If you changed the SSH port, allow that port instead.
Everything else should remain closed.
Step 8: Enable Automatic Security Updates
Install:
sudo apt install unattended-upgrades
Enable:
sudo dpkg-reconfigure unattended-upgrades
This automatically installs important security patches.
For a small personal VPS, this is usually worth it.
Step 9: Monitor Logs Regularly
The easiest security tool is still your logs.
Useful commands:
journalctl -u ssh journalctl -f last lastb
If something unusual happens, the logs usually tell the story first.
My Current VPS Security Baseline
Today my minimum VPS security checklist looks like this:
- Dedicated sudo user
- SSH keys only
- Root login disabled
- Password login disabled
- Fail2Ban enabled
- Firewall enabled
- Automatic security updates enabled
- Regular log monitoring
None of these steps are complicated.
Together, they dramatically reduce the attack surface of a small Ubuntu server.
Most importantly, they protect against the kind of automated attacks that every internet-facing VPS experiences from day one.