A fresh VPS is reachable from the entire internet within seconds of provisioning. Automated scanners will find it before you do. Port probes, brute-force SSH attempts, and vulnerability scans start hitting new IP addresses almost immediately, not because anyone is targeting you specifically, but because bots sweep entire IP ranges continuously.

If you are running an unmanaged VPS, every item on this list is your responsibility. Managed plans handle some of these steps for you, but the scope varies wildly between providers. Either way, knowing what "secured" actually looks like puts you in a better position to verify the work, whether you did it yourself or someone else did.

These 10 steps are ordered roughly by priority. Do them in sequence on a fresh server before deploying anything into production.

1. Apply All Pending Updates First

Before touching configuration files or installing software, update the operating system. The image your provider used to provision the server may be weeks or months behind on security patches.

On Debian and Ubuntu systems, that means apt update && apt upgrade. On RHEL, Rocky, or Alma, use dnf update. Reboot afterward if the kernel was updated. This takes minutes and closes vulnerabilities that are already public knowledge.

Skipping this step means every configuration change you make afterward sits on top of a potentially compromised foundation.

2. Create a Regular User and Stop Logging In as Root

Root has unrestricted access to everything. Using it as your daily login account means every typo, every compromised session, and every misconfigured script runs with full system privileges.

Create a regular user account, add it to the sudo group, and confirm you can log in with it. Once that works, disable direct root login over SSH by setting PermitRootLogin no in your SSH server configuration. Restart the SSH service to apply the change.

This does not stop you from running commands as root when you need to. It stops an attacker who guesses or brute-forces the root password from getting a shell.

3. Switch to SSH Key Authentication

Password-based SSH login is the single most common entry point for brute-force attacks on VPS instances. Switching to key-based authentication eliminates that entire attack surface.

Generate a key pair on your local machine (RSA 4096-bit or Ed25519 are both solid choices), copy the public key to the server, and then set PasswordAuthentication no in your SSH configuration. Test that key login works in a separate terminal session before closing your current one. Locking yourself out of your own server by disabling password auth before confirming key auth works is a mistake that happens exactly once per person.

If your provider offers a console or out-of-band access, confirm you know how to reach it before making this change. That is your recovery path if something goes wrong.

4. Configure a Firewall

A default VPS installation often has no firewall rules active. Every listening service is reachable from the internet.

The goal is simple: block everything inbound except the ports you explicitly need. For most web servers, that means SSH (port 22 or a custom port), HTTP (80), and HTTPS (443). Everything else should be denied by default.

On Ubuntu and Debian, ufw is the most straightforward tool. On RHEL-family distributions, firewalld is the standard. Both are front-ends for the underlying packet filtering system. The important thing is not which tool you use but that you actually enable it and verify the rules.

A common mistake: opening a port for temporary debugging and forgetting to close it. Keep your firewall rules in a configuration file or script that you can review and reapply.

5. Install Fail2ban

Even with key-only SSH, your server logs will fill with failed authentication attempts. Fail2ban watches log files for repeated failures and temporarily bans the source IP using firewall rules.

The default configuration covers SSH out of the box. If you run other services that accept authentication (a web application login page, an FTP server, a mail server), add jails for those as well.

Fail2ban does not make a weak configuration secure. It reduces noise and slows down brute-force attempts. Think of it as a filter that removes the easy automated attacks so your logs remain useful for spotting real threats.

6. Disable Services You Are Not Using

A fresh server image often comes with services running that you did not ask for and do not need. Each one is a potential attack surface.

List what is listening with ss -tlnp or netstat -tlnp. If you see a service you do not recognise or do not need, stop it and disable it from starting at boot. Common examples: mail transfer agents, FTP servers, and database engines installed by default but not required for your workload.

The principle is straightforward: the fewer things running, the fewer things that can be exploited. A web server that only runs Nginx and your application has far less exposure than one that also runs Postfix, vsftpd, and a publicly accessible MySQL instance.

