← Alex Reed

The 15-Minute Server Hardening Checklist

April 25, 2026 · 6 min read

I've hardened enough fresh VPS instances to know the drill. Here's the checklist I actually run, in order, every time. No security theater. No 200-page CIS benchmark. Just the things that stop real attacks.

Target: Ubuntu/Debian. Time: ~15 minutes if you copy-paste. Assumes root or sudo.

Step 1: Update Everything (2 min)

apt update && apt upgrade -y
apt autoremove -y

Not optional. Most exploits target known vulnerabilities with patches already shipped. If you're not updating, nothing else matters.

✅ Reboot if kernel updated. Unapplied kernel patches = no protection.

Step 2: Disable Password Auth (1 min)

# Copy your SSH key first. Do NOT skip this.
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd

Password auth is how most brute-force attacks succeed. SSH keys only. Period.

⚠️ Make sure your key is in ~/.ssh/authorized_keys BEFORE restarting sshd. Otherwise you lock yourself out.

Step 3: Disable Root Login (30 sec)

sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart sshd

Log in as a regular user. Use sudo. Root login over SSH is an unnecessary risk.

Step 4: Install and Enable UFW (2 min)

apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
# Only open what you need:
# ufw allow 80/tcp
# ufw allow 443/tcp
ufw enable
ufw status verbose

Default deny. Open only what you need. If you're running a web server, add 80 and 443. Nothing else.

✅ Rule of thumb: if you can't explain why a port is open, close it.

Step 5: Install Fail2Ban (2 min)

apt install -y fail2ban
systemctl enable fail2ban
systemctl start fail2ban

Default config bans after 5 failed SSH attempts for 10 minutes. That's fine for most setups. If you want tighter settings:

cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 3600
findtime = 600
EOF
systemctl restart fail2ban

Step 6: Remove Unnecessary Software (1 min)

# Check what's listening
ss -tlnp

# Remove common unnecessary packages
apt purge -y telnetd rsh-server tftpd 2>/dev/null
apt autoremove -y

Every listening service is an attack surface. If you don't need it, remove it.

Step 7: Set Up Automatic Security Updates (2 min)

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

Accept the prompt. This installs security updates automatically. You'll still need to handle major version upgrades manually, but day-to-day security patches land without intervention.

Step 8: Secure Shared Memory (30 sec)

echo 'tmpfs /run/shm tmpfs defaults,noexec,nosuid 0 0' >> /etc/fstab
mount -o remount /run/shm

Prevents certain privilege escalation attacks that use shared memory for execution.

Step 9: Limit su Access (30 sec)

dpkg-statoverride --update --add root su 4750
groupadd -r wheel 2>/dev/null
usermod -aG wheel $(whoami)
echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel
chmod 440 /etc/sudoers.d/wheel

Only users in the wheel group can sudo. Reduces the blast radius of a compromised user account.

Step 10: Verify (2 min)

# Run all of these and confirm:
ss -tlnp                    # Only expected ports listening
ufw status                  # Only expected ports allowed
fail2ban-client status sshd # Ban counter active
cat /etc/ssh/sshd_config | grep -E '(PasswordAuth|PermitRoot)'  # Both "no"
lastb | head                # Check for brute force attempts
journalctl -u sshd | tail   # No suspicious SSH activity

What This Doesn't Cover

This is the 15-minute checklist. It stops drive-by scans, brute force, and low-effort exploits. It does NOT cover:

Those are phase two. This checklist gets you from "embarrassingly vulnerable" to "reasonably hardened" in the time it takes to brew coffee.

The tl;dr

  1. Update everything
  2. SSH keys only, no root login
  3. UFW default deny
  4. Fail2ban
  5. Remove unused software
  6. Automatic security updates
  7. Verify everything

Done. Ship it.