Why Your Production Server Needs a Hardening Checklist
A freshly provisioned VPS is vulnerable by default. Default SSH passwords, open ports, unnecessary services, and misconfigured firewalls are the most common entry points for attackers. According to the 2026 Verizon Data Breach Investigations Report, 68% of server compromises involving VPS instances could have been prevented by following a structured hardening checklist. This guide provides 30 essential security steps organized by priority, with specific commands and configurations for Ubuntu 24.04 LTS and Debian 12 — the most common VPS operating systems in 2026.
Before you begin, ensure your provider supports the security features discussed here. Compare VPS providers on our performance comparison table to confirm your host offers features like encrypted boot volumes, DDoS protection, and firewall-as-a-service.
Phase 1: Immediate Access Hardening (Steps 1–8)
1. Disable Root SSH Login
Root login via SSH is the most targeted attack vector. Create a sudo user and disable root SSH access:
adduser deploy
usermod -aG sudo deploy
# Then edit /etc/ssh/sshd_config:
# PermitRootLogin no
2. Enforce SSH Key Authentication Only
Disable password authentication entirely. Ed25519 keys are now the recommended standard over RSA 4096:
# On your local machine
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/vps_key
# On the server, edit /etc/ssh/sshd_config:
# PasswordAuthentication no
# PubkeyAuthentication yes
# AuthenticationMethods publickey
3. Change Default SSH Port
Moving SSH off port 22 reduces automated attack volume by 95%+:
# In /etc/ssh/sshd_config:
# Port 2222
# Then update your firewall rules accordingly
4. Configure Fail2ban for SSH
Fail2ban adds rate-limiting to SSH attempts, blocking IPs after configurable thresholds:
sudo apt install -y fail2ban
sudo cp /etc/fail2ban/jail.{conf,local}
# In /etc/fail2ban/jail.local:
# [sshd]
# enabled = true
# port = 2222
# maxretry = 3
# bantime = 3600
sudo systemctl enable --now fail2ban
5. Set Up UFW with Minimal Rules
Uncomplicated Firewall (UFW) provides a simple interface to iptables/nftables:
ufw default deny incoming
ufw default allow outgoing
ufw allow 2222/tcp comment 'SSH'
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
ufw --force enable
6. Disable Unused Network Services
Audit and stop any services not required for production:
# List listening services
ss -tulpn
# Common services to disable if unused:
# sudo systemctl disable --now cups.service avahi-daemon.service postfix.service
7. Harden SSH Cipher Configuration
Use only modern, secure SSH ciphers in /etc/ssh/sshd_config:
Ciphers [email protected],[email protected]
KexAlgorithms [email protected],diffie-hellman-group16-sha512
MACs [email protected],[email protected]
8. Enable SSH Two-Factor Authentication
For production servers with administrative access, enable TOTP-based 2FA:
sudo apt install -y libpam-google-authenticator
google-authenticator
# In /etc/pam.d/sshd add: auth required pam_google_authenticator.so
# In /etc/ssh/sshd_config: AuthenticationMethods publickey,keyboard-interactive
Phase 2: System Hardening (Steps 9–16)
9. Keep System Packages Updated
Configure automatic security updates to ensure critical patches are never missed:
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
# Ensure only security updates are applied automatically
# Edit /etc/apt/apt.conf.d/50unattended-upgrades
10. Configure Kernel Hardening with sysctl
Add these sysctl settings to /etc/sysctl.d/99-hardening.conf:
# IP spoofing protection
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.default.rp_filter=1
# Ignore ICMP redirects
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 cookie protection
net.ipv4.tcp_syncookies=1
# Protect against time-wait assassination
net.ipv4.tcp_rfc1337=1
11. Set Filesystem Permissions Correctly
# Restrict /etc/shadow and /etc/gshadow
sudo chmod 640 /etc/shadow /etc/gshadow
# Set secure umask
echo "umask 027" >> /etc/profile
# Restrict world-writable directories
find / -type d -perm -o+w -not -path '/proc/*' -not -path '/sys/*' 2>/dev/null | grep -v '/tmp\|/var/tmp\|/dev/shm'
12. Install and Configure auditd
sudo apt install -y auditd audispd-plugins
# Monitor key system files
auditctl -w /etc/passwd -p wa -k passwd_changes
auditctl -w /etc/shadow -p wa -k shadow_changes
auditctl -w /etc/ssh/sshd_config -p wa -k sshd_config
13. Set Up Logwatch for Daily Log Review
sudo apt install -y logwatch
# Daily email summary of system activity
# Configure /etc/cron.daily/00logwatch
14. Restrict cron to Authorized Users
echo root > /etc/cron.allow
echo deploy >> /etc/cron.allow
chmod 600 /etc/cron.allow
15. Disable Unused Filesystems
Prevent attackers from exploiting less common filesystems by disabling them via /etc/modprobe.d/block-filesystems.conf:
install cramfs /bin/true
install freevxfs /bin/true
install jffs2 /bin/true
install hfs /bin/true
install hfsplus /bin/true
install udf /bin/true
16. Secure Shared Memory
# In /etc/fstab:
tmpfs /run/shm tmpfs defaults,noexec,nosuid 0 0
Phase 3: Application & Service Hardening (Steps 17–24)
17. Run Web Server Under Dedicated User
Ensure Nginx/Apache runs as its own user (www-data) with minimal privileges. Never run applications as root.
18. Set Up a Web Application Firewall (WAF)
# Using Nginx + ModSecurity 3.0
sudo apt install -y libmodsecurity3 nginx-mod-security
# Enable OWASP Core Rule Set 4.0+
# See: https://coreruleset.org/
19. Implement Rate Limiting
# In Nginx:
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/s;
limit_req zone=login burst=10 nodelay;
# In UFW:
ufw limit 2222/tcp
20. Harden PHP Configuration
# In /etc/php/8.4/fpm/php.ini:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,show_source
expose_php = Off
open_basedir = /var/www/html:/tmp
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
21. Configure Database Security
# MySQL/MariaDB secure installation
sudo mysql_secure_installation
# Bind to localhost only in /etc/mysql/mariadb.conf.d/50-server.cnf:
bind-address = 127.0.0.1
# Create application-specific user with minimal privileges
CREATE USER 'app'@'localhost' IDENTIFIED BY 'strong-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'localhost';
22. Enable HTTPS with Automatic Renewal
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
# Verify auto-renewal
sudo systemctl status certbot.timer
23. Set Up Intrusion Detection with AIDE
sudo apt install -y aide
sudo aideinit
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# Run weekly checks
sudo aide --check
24. Configure AppArmor Profiles
sudo apt install -y apparmor apparmor-profiles apparmor-utils
sudo aa-status # Check active profiles
sudo aa-enforce /usr/sbin/nginx # Enforce Nginx profile
Phase 4: Monitoring & Incident Response (Steps 25–30)
25. Set Up Centralized Logging
Forward logs to a remote syslog server or a log aggregation service:
# In /etc/rsyslog.d/remote.conf
*.* @logs.example.com:514
26. Install and Configure CrowdSec
CrowdSec is the modern successor to Fail2ban, using a community-driven IP reputation database:
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | bash
sudo apt install -y crowdsec
sudo cscli collections install crowdsecurity/nginx
sudo systemctl enable --now crowdsec
27. Monitor SSH Login Attempts
sudo journalctl -u ssh.service | grep 'Failed password'
# Set up a daily cron to report failed attempts:
sudo journalctl -u ssh.service --since yesterday | grep 'Failed password' | wc -l
28. Take Regular Snapshots and Backups
# Automate daily database dumps
echo "0 2 * * * mysqldump --all-databases | gzip > /backup/db-\$(date +\%Y\%m\%d).sql.gz" | crontab -
# Use provider snapshots or rsync to an off-site location
29. Create an Incident Response Plan
Document the steps to take if a compromise is detected:
- Isolate the affected server by updating firewall rules to deny all inbound traffic except from your investigation machine
- Take a forensic snapshot of the server before any cleanup
- Rotate all credentials (SSH keys, database passwords, API tokens)
- Review logs with
ausearchandjournalctlfor the attack timeline - Restore from the last known-good backup after eliminating the root cause
30. Perform Regular Security Audits
Run automated security scanners monthly:
# Lynis security audit
sudo apt install -y lynis
sudo lynis audit system
# Rootkit detection
sudo apt install -y rkhunter
sudo rkhunter --check
# OpenSCAP compliance scanning
sudo apt install -y libopenscap8 openscap-scanner
Conclusion
Security hardening is not a one-time task — it is an ongoing process. Implement these 30 steps in order of priority, and automate the recurring checks (unattended upgrades, log review, AIDE integrity checks, CrowdSec) to ensure continuous protection. A properly hardened VPS can withstand 99% of automated attacks and significantly raises the bar for targeted intrusions.
For additional protection, choose a VPS provider that offers DDoS mitigation, encrypted boot volumes, and a built-in firewall. Compare VPS providers on our performance comparison table to find a host with enterprise-grade security features at budget-friendly prices.

Leave a Reply
You must be logged in to post a comment.