I manage a handful of VPS boxes. Every time I spin up a new one I forget something. Disable root login? Nope. Set up fail2ban? Maybe next week. Unattended upgrades? Lol.
After one too many "wait, how did that get in" moments, I wrote myself a checklist. Here are the 5 rules I actually follow now ( and why ).

1. Disable Root Login and Password Auth
This is rule zero. If you can SSH in as root with a password, you are playing on easy mode ( for the attacker ).
Here is my sshd_config snippet:
# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickeyGenerate a key pair locally, copy the public key to the server, then restart sshd. Do not close your session until you have confirmed the new key works ( trust me ).
ssh-keygen -t ed25519 -C "myserver"
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# Test in a NEW terminal before closing this one2. Fail2ban or Go Home
Brute force attacks are not theoretical. They are constant. Every single one of my servers gets hammered within hours of going live.
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2banThe defaults are fine to start. After a week, check the logs:
sudo fail2ban-client status sshd
# Banned IPs in the last 24h: usually dozensIf you want to be more aggressive ( I do ):
# /etc/fail2ban/jail.local
[sshd]
enabled = true
maxretry = 3
bantime = 3600
findtime = 600
3. Unattended Upgrades Are Not Optional
I used to update servers manually. That lasted until I realized I had a box running a kernel from 6 months ago with 3 known CVEs. Never again.
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgradesOr configure it manually if you want more control:
# /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";Yes, I let it auto-reboot at 3am. My servers are not running heart surgery ( )
4. Firewall: nftables Over iptables
I know, iptables is everywhere. Documentation, Stack Overflow answers, every tutorial from 2012. But nftables is the replacement and it is better. Deal with it.
sudo apt install nftables -y
sudo systemctl enable nftablesHere is my standard ruleset:
#!/usr/sbin/nft -f
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback
iif lo accept
# Allow established connections
ct state established,related accept
# Allow SSH
tcp dport 22 accept
# Allow HTTP/HTTPS
tcp dport { 80, 443 } accept
# Allow ICMP ( ping )
ip protocol icmp accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}Default policy: drop everything, allow only what you need. If you need more ports, add them explicitly. No wildcards, no hope.

5. Audit and Log Everything
If you are not reading your logs, the hardening does not matter. You are just making the attacker work slightly harder.
Install auditd:
sudo apt install auditd -y
sudo systemctl enable auditd
sudo systemctl start auditdKey rules to watch:
# /etc/audit/rules.d/audit.rules
-w /etc/ssh/ -p wa -k ssh_config
-w /etc/nftables.conf -p wa -k firewall_config
-w /etc/sudoers -p wa -k sudoers
-w /var/log/auth.log -p wa -k auth_log
-a always,exit -F arch=b64 -S execve -k execThen review:
sudo ausearch -k ssh_config -ts today
sudo ausearch -k firewall_config -ts this-weekI also ship logs to a central location ( another server, not the same one ). If someone roots your box, the first thing they do is clean the logs. You want copies elsewhere.

Conclusion
These 5 rules take maybe 20 minutes on a fresh box. 20 minutes that save you from cleaning up at 2am because someone brute-forced your root password ( again ).
I keep these in a shell script that I run on every new server. Copy, paste, sleep better.
Thank you