7. Enable Automatic Security Updates

Manual patching works until the day you forget. Or go on holiday. Or get busy with a deadline and push it back a week, which turns into a month.

Both unattended-upgrades (Debian/Ubuntu) and dnf-automatic (RHEL/Rocky/Alma) can be configured to install security patches automatically. The conservative approach is to auto-install security updates only, not full version upgrades, so you get critical fixes without risking compatibility-breaking changes.

Check the logs periodically to confirm updates are actually being applied. Automated does not mean invisible.

8. Set Up TLS for Every Public-Facing Service

Any service exposed to the internet should use TLS. For web traffic, that means HTTPS. For other protocols (database connections, mail, API endpoints), the same principle applies.

Free TLS certificates from Let's Encrypt, combined with automated renewal via Certbot or a similar ACME client, have removed every practical barrier to running HTTPS. There is no legitimate reason to serve production traffic over plain HTTP.

Beyond encryption, many browsers and search engines now penalise or flag HTTP-only sites. TLS is a baseline expectation, not a premium feature.

While you are at it, redirect HTTP to HTTPS so no traffic is accidentally served unencrypted. Most web server configurations make this a single directive.

9. Configure Automated Backups and Test a Restore

Backups that have never been restored are not backups. They are assumptions.

Set up automated backups of your application data, databases, and critical configuration files. Store them off-server: a separate storage service, a different VPS, or an object storage bucket. Backups stored on the same machine they protect are useless if that machine fails or is compromised.

Then test the restore process. Spin up a fresh instance, pull the backup, and confirm your application runs. Do this at least once. The time to discover your backup process is broken is not the day you actually need it.

The self-hosting tools guide covers Vaultwarden specifically on this point: a lost database without a tested backup means a lost vault. The same principle applies to everything on your server.

10. Set Up Monitoring and Alerting

A server you never check on is a server where problems go unnoticed. Breaches, disk fills, crashed services, failed backups: if nothing alerts you, you find out from your users (or worse, you never find out at all).

At minimum, monitor:

  • Disk usage (full disks cause cascading failures)
  • Memory pressure
  • CPU load
  • SSH login attempts
  • Service availability (is your web server actually responding?)

Uptime Kuma, Prometheus with Node Exporter, or even a simple cron job that pings a healthcheck endpoint and sends an email on failure are all valid starting points. The complexity should match the stakes. A personal project does not need an enterprise monitoring stack, but it does need something that tells you when things break.

The managed vs unmanaged guide explains this split in detail: on a managed plan, your provider typically handles monitoring and incident response. On an unmanaged plan, a crashed service stays down until you notice. Choose your monitoring investment accordingly.

Quick Reference

Step What it prevents Time to complete
Apply updates Known vulnerability exploitation 5 to 15 minutes
Non-root user Full-privilege compromise from a single session 5 minutes
SSH key auth Brute-force password attacks 10 to 20 minutes
Firewall Unauthorized access to non-public services 10 minutes
Fail2ban Automated brute-force flooding 10 minutes
Disable unused services Unnecessary attack surface 10 to 20 minutes
Automatic security updates Unpatched vulnerabilities from delayed maintenance 10 minutes
TLS everywhere Data interception, browser warnings, SEO penalties 15 to 30 minutes
Automated backups Unrecoverable data loss 30 to 60 minutes
Monitoring Silent failures and undetected breaches 20 to 60 minutes

The total time commitment for all 10 steps is roughly two to four hours on a fresh server. That is a one-time investment that prevents the most common categories of VPS compromise.

Where to Go from Here

Security is not a one-time task, but this checklist covers the foundation. If you are still deciding on a provider, the VPS evaluation guide covers what to assess before committing, and user reviews on the site surface real-world experiences with reliability and support quality across dozens of providers. Browse the full providers directory to compare options with your security requirements in mind.