Disclosure: we may earn a commission or referral reward from CloudCone, Contabo, DigitalOcean (account credit, not cash), Hostwinds, InterServer, RackNerd, VPSDime and Vultr if you sign up through our links. It does not change the price you pay. Every other provider pays us nothing. Prices in this guide are as of the date shown and may have changed; see the comparison pages for the latest checked prices.

Guides · BLOG

How to secure a VPS in 2026: the practical checklist

Some prices quoted in this guide are out of date. It is being rebuilt on our price index; for current prices use the comparison pages, which show when each price was checked.

A fresh VPS with the default configuration is scanned by botnets within minutes and has SSH brute-force attempts within an hour. This checklist takes 30 minutes and puts a fresh VPS in an actually-defensible position for real production use.

The threat model

We're not defending against nation-state actors. We're defending against:

1. Automated SSH brute-force looking for weak or default passwords.

2. Web application vulnerability scanners looking for known bugs in WordPress, phpMyAdmin, common CMSes.

3. Compromised NPM/PyPI/Composer packages that make outbound connections from your app.

4. Someone opening your ~/.aws/credentials file because you accidentally exposed it.

Real threats. Easily countered with basic hardening.

Step 1: SSH keys only (5 minutes)

Never SSH with a password.

Generate a key on your local machine if you don't have one:

```bash

ssh-keygen -t ed25519 -C "[email protected]"

```

Add the public key to your VPS:

```bash

ssh-copy-id user@vps

```

Or manually paste ~/.ssh/id_ed25519.pub into /home/user/.ssh/authorized_keys on the VPS.

Disable password SSH:

```bash

sudo sed -i 's/^#PasswordAuthentication./PasswordAuthentication no/' /etc/ssh/sshd_config

sudo systemctl restart ssh

```

Test in a NEW terminal before closing your current session. If you lock yourself out with a bad config, use your provider's console access to recover.

Step 2: Disable root SSH (2 minutes)

Nobody should log in as root. Create a sudo user instead:

```bash

adduser deploy

usermod -aG sudo deploy

mkdir -p /home/deploy/.ssh

cp ~/.ssh/authorized_keys /home/deploy/.ssh/

chown -R deploy:deploy /home/deploy/.ssh

```

Disable root SSH:

```bash

sudo sed -i 's/^#PermitRootLogin./PermitRootLogin no/' /etc/ssh/sshd_config

sudo systemctl restart ssh

```

Test with ssh deploy@vps and sudo -i.

Step 3: Firewall with UFW (2 minutes)

Only open the ports you actually need:

```bash

ufw allow OpenSSH

ufw allow 80

ufw allow 443

ufw --force enable

```

Check: ufw status.

Step 4: fail2ban for SSH (3 minutes)

Blocks IPs that fail SSH login attempts:

```bash

apt install fail2ban

```

Create /etc/fail2ban/jail.local:

```

[sshd]

enabled = true

findtime = 10m

maxretry = 3

bantime = 1h

```

```bash

systemctl restart fail2ban

```

Check bans: fail2ban-client status sshd.

Step 5: Automatic security updates (2 minutes)

Unattended-upgrades installs critical security patches automatically:

```bash

apt install unattended-upgrades

dpkg-reconfigure -plow unattended-upgrades

```

Verify enabled: /etc/apt/apt.conf.d/20auto-upgrades should have both settings at "1".

By default, only security-marked updates auto-install. Package updates that could break services stay manual.

Step 6: Remove services you don't use (2 minutes)

```bash

systemctl list-units --type=service --state=running

```

Anything you don't recognise, look up. If you don't need it, disable it:

```bash

systemctl disable --now unnecessary-service

```

Common candidates: sendmail (use msmtp or a relay instead), rpcbind, avahi-daemon, snapd (if you don't use snaps).

Step 7: Set up log monitoring (5 minutes)

Install logwatch for nightly emailed summaries:

```bash

apt install logwatch

```

Edit /etc/logwatch/conf/logwatch.conf:

```

Detail = Med

MailTo = [email protected]

```

Requires working mail delivery. Set up msmtp or a relay to Sendgrid/Mailgun if you don't have one.

Every morning: quick scan of last night's failed SSH attempts, sudo usage, cron output.

Step 8: Nginx / Apache hardening (5 minutes)

If you're serving HTTP:

Hide server version headers. In Nginx:

```nginx

/etc/nginx/nginx.conf, http block

server_tokens off;

```

In Apache:

```

/etc/apache2/conf-enabled/security.conf

ServerTokens Prod

ServerSignature Off

```

Rate limit — Nginx limit_req_zone for authenticated endpoints (login pages, API endpoints).

Deny access to sensitive files — .env, .git, backup files. In Nginx:

```nginx

location ~ /\.(env|git|htaccess) { deny all; }

location ~ \.(bak|old|orig|save)$ { deny all; }

```

Step 9: Application-layer security

Beyond the OS:

Use Cloudflare in front — see our Cloudflare setup guide. Blocks a lot of automated attacks at the edge.

Keep application dependencies updated. For Node: npm audit fix. For Python: pip-audit. For PHP: composer audit.

Rotate secrets regularly. API keys, database passwords, auth tokens.

Use environment variables for secrets, not hardcoded in code.

Step 10: Backup (5 minutes)

Because the best security is not needing to be secure — you can recover from a breach:

See our automated backups guide. Encrypted, off-server, tested restore.

What NOT to do

  • Don't change the SSH port and call it security. Obscurity is not security. Botnets scan all ports; only SSH keys + fail2ban actually help.
  • Don't install "security software" like anti-virus. Modern Linux servers don't have Windows-style malware; the tools are enterprise-oriented and mostly noise on a small VPS.
  • Don't disable IPv6 unless you have a specific reason. IPv6 is fine.
  • Don't remove sudo after locking down. You'll need it. Just don't NOPASSWD unless you know why.
  • Don't ignore unattended-upgrades failure emails. They mean auto-updates stopped.

After 30 minutes: you have

  • SSH-key-only login.
  • No root SSH.
  • Firewalled ports.
  • Brute-force protection.
  • Auto-installed security patches.
  • Log monitoring.
  • Nightly summary emails.

That's the practical baseline. From here, security is a discipline — updated dependencies, monitored logs, encrypted backups, secrets rotation.

Related guides