Overview

A newly provisioned VPS is a blank canvas — and an attractive target. Automated bots scan IP ranges constantly, probing for weak SSH passwords and unpatched services. Hardening your VPS isn’t paranoia; it’s basic hygiene.

This guide covers the essential hardening steps for an Ubuntu/Debian VPS. Each step is practical and has clear rationale.

Time required: 30-60 minutes Servers: Any Linux VPS (tested on Ubuntu 22.04 LTS)


1. Update the System

Before anything else, bring the system fully up to date:

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

Rebooting ensures you’re running on the latest kernel and base packages.


2. Create a Standard User

Never use root for daily administration. Create a standard user with sudo access:

# Create new user
sudo adduser aaron

# Add to sudo group
sudo usermod -aG sudo aaron

# Switch to the new user
sudo su - aaron

From now on, use sudo for administrative tasks.


3. Configure SSH Keys

Password authentication is a liability. SSH keys are much stronger.

On Your Local Machine

Generate a new ED25519 key (stronger and faster than RSA):

ssh-keygen -t ed25519 -C "aaron@workstation"

Save it to ~/.ssh/id_ed25519. Set a strong passphrase.

Add the Key to the Server

# Copy public key to server
ssh-copy-id -i ~/.ssh/id_ed25519.pub aaron@your-server-ip

You’ll be prompted for the user’s password once, then the key is installed.

Disable Password Authentication

# Edit SSH config
sudo nano /etc/ssh/sshd_config

Set these values:

PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
MaxAuthTries 3

Then restart SSH:

sudo systemctl restart sshd

Before logging out: Test that passwordless authentication works in a new terminal. If you lock yourself out, you can recover via the provider’s console.


4. Install and Configure UFW (Firewall)

Ubuntu’s Uncomplicated Firewall (UFW) makes firewall management simple.

# Default deny incoming, allow outgoing
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH (specific port to avoid lockout)
sudo ufw allow 22/tcp comment 'SSH'

# Allow HTTP/HTTPS
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

# Enable the firewall
sudo ufw enable

Verify the rules:

sudo ufw status verbose

Only the ports you explicitly allow will accept connections. This blocks all the scanning bots probing random ports.


5. Enable Automatic Security Updates

Unattended security updates prevent you from running vulnerable software:

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades

The configuration tool will ask if you want to enable automatic updates. Select Yes.

Verify it’s active:

systemctl status unattended-upgrades.service

6. Install and Configure Fail2ban

Fail2ban monitors auth logs and bans IPs that repeatedly fail authentication:

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

Create a local config to override defaults (avoiding changes to the package defaults):

sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5

[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log

Restart:

sudo systemctl restart fail2ban

Check status:

sudo fail2ban-client status
sudo fail2ban-client status sshd

7. Set Up Time Synchronization

Accurate time is critical for logs, certificates, and security protocols:

sudo apt install chrony -y
sudo systemctl enable chrony
sudo systemctl start chrony

Verify:

chronyc tracking

Add a few sysctl settings to improve network security:

sudo nano /etc/sysctl.d/99-hardening.conf
# Disable ICMP redirect acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# Enable TCP SYN cookies (prevent SYN flood attacks)
net.ipv4.tcp_syncookies = 1

# Hide kernel version from ICMP
net.ipv4.icmp_echo_ignore_all = 1

Apply:

sudo sysctl --system

9. Review Open Ports

Regularly check what’s listening:

# List all listening TCP ports
sudo ss -tlnp

# Check for unexpected services
sudo netstat -tlnp

Only services you explicitly installed should be listening. Shut down anything unexpected.


10. Set Up Logwatch for Monitoring

Logwatch summarizes daily log activity:

sudo apt install logwatch -y

Configure it to email you daily (requires a working mail setup):

sudo nano /etc/cron.daily/00logwatch

Add:

/usr/sbin/logwatch --output mail --mailto your@email.com --range today --detail high

Quick Reference

TaskCommand
Check SSH statussudo systemctl status sshd
Check firewallsudo ufw status verbose
Check fail2bansudo fail2ban-client status sshd
Check open portssudo ss -tlnp
Apply kernel hardeningsudo sysctl --system

When You’re Done

After hardening, your VPS has:

This is the baseline for any production server. The specific services you run (nginx, Docker, Coolify, etc.) will have their own hardening requirements, but this foundation applies universally.

Tired of managing servers?

This site helps you find the right FOSS hosting solution. If you'd rather have experts handle the infrastructure, OpsHelp offers fully managed hosting that supports open source.