[ OK ]Initializing kernel...
~/im/blog
Hire Me

Let's Talk

Got an infrastructure problem or need an extra hand? I'm open to discussing new projects.

Get in touch

Connect

Find me on social media and professional networks.

© 2026 Irfan Miral. All rights reserved.Developed byIrfan Miral
Privacy PolicyTerms & Conditions
HomeServicesAbout/ResumeBlogContactTools
2026-06-10• 5 min read

The First Hour on a New VPS: My Hardening Checklist

Security Server Security Linux Administration VPS

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

Need help with this?

If you'd rather have someone handle Server Management & Administration for you, that's exactly what I do.

Get in Touch
PreviousThe DNS Records That Actually MatterNext Automating Let's Encrypt So You Never Think About Certificates Again