Skip to main content

Harden your VPS: a checklist you can finish in 20 minutes

The concrete steps that stop the overwhelming majority of opportunistic attacks.

You will never make a server perfectly secure. You can make it an unattractive target in about twenty minutes, which deflects essentially all automated attacks.

1. Key-only SSH

Covered fully in SSH keys and access. This is the highest-value single step. Password brute-forcing is the most common intrusion method on the public internet and this eliminates it.

text
PasswordAuthentication no
PermitRootLogin prohibit-password

2. A default-deny firewall

Allow only what you actually serve. On Debian/Ubuntu:

bash
apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp          # SSH — see the warning below
ufw allow 80,443/tcp      # web
ufw enable
ufw status verbose

On RHEL-family, use firewalld:

bash
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload

Warning: enable the firewall while your SSH session is open and confirm SSH is allowed before you disconnect. If you change the SSH port, allow the new port first. See Firewall basics for the details, including our private mesh interface which must always be allowed.

3. Automatic security updates

bash
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades    # choose yes
# verify:
systemctl status unattended-upgrades --no-pager

On RHEL-family, dnf-automatic does the same job. Automatic security patches close the window between a vulnerability being published and being exploited — which in practice is often hours.

4. Fail2ban

Blocks an IP after repeated failed logins, turning an endless brute-force attempt into a dead end. See Fail2ban basics.

bash
apt install -y fail2ban
systemctl enable --now fail2ban

5. Turn off what you do not use

Every listening service is a potential entry point.

bash
ss -tulpn        # what is listening, and who owns it
systemctl --type=service --state=running   # what is running

Stop and disable anything you did not ask for. A minimal server is a secure server.

6. Run services as unprivileged users

Databases, web apps and workers should never run as root. Most packages create their own service user automatically; use it. If you are writing your own unit file, set User= and Group= explicitly.

7. Protect secrets

  • Never commit secrets to git. Use environment files with chmod 600.

  • Never make a config file world-readable if it contains a password or key.

  • Prefer per-service credentials over one shared admin credential.

8. Have a way back in

  • Confirm the rescue console in /panel/vps works before you need it.

  • Take a snapshot before risky changes — see Resize, snapshot and reinstall.

  • Keep at least one SSH key that is stored somewhere other than your everyday laptop.

9. Monitor

A server you never look at is a server you cannot defend. Add a monitoring check and read your logs occasionally — Reading your logs shows how.

Optional: intrusion detection

For higher-value hosts, CrowdSec (crowd-sourced blocking, MIT-licensed) and Wazuh (host intrusion detection) add real depth. Both are documented in our app hosting guides.

Related reading