The First Hour on a New VPS: My Hardening Checklist
Advertisement
When a new VPS comes online, nothing gets deployed until it passes this checklist. It takes under an hour, and it immediately shuts down the attack surface that automated scanners target the second a new IP appears. None of this is exotic. It's the boring, foundational stuff that actually matters.
1. Kill password auth immediately
The very first thing I do after the initial root login is create a non-root user with sudo access, copy my SSH public key over, and test that key-based login works. I do this in a second terminal before touching anything else.
adduser deploy
usermod -aG sudo deploy
rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy
Once that login works, /etc/ssh/sshd_config gets three changes:
PermitRootLogin no
PasswordAuthentication no
MaxAuthTries 3
Run systemctl restart sshd. From this point on, the only way into the box is a private key. No passwords to brute-force, no passwords to phish.
2. Default-deny firewall
Next goes UFW (or CSF). Set it to deny all incoming traffic by default, opening only the ports the server actually needs:
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Database ports, control panels, or admin interfaces get added only when specifically needed. And when they are added, they are scoped to a specific source IP or VPN range—never left open to the world. A simple firewall rule like this would have stopped the CyberPanel worm I wrote about earlier cold.
3. Fail2ban to cut the noise
Even with key-only SSH, logs will fill up with login attempts from botnets. Fail2ban won't stop a targeted, sophisticated attack, but it drops the noise floor dramatically by banning IPs after a handful of failed attempts:
apt install fail2ban
systemctl enable --now fail2ban
The default sshd jail is enough to start. If the server runs a web-facing service like Nginx or WordPress, I add jails for those too. Repeated /wp-login.php hits from the same IP get banned just as fast as SSH scans.
4. Unattended security updates
A server that doesn't patch itself will eventually run a kernel or OpenSSL version with a known exploit. Unattended upgrades handle security patches automatically.
apt install unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades
I periodically check /var/log/unattended-upgrades/ just to confirm it's actually running, not just sitting there.
The baseline
None of this is advanced. That's the point. It's the absolute minimum baseline every server needs before application code goes anywhere near it. The compromised servers I see almost never fall to zero-days; they fall to default passwords, open admin ports, or unpatched kernels. Spending an hour here prevents a catastrophic day later.
Advertisement