DCOUTLIERMENTORSHIP
Server Security

VPS Hardening Checklist: How I Secure Every Server I Manage

June 10, 20269 min

A default VPS is not a secure VPS. Spin up a fresh Ubuntu or Debian box on any provider and, within minutes of it getting a public IP, automated bots are already knocking on port 22 trying default credentials. Most breaches on small and mid-size servers have nothing to do with sophisticated zero-days — they come from root login left enabled, password authentication nobody disabled, a firewall that was never configured, or a service left exposed that nobody remembered was running. Hardening a server isn't one big move. It's a checklist of small, boring defaults that most people skip because nothing bad has happened yet.

This is the checklist I actually run against every server I manage, in the order I run it — from the moment a box is provisioned to the ongoing maintenance that keeps it clean months later.

Day-One Hardening, Before Anything Else Goes Live

  • Create a non-root sudo user immediately, then disable root login over SSH. Root is the single most-targeted username on the internet. An attacker who compromises a named sudo user still has to escalate privileges — one extra wall that stops a huge share of automated attacks outright.
  • Switch to key-based SSH authentication and disable password authentication entirely. Password brute-forcing is the most common attack vector against exposed SSH ports. An SSH key that isn't guessable by brute force removes that attack surface completely, rather than just making it slower.
  • Change the default SSH port. This doesn't stop a targeted attacker, but it silences the overwhelming majority of automated scanning traffic that only checks port 22 — which cuts noise in your logs dramatically and makes real attack attempts easier to spot.
  • Set up a firewall with default-deny. UFW or iptables, configured to block everything except the specific ports you explicitly need (SSH on its new port, HTTP/HTTPS, anything else genuinely required) is non-negotiable. An open port you forgot about is the single most common way a server gets compromised without anyone noticing for weeks.
  • Install fail2ban (or an equivalent like CrowdSec) immediately. It watches auth logs and automatically bans IPs after repeated failed login attempts — a simple layer that neutralizes brute-force attempts across SSH, and any web-facing login forms you configure it to watch.

The five checks I run on every server before I call it "live"

  • • Root SSH login disabled and password auth off — key-based only
  • • Firewall active with default-deny and only required ports open
  • • fail2ban or equivalent running and actually banning, not just installed
  • • Automatic security updates enabled for the OS
  • • No service exposed to the public internet that doesn't need to be

Ongoing Maintenance: Where Most Servers Actually Get Compromised

Initial hardening protects a server on day one. Servers get breached months later, usually because the ongoing maintenance layer never existed. Unattended-upgrades (or the distro equivalent) for automatic security patching closes the gap between a CVE being disclosed and your server actually getting patched — a window attackers actively scan for and exploit within hours of a disclosure, not weeks. Beyond OS patching, every piece of software running on the box — the web server, the database, any CMS or application framework — needs its own update cadence, because an outdated WordPress plugin or an old Nginx build is just as exploitable as an unpatched kernel.

Log monitoring matters as much as patching. Reviewing auth logs, web server access logs, and fail2ban's ban list periodically — even a quick weekly pass — catches reconnaissance patterns (repeated probing of specific paths, unusual login attempt spikes) before they become an actual breach. Malware and file-integrity scanning, using something like Monarx or a similar server-side scanner, adds a layer that catches compromised files or injected malware even if the initial entry point was something you missed.

Application and Network-Layer Hardening

  • Bind databases to localhost only unless a specific, firewalled remote connection is genuinely required — a database listening on a public interface is one of the most common causes of large-scale data breaches, and it's entirely avoidable.
  • Enforce TLS everywhere, including on internal service-to-service traffic where practical, with certificates renewed automatically rather than tracked manually on a calendar that gets forgotten.
  • Set strict file permissions — web-facing application directories should never be world-writable, and secrets (API keys, database credentials) belong in environment variables or a secrets manager, never committed to a repo or left in a world-readable config file.
  • Rate-limit at the reverse proxy layer (Nginx, Caddy, or a CDN in front of the server) to blunt both basic DDoS attempts and credential-stuffing traffic before it ever reaches the application.
  • Isolate services with containers or separate users where practical, so a compromise in one application doesn't automatically grant access to everything else on the box.

Backups: The Control That Turns a Breach into an Inconvenience

Every hardening step above reduces the odds of a compromise. None of them makes it zero. Automated, regularly tested backups — snapshots plus off-server backups, not just one or the other — are what determine whether an actual breach costs you an afternoon of restoring from a known-good state, or costs you the entire server and everything on it. Untested backups are not backups; the only way to know a restore actually works is to have run it at least once before you need it for real.

Common Mistakes

  • Leaving root SSH login and password authentication enabled because key setup felt like an extra step
  • Configuring a firewall once at launch and never revisiting it as new services get added over time
  • Skipping automatic security updates because a manual update once broke something
  • Exposing a database or admin panel directly to the public internet "temporarily" and forgetting to close it
  • Having backups configured but never actually testing a restore, only discovering they're broken during a real incident

FAQ

Is changing the default SSH port actually worth doing?

It's not a substitute for key-based auth and a firewall, but it dramatically cuts the volume of automated scanning noise hitting your server, which makes genuine attack attempts far easier to spot in your logs.

How often should I actually be patching a production server?

OS security patches should be automatic. Application-level software (web server, database, CMS, frameworks) should be checked and updated at minimum monthly, and immediately for any disclosed critical vulnerability affecting software you run.

Do I need a Web Application Firewall on top of everything else?

For anything public-facing and business-critical, yes — a WAF adds a layer that catches application-level attacks (SQL injection, XSS attempts) that a network firewall and SSH hardening simply don't cover, since those operate at a different layer entirely.

How do I know if my hardening is actually enough?

Run an audit tool like Lynis periodically, and check your setup against this checklist on a schedule, not just once at launch — hardening isn't a one-time task, it's a maintenance habit that decays the moment it's ignored.

Every item on this checklist is simple in isolation, but the servers that actually stay secure are the ones where all of it runs together, consistently, month after month — which is exactly the part that's hardest to build alone the first few times you're doing it for real.

Ready to stop reading about it?

24 hours of direct, private mentorship over Telegram — screenshots, voice notes, and real answers for your specific situation.

© 2026 DCOUTLIER. Privacy Policy · Terms of Use