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:
- AppArmor or SELinux enforcing mode — mandatory access control for your web server and database.
- 2FA on SSH — Google Authenticator PAM module combined with key auth.
- ClamAV — rarely needed on Linux but mandatory if you accept user-uploaded files.
- Off-site backups — snapshots on your provider are not backups. Use Restic or Borg to S3-compatible storage.
- IPv6 firewall rules — UFW handles both IPv4 and v6 by default on modern distros, but verify with
sudo ip6tables -L. - Reduce kernel attack surface —
sudo apt install linux-hardenedon Debian-derived distros. - Docker hardening — don't run containers as root, drop capabilities, read-only filesystems where possible.
Common mistakes we see
Three things we see burn people repeatedly:
- Testing SSH changes from a single session. Always keep a second working session open while editing sshd_config.
- Opening MySQL/Postgres/Redis to 0.0.0.0. Bind to localhost only, use SSH tunnels or WireGuard for remote access.
- 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.