The day I provisioned the box, I hadn't even pointed DNS at it yet. No domain resolved to it. Nothing on the internet knew it existed.
I checked the SSH log anyway:
journalctl -u ssh --since "24 hours ago" | grep -c "Failed password"Four digits.
A week later I ran it again: a bit over six thousand. About thirty-five an hour, starting from day one.
(On Debian and Ubuntu the unit is ssh. On CentOS and RHEL it's sshd.)
What's actually in the log
A few lines, IPs redacted:
Failed password for root from 45.148.x.x port 51234 ssh2
Invalid user admin from 103.97.x.x port 44122 ssh2
Invalid user oracle from 45.148.x.x port 51980 ssh2
Invalid user ubuntu from 198.98.x.x port 38012 ssh2
Failed password for invalid user postgres from 141.98.x.x port 55410 ssh2The count isn't the interesting part. The usernames are: root, admin, ubuntu, oracle, postgres, test, pi.
Every one of those is a default account on some device or piece of software. None of them is my username. Whoever is on the other end doesn't know who I am and doesn't care — they're working through a list.
This is background noise. You aren't being targeted. You just have a public IP.
So where's the actual risk
Once that landed, what I was afraid of changed.
Not "someone is attacking me," but "what happens if password authentication is still on and my password is Admin123!?"
A script can try tens of thousands of times a day against a few thousand common passwords. It doesn't need to be clever. It needs me to have left the door unlocked.
The doors I closed
The exact commands are in Ops security, and I won't repeat them here. What's worth explaining is why these four, and why in this order:
- Switch to key auth, then turn off passwords. This is the only step that actually solves the problem. A key can't be guessed, so brute force stops being a strategy. Get the order right: confirm the key works before you disable passwords, or you'll lock yourself out.
- Disable direct root login.
rootexists on every Linux box, so the attacker already knows half the credentials. Turning it off makes the username half unknown again. - Firewall everything except what you need. ufw allows SSH, 80, 443, and drops the rest. One less listening port is one less category of problem.
- fail2ban. It reads the log and bans IPs. The log did get noticeably quieter afterwards.
About that fourth one, an honest note: fail2ban made the log look better without making the machine safer.
Every IP it banned was already unable to get in, because password auth was off. Its real value is that reading your logs stops being depressing, plus it fends off the nuisance case where tens of thousands of connections exhaust your SSH slots.
After all four, the box was secure. And still logging thirty-something failures an hour.
What actually made the log go quiet
Later I did a fifth thing: I took port 22 off the public internet.
With a Cloudflare Tunnel, the server dials out to Cloudflare and SSH traffic comes back through that tunnel. Now the machine has no open SSH port at all — scanners have nothing to knock on, so there's nothing to log.
Setup is in Set up Cloudflare. It's more work than installing fail2ban, but for a personal server it's a one-time cost that keeps paying off.
The count now:
journalctl -u ssh --since "7 days ago" | grep -c "Failed password"
0Two things I got wrong
Changing the port does nothing. I moved 22 to 2222 for a while, thinking I'd slipped past the scanners. All it did was reduce the noise, because plenty of scripts only check 22. The ones that sweep every port found the new one in a minute or two. It lowers your log volume, not your risk. Don't put it on a security checklist.
"There's nothing valuable on my server" isn't an argument. What attackers usually want isn't your data — it's your bandwidth and CPU. When the box ends up sending spam or mining coins, the bill and the reputation are yours.
A three-minute check
If you have a VPS with a public address, SSH in and run these:
# Is password auth still on? You want: no
sudo sshd -T | grep -i passwordauthentication
# Can root log in directly? You want: no
sudo sshd -T | grep -i permitrootlogin
# How many attempts in the last week
sudo journalctl -u ssh --since "7 days ago" | grep -c "Failed password"If the first one comes back yes, turn it off today.
There's a line in the launch checklist about confirming password login is disabled. Same item. Running it before you launch beats reading logs afterwards.