Hardening a new VPS
Answer
Hardening a new VPS takes about twenty minutes: disable password and root SSH login, enable key-only authentication, configure nftables to default-deny inbound, enable unattended security upgrades, and install fail2ban. Those five steps eliminate the overwhelming majority of real-world compromises.
What actually compromises servers
Not zero-days. In practice: SSH password brute force against weak credentials, unpatched services left running for months, exposed admin panels with default passwords, and application vulnerabilities in whatever the operator installed. The list is boring and it has not changed in fifteen years.
The checklist below is ordered by how much risk each step removes per minute spent. Do them in order and stop when you run out of patience — you will still have removed most of the risk.
Step 1 — SSH keys only
This single change removes the most common attack entirely. Generate an Ed25519 key, copy the public half up, then edit /etc/ssh/sshd_config to set PasswordAuthentication no, PermitRootLogin prohibit-password and KbdInteractiveAuthentication no.
Test the key in a second terminal before closing the first. Locking yourself out is embarrassing and, on a machine with console access, entirely recoverable — but do it in the right order anyway.
Step 2 — default-deny firewall
nftables on modern Debian and Ubuntu, or firewalld on RHEL derivatives. Default-deny inbound, allow established and related, allow your SSH port, allow whatever the workload actually needs, and nothing else.
The important discipline is that "nothing else" is the whole point. A firewall with a permissive rule added during debugging and never removed is a firewall that is not doing anything.
- Default policy: drop inbound, accept outbound
- Accept established, related
- Accept loopback
- Accept your SSH port, ideally rate-limited
- Accept the workload ports, explicitly listed
- Accept ICMP echo — do not break path MTU discovery
Step 3 — automatic security updates
unattended-upgrades on Debian and Ubuntu, dnf-automatic on RHEL derivatives, configured for security updates only. Most compromises exploit vulnerabilities that were patched months earlier.
Enable automatic reboot in a maintenance window if your workload tolerates it. Kernel updates do nothing until the machine reboots, and a server with 400 days of uptime and eleven pending kernel CVEs is not a badge of honour.
Step 4 — fail2ban, and a note on its real value
With password authentication already disabled, fail2ban stops relatively few actual compromises. What it does is cut log noise dramatically, which matters because a log full of thousands of failed attempts is a log nobody reads, and unread logs are how real intrusions go unnoticed for weeks.
The default sshd jail is enough. Add jails for whatever else you expose to the internet.
Step 5 — reduce the attack surface
Run ss -tlnp and look at what is listening. On a default install this usually includes services you did not know were running and do not need. Remove them rather than firewalling them — software that is not installed has no vulnerabilities.
Bind services that only need local access to 127.0.0.1 rather than 0.0.0.0. A database listening on all interfaces behind a firewall is one misconfiguration away from being public.
What to skip
Changing the SSH port reduces log noise and stops exactly zero targeted attacks. Do it if you like, but do not count it as security. Port knocking adds fragility for a marginal gain. Intrusion-detection systems generate alerts nobody triages on a single server.
If you want one more meaningful step after the five above, it is encrypted off-site backups in a different jurisdiction, tested by actually restoring them. Recovery capability is worth more than another layer of prevention.
Frequently asked questions
01 Is changing the SSH port worth it?
For log noise, yes. For security, no — it stops opportunistic scanners and zero targeted attacks. Do it if you like the quieter logs, but do not count it as a control.
02 Do I need fail2ban if I use SSH keys?
For direct security, barely. For log hygiene, yes — thousands of failed attempts make logs unreadable, and unread logs are how real intrusions stay unnoticed.
03 Should I enable automatic reboots?
If the workload tolerates it, yes, in a maintenance window. Kernel patches do nothing until reboot. Long uptime with pending kernel CVEs is a liability, not an achievement.
Related