Hands-on VPS & self-hosting Monday, June 1, 2026
VPS.app
Hands-on VPS benchmarks and self-hosting guides — tested, not theorized.
Self-Hosting Guides

How to Secure a VPS: 10 Essential Steps (2026)

Some links below are affiliate links: if you buy through them I may earn a commission at no extra cost to you. I only recommend what I have actually tested, and it never changes my verdict.

VPS server security hardening

Every time a new VPS boots, it is already reachable from the entire internet. Within minutes, automated scanners are probing port 22 trying default credentials. This guide is the checklist I run through on every fresh box — tested on Ubuntu 24.04 LTS, applicable with minor adjustments to any Debian-based distro.

Work through the sections in order. Each step takes two minutes or less, and together they close the gaps that the vast majority of real-world attacks exploit.

1. Create a non-root user

Providers give you root by default. The first thing to do is make a normal user and switch to it permanently.

adduser deploy
usermod -aG sudo deploy

Log out, reconnect as deploy, and confirm sudo works before you continue:

sudo whoami
# should output: root

Never log in as root again. If you need elevated access, use sudo.

2. Set up SSH keys and disable password login

Password login is the main attack surface automated bots target. Replace it with key-based authentication.

Generate a key pair on your local machine if you do not have one already:

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

Copy the public key to the server:

ssh-copy-id deploy@YOUR_SERVER_IP

Test that key login works, then open /etc/ssh/sshd_config on the server and set:

PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no

Restart SSH — but keep your current session open while you test in a second window:

sudo systemctl restart ssh

Open a new terminal and confirm you can still log in with your key before closing the original session.

3. Configure a firewall

UFW (Uncomplicated Firewall) ships with Ubuntu and gives you a readable default-deny policy in a few commands.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Run the allow OpenSSH line before ufw enable, or you will lock yourself out. Add only the ports your services actually need — everything else stays closed.

4. Enable automatic security updates

Unpatched packages are how most servers get compromised weeks or months after initial setup. Let the OS handle security patches automatically.

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

Verify it is active:

sudo systemctl status unattended-upgrades

The default configuration installs security updates only, leaving feature updates for you to apply manually. That is the right balance — you get patches without unexpected breakage.

5. Install Fail2ban

Even with SSH keys enabled, bots still hammer every open port. Fail2ban reads service logs and bans IPs that trigger too many failures, reducing noise and protecting other services alongside SSH.

sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit /etc/fail2ban/jail.local to set sensible defaults in the [DEFAULT] section:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5

Enable and start it:

sudo systemctl enable --now fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd

6. Reduce attack surface

The fewer things exposed, the smaller the target. Two quick wins:

Close unused ports. List what is currently listening:

sudo ss -tulnp

Disable services you do not need. Common candidates on a fresh Ubuntu install:

sudo systemctl stop avahi-daemon
sudo systemctl disable avahi-daemon

Do not expose app ports directly. Run applications on localhost and put them behind a reverse proxy that handles HTTPS termination. This means your app never touches the public internet directly, and you only need ports 80 and 443 open. See the Nginx Proxy Manager setup guide for a straightforward way to do this.

Bonus: should you change the SSH port?

Moving SSH from port 22 to something like 2222 or 51022 is a common recommendation. The honest take: it eliminates a large volume of automated scanner noise from your logs, which makes it easier to spot real events. It is not a security control — any port scanner finds your SSH within seconds. Do not rely on it instead of key auth and a firewall; do it in addition if log cleanliness matters to you.

If you do change it, allow the new port in UFW before restarting SSH:

sudo ufw allow 2222/tcp

Then update Port 2222 in /etc/ssh/sshd_config and restart.

Troubleshooting and gotchas

Four situations that trip people up:

Locked out after disabling password auth. Always keep an existing session open while you test changes. If you do get locked out, most providers offer a web console or rescue mode that bypasses SSH entirely — use that to re-enable password auth temporarily, then fix the issue properly.

UFW blocked SSH. This happens when you run ufw enable before adding the SSH allow rule. Fix it via the provider console: disable UFW (ufw disable), add the SSH rule, then re-enable.

Key auth fails even after ssh-copy-id. The most common cause is wrong permissions. On the server, the ~/.ssh directory must be 700 and ~/.ssh/authorized_keys must be 600, both owned by your user:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Fail2ban banned yourself. Check whether your IP is banned:

sudo fail2ban-client status sshd

Unban it:

sudo fail2ban-client set sshd unbanip YOUR_IP

Add your home IP to the ignoreip line in jail.local to prevent this recurring.

After hardening

With the basics in place, the natural next steps are:

For host recommendations: Hetzner offers excellent value for European and US regions; Vultr has a developer-friendly cloud with solid global coverage.

Frequently asked questions

What is the single most important VPS security step?

Switching SSH from password login to key-based authentication and disabling root password login. It removes the entire brute-force attack surface that most automated bots rely on.

Do I need fail2ban if I use SSH keys?

It still helps — fail2ban bans IPs that hammer your services, cutting log noise and protecting other ports. With SSH keys it is defense in depth rather than your only line of defense.

Should I disable the root account entirely?

Do not delete it, but disable direct root SSH login (PermitRootLogin no) and use a normal user with sudo. That gives you an audit trail and prevents direct root brute-forcing.

How do I keep a VPS patched automatically?

On Debian/Ubuntu, enable unattended-upgrades for security patches. Reboot on a schedule for kernel updates, or use Ubuntu Pro Livepatch where available.

Will changing the SSH port actually make my server safer?

It reduces log noise from automated scanners but does not stop a targeted attacker. Treat it as a minor convenience, not a real security control — key auth and a firewall matter far more.