Skip to main content

VPS Security Hardening Checklist: Protect Your Server in 30 Minutes (2026)

· 7 min read
Yassine El Haddad
Software Developer & Automation Specialist

I build production AI agents, web scrapers, and automation pipelines. Most of what I publish here comes from the actual problems they run into: proxies that get banned, anti-bot stacks that fingerprint your client, RAG that drifts when the underlying data moves. Stack: Python, TypeScript, Go, FastAPI, LangChain, Crawlee, Playwright, deployed on AWS, GCP, and Cloudflare.

Default VPS configurations are insecure. Bots scan the internet for open ports and weak SSH configs within minutes of provisioning — brute-force attempts and exploit probes start almost immediately. A Liquid Web VPS gives you a solid foundation, but you still need to harden the OS. This guide walks through six essential steps to protect your server in about 30 minutes, whether you run self-hosted scrapers, APIs, or web apps.

Why VPS Security Matters

Unhardened servers are prime targets. Attackers run automated scans 24/7 looking for:

  • Default SSH — Port 22, root login, password auth
  • Unpatched software — Known CVEs in OpenSSH, Nginx, PHP
  • Open ports — Redis, MySQL, MongoDB exposed to the internet
  • Weak configs — No rate limiting, no fail2ban

A single compromised server can become a crypto miner, spam relay, or pivot for lateral movement. Hardening takes 30 minutes and drastically reduces your attack surface. For managed security, Liquid Web offers proactive monitoring and managed patching — ideal if you prefer not to DIY every layer.

Step 1: SSH Hardening

SSH is your primary access. Secure it first.

Disable root login and use key-based auth

Edit /etc/ssh/sshd_config:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Port 2222

Change Port to something non-default (e.g. 2222) to reduce noise from bots. Test your SSH key login before disabling passwords. Reload: systemctl reload sshd.

Configure fail2ban

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

Edit /etc/fail2ban/jail.local:

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

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

Restart fail2ban, then update UFW (next step) to allow your new SSH port.

Step 2: Firewall (UFW)

Allow only what you need. For most web apps: SSH, HTTP, HTTPS.

ufw default deny incoming
ufw default allow outgoing
ufw allow 2222/tcp # or your SSH port
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status

Never enable UFW before allowing your SSH port — or you'll lock yourself out. Test from another terminal before closing your session.

Step 3: Automatic Security Updates

Keep packages patched without manual intervention:

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

Edit /etc/apt/apt.conf.d/50unattended-upgrades to enable security updates. Optionally run a Lynis audit and aim for a score of 75+.

Step 4: User Management

Create a non-root user and disable password auth:

adduser deploy
usermod -aG sudo deploy
# Copy your SSH key: ssh-copy-id deploy@YOUR_SERVER

After confirming key-based login for deploy, set PasswordAuthentication no in sshd_config and disable root login.

Step 5: Nginx/Web Server Hardening

Hide version and add security headers. In your Nginx server block:

server_tokens off;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self';" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

For reverse proxies like Traefik, use the equivalent middleware for headers and TLS hardening.

Step 6: Monitoring — auditd and Alerts

Install auditd for audit trails:

apt install auditd -y
auditctl -w /etc/passwd -p wa -k passwd_changes
auditctl -w /etc/shadow -p wa -k shadow_changes

Watch logs with tail -f /var/log/syslog or ship them to a SIEM. Set up simple alerts (e.g. Cron + email or a monitoring service) for failed logins and service restarts.

Quick Security Checklist

Before going live, verify:

  • Root login disabled, SSH key-only auth
  • SSH port changed from 22 (or fail2ban tuned for 22)
  • UFW enabled: only SSH, 80, 443 open
  • Unattended-upgrades for security updates
  • Non-root user with sudo, password auth disabled
  • Nginx/Traefik: version hidden, HSTS, X-Frame-Options, CSP
  • auditd or log shipping configured
  • Backups configured (see Docker Compose production guide for volume backups)

Managed VPS vs DIY Security for Self-Hosted Scrapers

AspectManaged (Liquid Web)DIY Hardening
PatchingProactive, managedunattended-upgrades
FirewallOften pre-configuredUFW yourself
DDoS protectionIncludedSelf-mitigate or Cloudflare
Monitoring24/7, SLA-backedauditd, own alerts
CostHigher monthlyVPS only
ControlLess granularFull control
Best forProduction, complianceDev, hobby, learning

For production scrapers and APIs, Liquid Web VPS reduces operational burden with managed security, DDoS protection, and 99.99% uptime SLA. For dev and staging, DIY hardening on a budget VPS is sufficient — just follow this checklist. Pair with Coolify for app deployment and Traefik for TLS and routing.

When to Use Liquid Web Managed Security

Choose managed hosting when you need:

  • Compliance — PCI, HIPAA, or SOC2 requirements
  • Uptime — Mission-critical scrapers or APIs
  • Time — Prefer to focus on product, not ops
  • Support — 24/7 help with security incidents

Combine this hardening guide with Traefik v3 for SSL and Docker Compose production patterns for your containers. Your server will be ready for self-hosted scrapers, Coolify, and more.

Apify Affiliate Banner 728x90Apify Affiliate Banner 728x90Apify Affiliate Banner 300x50Apify Affiliate Banner 300x50
Test before you enforce

Always test SSH key login and UFW rules from a second session before closing your main connection. One wrong UFW rule or sshd_config change can lock you out — use the host's KVM/console as a last resort.

Frequently Asked Questions

About 30 minutes for SSH, UFW, fail2ban, unattended-upgrades, and basic Nginx headers. Add another 15–30 minutes for user setup and auditd.

You can reduce fail2ban's priority, but keeping it is still recommended. Port change reduces noise; fail2ban blocks persistent attackers who find your port.

Allow SSH (22 or your custom port), HTTP (80), HTTPS (443). Deny everything else. Add specific ports only if you run Redis, PostgreSQL, etc. — ideally keep those internal.

Managed (e.g. Liquid Web) for production, compliance, and uptime. DIY for dev, staging, learning, and cost-sensitive setups. This checklist works for both.

Use the host's web console (KVM/VNC) to log in locally. Restore PasswordAuthentication or fix UFW/fail2ban. Never disable password auth until key login is confirmed.

Common mistakes and fixes

Locked out after SSH hardening

Ensure you've added your SSH key and tested login before disabling password auth. Use your host's console (KVM/VNC) to regain access. Re-enable PasswordAuthentication temporarily if needed.

UFW blocks your connection

Allow SSH first: ufw allow 22/tcp. If you changed SSH port, use that port. Run ufw enable only after confirming the allow rule. Test from a second terminal before closing the first.

fail2ban bans your IP

Add your IP to ignoreip in /etc/fail2ban/jail.local. Use fail2ban-client set sshd unbanip YOUR_IP to unban. Whitelist your office/home IP range.