yash@jain:~$

../ yash@jain:~$ cat /archive/vps-hardening-traps.md

noteServers & self-hosting

Most of my VPS hardening checklist exists because something already went wrong

My server kept accepting password logins after I'd locked them off. Three separate times, the tooling quietly undid my own security work. Everything on my checklist is a mistake I made first.

I want to be upfront: I’m not a sysadmin. A few months ago I couldn’t have told you what hardening a server meant. But I run my own VPS now — it’s where my AI agents live — and every line on my security checklist is there because I got something wrong first and had to figure out why.

If you’re a non-technical person who’s been told “just put it on a VPS,” this is the part nobody walks you through. A VPS (“virtual private server”) is just a computer you rent in a data center and control over the internet. Hardening it means locking the doors. The internet has templates for this — key-only login, a firewall, fail2ban. I followed one. Then reality corrected me.

My provider’s own image re-enabled password login. I hardened the main SSH config file and moved on, feeling competent. Password login was still on. The provider’s image ships with override files — four of them — tucked in a config directory that silently re-enable it. The main file gets overruled. I only found this because something told me to double-check. If you lock down SSH and don’t check the override folder, you haven’t locked it down.

My server wouldn’t listen on the port I told it to. I changed the SSH port, restarted the service, and nothing happened. Turns out modern Ubuntu runs SSH through something called socket activation, which overrides the config file. The fix was a set of commands to disable the socket and enable the real service. I’d never have guessed this from the config alone.

I mangled my own API key. I wrote a 42-character secret key to the server using a copy-paste shell trick. It silently chopped the key to 14 characters, and I burned an hour on “401 unauthorized” errors that made no sense. The right way is a proper file-copy command that preserves every character exactly.

My home internet provider blocked the whole server. Moving to a different port didn’t help — they’d blackholed the entire IP address, not just the port. The actual fix was a mesh network (Tailscale) that routes around my ISP entirely.

And the one that could’ve ended badly: I made sure my provider had a working web console — a back door into the server through their dashboard — before I locked down SSH. If I’d locked myself out without that, I’d have had no way back in.

The pattern here isn’t “be careful.” It’s that the template gets you 80% there and the last 20% is provider-specific traps you only find by hitting them. I write them down so the next version of me doesn’t have to rediscover them.

Related reading

← cd /archive