How to harden a new VPS: a security checklist
A brand-new server is exposed to the internet the moment it boots โ automated bots start probing it within minutes. The good news: a short list of well-understood steps blocks the overwhelming majority of those attacks. This is a practical, copy-pasteable checklist for locking down a fresh Linux VPS, with the reasoning behind each step.
Contents
1. Start with a realistic threat model
Before typing any commands, be clear about what you're defending against. For almost everyone running a VPS, the threat is opportunistic and automated: bots that sweep the entire IPv4 space looking for SSH servers with weak passwords, unpatched software with known CVEs, and misconfigured services left open to the world. You are not, in the typical case, the target of a determined human adversary.
That's encouraging, because opportunistic attacks are defeated by raising the bar just above "easy". Key-only SSH, a firewall, and timely patches eliminate the vast majority of real-world compromises. The steps below are ordered so that the highest-impact changes come first.
2. Create a non-root sudo user
Logging in as root means every process and every mistake runs with full privileges, and "root" is the one username every bot already guesses. Create an ordinary user with sudo access and use that instead.
# Debian / Ubuntu adduser deploy usermod -aG sudo deploy # RHEL family (Rocky, Alma, CentOS Stream, Fedora) adduser deploy passwd deploy usermod -aG wheel deploy
Give the new user your SSH key so you can log in as them, then verify sudo works before you disable root:
# copy root's authorized key to the new user rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy/ # from your laptop, in a NEW terminal: ssh deploy@YOUR_SERVER_IP sudo -v # should accept and return without error
3. Lock down SSH (keys only)
SSH is the front door, so it deserves the most attention. Use an ed25519 key, disable password and root login, and let only your key in. Generate a key locally if you don't have one:
ssh-keygen -t ed25519 -C "vps-key"
Then create a small drop-in config on the server (cleaner than editing the main file). On most modern distros the include directory is already active:
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf >/dev/null <<'EOF' PermitRootLogin no PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes AllowUsers deploy EOF # validate the config, then reload sudo sshd -t && sudo systemctl reload ssh # or: systemctl reload sshd
With a session still open, confirm you can open a fresh ssh deploy@IP connection. Only then close the original. Changing the SSH port is optional โ it adds no real security by itself, but it cuts a huge amount of automated scan noise from your logs. If you do, set Port 2222 (for example) and allow it in the firewall before reloading.
4. Set up a default-deny firewall
A firewall ensures that the only things reachable from the internet are the ports you explicitly chose โ so a service that gets installed later (or starts by accident) isn't silently exposed. On Debian/Ubuntu, ufw is the simplest option:
sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow OpenSSH # or: sudo ufw allow 2222/tcp # add only what you actually serve: # sudo ufw allow 80/tcp # sudo ufw allow 443/tcp sudo ufw enable sudo ufw status verbose
On the RHEL family, firewalld plays the same role (firewall-cmd --add-service=ssh --permanent). The principle is identical: deny by default, open the minimum.
5. Add fail2ban
fail2ban watches your logs and temporarily bans IPs that fail to authenticate repeatedly. With key-only SSH, brute force can't succeed anyway โ but fail2ban still trims log noise and becomes genuinely valuable once you expose other services (web apps, mail, etc.).
sudo apt install fail2ban -y # Debian/Ubuntu sudo tee /etc/fail2ban/jail.local >/dev/null <<'EOF' [sshd] enabled = true maxretry = 4 bantime = 1h findtime = 10m EOF sudo systemctl enable --now fail2ban sudo fail2ban-client status sshd
6. Turn on automatic security updates
Unpatched software is the other half of how servers get compromised. Let the system apply security patches on its own:
# Debian / Ubuntu sudo apt install unattended-upgrades -y sudo dpkg-reconfigure -plow unattended-upgrades # choose "Yes" # RHEL family sudo dnf install dnf-automatic -y sudo systemctl enable --now dnf-automatic.timer
Automatic security updates are safe to leave on. Do a full apt upgrade (or dnf upgrade) periodically too, and reboot when a kernel update needs it.
Need a server to harden?
Deploy a real cloud VPS in minutes โ pay with Bitcoin, Monero or USDT. No KYC, no bank card.
๐ Deploy a VPS7. Shrink the attack surface
Every listening service is a potential entry point. See what's actually open and switch off anything you don't need:
# list listening sockets and the process behind each sudo ss -tulpn
- Bind to localhost when you can. Databases and admin interfaces rarely need to face the internet โ bind them to 127.0.0.1 and reach them over an SSH tunnel.
- Remove unused packages and services. Fewer daemons means fewer CVEs to track.
- Don't run app services as root. Give each service its own unprivileged user.
- Set the basics: a sensible hostname, the correct timezone, and time sync (timedatectl set-ntp true) so your logs are trustworthy.
8. Backups and basic monitoring
On a destroy-anytime, hourly-billed VPS, your data lives and dies with the instance โ backups are your responsibility, not the host's. Take snapshots before risky changes and keep an off-server copy of anything you can't recreate. For monitoring, you don't need much to start: check authentication logs occasionally (journalctl -u ssh or /var/log/auth.log), and put a simple uptime check on any public service so you hear about an outage before your users do.
9. The quick checklist
- Created a non-root user with sudo and confirmed it works
- SSH set to key-only โ root login and passwords disabled
- Tested a fresh SSH session before closing the old one
- Default-deny firewall enabled, only required ports open
- fail2ban running on SSH (and any other public service)
- Automatic security updates enabled
- Reviewed listening ports; bound internal services to localhost
- Backups and a basic uptime/log check in place
Run through this once on every new box and you'll have shut the door on the attacks that actually happen in the wild. For a privacy-minded setup, this pairs naturally with our guide on deploying an anonymous VPS and paying with Monero, and the rundown of which crypto is best for paying anonymously.
FAQ
Do I still need fail2ban if I use SSH keys only?
Should I change the default SSH port?
Is a firewall necessary if I only run SSH?
How often should I apply updates?
GhostVPS is an anonymous, no-KYC VPS host on real DigitalOcean infrastructure. Pay with Bitcoin, Monero or USDT (TRC20); deploy in minutes from $6/mo. See pricing or open the panel.