Most compromised servers aren’t victims of sophisticated attacks. They fall to weak passwords, unpatched software, services exposed by accident and missing backups. This checklist covers those basics in order of impact. Work through it on every new server, and revisit it a few times a year.
Access
1. Use SSH keys, disable password logins. Keys can’t be brute-forced. Set PasswordAuthentication no once key login works. → SSH keys
2. Disable direct root login. Log in as a named user and use sudo. → Disable root SSH login
3. One account per person. No shared logins; remove accounts when people leave. → Create users
4. Limit sudo. Full sudo for administrators only; command-restricted rules for automation. → sudo and sudoers
5. Restrict who can SSH in. AllowUsers or AllowGroups in sshd config; restrict port 22 to known IPs or a VPN if possible.
6. Consider 2FA for interactive admin logins. → SSH two-factor authentication
Updates
7. Patch promptly. Enable automatic security updates. → Unattended upgrades
8. Reboot for kernel updates (or use live patching). Check /var/run/reboot-required on Debian/Ubuntu or dnf needs-restarting -r on RHEL.
9. Run a supported OS release. End-of-life releases get no security fixes. → Check your Linux version
Network exposure
10. Enable a firewall: default deny incoming. Open only the ports you need. → UFW / firewalld
11. Audit listening services. sudo ss -tulpn — anything on 0.0.0.0 that shouldn’t be public? Databases, Redis, Memcached, Elasticsearch and admin panels belong on 127.0.0.1 or a private network. → Check open ports
12. Remember Docker bypasses the host firewall for published ports. Publish internal services on 127.0.0.1 only. → Docker networking
13. Block brute force. Fail2Ban or CrowdSec for SSH and web logins. → Fail2Ban
14. Remove what you don’t use. Every installed service is attack surface: systemctl list-units --type=service --state=running, disable and uninstall the rest.
Files and permissions
15. Secrets readable only by their owner. .env, wp-config.php, private keys: mode 600/640. → File permissions
16. No world-writable files in web roots. find /var/www -perm -o+w; never “fix” problems with chmod 777.
17. Run services as unprivileged users. Apps, workers and containers should not run as root.
18. Audit setuid binaries occasionally: find / -xdev -perm -4000 -type f.
Web applications
19. HTTPS everywhere. Free certificates with Let’s Encrypt; redirect HTTP to HTTPS. → Certbot on Nginx
20. Keep apps and plugins updated. For WordPress, outdated plugins are the number one entry point. → WordPress hardening
21. Hide version banners, add security headers, rate-limit logins. → Nginx rate limiting, security headers
22. Debug modes off in production. Laravel APP_DEBUG, Django DEBUG, Flask debug — they leak secrets.
Visibility and recovery
23. Keep logs and look at them. Persistent journal, log rotation, and a habit of checking auth logs. Consider central logging for several servers. → journalctl
24. Monitor. External uptime checks and resource alerts (disk, memory, CPU). → Uptime Kuma, Netdata
25. Backups: automated, offsite, tested. The final safety net against ransomware, mistakes and hardware failure. → Automated backups with Borg, the 3-2-1 rule
Quick audit commands
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|kbdinteractive'
sudo ss -tulpn
sudo ufw status verbose # or: sudo firewall-cmd --list-all
apt list --upgradable 2>/dev/null | wc -l
getent group sudo wheel
sudo find /var/www -xdev -perm -o+w -type f | head
sudo journalctl -u ssh --since "24 hours ago" | grep -c "Failed"
Automated auditing
Lynis scans the system and suggests improvements with a hardening index:
sudo apt install lynis
sudo lynis audit system
Use it as a checklist generator, not a score to maximise. → Lynis security audit
Going further
- Mandatory access control: keep SELinux enforcing (RHEL family) or AppArmor enabled (Ubuntu).
- File integrity monitoring with AIDE.
- Intrusion detection with Wazuh or Suricata.
- Kernel and network sysctl hardening.
- A bastion host or VPN for all admin access.
If you suspect a compromise
Don’t just delete the malware you find. Preserve evidence, rotate credentials, and in most cases rebuild the server from a clean image and restore data from backups made before the incident. → Detecting a compromised server
Every VPS.DO server gives you full root access to apply all of the above — and a VNC console so a firewall mistake never locks you out for good.