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.

  • Security
  • Linux
  • Hardening