Freshly provisioned Linux VPS instances are scanned by bots within minutes of going online. This 10-minute hardening checklist closes the most common attack vectors before they become incidents. All commands assume Ubuntu 22.04 / Debian 12; adapt package names for other distros.

Minute 1: Update everything

Never skip this step. You want the latest patched kernel and libraries from the first moment you log in.

sudo apt update && sudo apt upgrade -y
sudo reboot

Why it matters: a single unpatched SSH CVE or kernel bug turns hardening into theatre. Reboot after kernel updates to actually load the new kernel.

Minute 2: Create a non-root user

Never SSH in as root. Create a standard user with sudo privileges:

adduser deploy
usermod -aG sudo deploy

Log out and back in as deploy before continuing. Every step below happens as this user using sudo.

Minutes 3-4: Switch to SSH key authentication

Password auth is the #1 entry point for brute-force attacks. Disable it.

First, on your local machine, generate and copy your key:

# Local machine
ssh-keygen -t ed25519 -C "you@yourmachine"
ssh-copy-id deploy@your.vps.ip

Then on the VPS, edit /etc/ssh/sshd_config:

sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sudo systemctl restart sshd

Do not close your existing session until you verify a new one works. Open a second terminal and SSH in again. If it works, you're safe to close the original.

Minute 5: Move SSH off port 22 (optional but effective)

Changing the port stops 99% of drive-by scanners. Pick a high port like 2222:

sudo sed -i 's/^#*Port.*/Port 2222/' /etc/ssh/sshd_config
sudo systemctl restart sshd

Now connect with ssh -p 2222 deploy@your.vps.ip. Remember to open the new port in the firewall (next step).

Minute 6: Set up a firewall with UFW

Block everything except what you explicitly need:

sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp   # SSH (adjust port if you kept 22)
sudo ufw allow 80/tcp     # HTTP
sudo ufw allow 443/tcp    # HTTPS
sudo ufw enable

Verify with sudo ufw status verbose. If you have a cloud provider firewall too (Hetzner, DigitalOcean), duplicate these rules there for defense in depth.

Minute 7: Install fail2ban

fail2ban watches log files and bans IPs that repeatedly fail. Catches what slips through the firewall:

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

The default sshd jail is active immediately. Customize in /etc/fail2ban/jail.local if needed.

Minute 8: Enable unattended security upgrades

Security patches must install themselves. You will forget otherwise.

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

Confirm it's running: sudo systemctl status unattended-upgrades.

Minute 9: Disable unused services and ports

Check what's listening:

sudo ss -tulpn

Anything you don't recognize, investigate. Kill off unnecessary daemons:

# Common candidates to disable if not needed
sudo systemctl disable --now avahi-daemon
sudo systemctl disable --now cups
sudo apt purge telnet rsh-client -y

Minute 10: Enable logging and basic monitoring

You can't respond to what you don't see.

# Install auditd for system call logging
sudo apt install auditd -y
sudo systemctl enable --now auditd

# Install logwatch for daily summaries
sudo apt install logwatch -y
# Runs daily via cron, emails root by default

If you have a mail forward set up (or use the admin email in your VPSRated SMTP settings), you'll get a readable summary every morning.

Bonus: additional hardening for production

The above covers the 80/20. If this VPS runs something important, also consider:

Common mistakes we see

Three things we see burn people repeatedly:

  1. Testing SSH changes from a single session. Always keep a second working session open while editing sshd_config.
  2. Opening MySQL/Postgres/Redis to 0.0.0.0. Bind to localhost only, use SSH tunnels or WireGuard for remote access.
  3. Relying on "fail2ban will save me" for weak passwords. It won't — use keys only, period.

What about Docker and containerized apps?

Containers don't replace host hardening. Even a perfectly configured Docker daemon won't save you if the underlying Linux host is compromised. Do both. Also: never put Docker behind a root-bound socket exposed to the network — it's a privilege-escalation gift to any attacker who gets code execution.

Next steps

Hardening is a continuous practice, not a one-time task. Set a calendar reminder to audit again every 90 days. If you're looking for providers with built-in protection, our best VPS ranking highlights hosts with included DDoS protection. For Windows workloads, see our Windows RDP security guide.