A freshly provisioned Linux server is not secure by default. Package managers install services with permissive configurations, default accounts may have weak credentials, and unnecessary attack surface is exposed. Server hardening is the process of reducing that surface to the minimum required for your application to function.
This checklist covers 20 essential steps organized from most critical to defense-in-depth measures. It is based on industry standards like the CIS Benchmarks and real-world production experience.
User Accounts and Access Control
1. Create a dedicated admin user
Never use root for daily administration. Create a named user with sudo privileges so all actions are attributable and auditable.
$ adduser admin
$ usermod -aG sudo admin
2. Enforce strong password policies
Configure PAM to require minimum length, complexity, and password age. Even if you use key-based SSH, passwords still protect sudo and console access.
$ sudo apt install libpam-pwquality
# /etc/security/pwquality.conf
minlen = 12
minclass = 3
3. Lock unused accounts
Disable or lock any default or unused accounts. Every active account is a potential entry point.
$ sudo passwd -l nobody
$ sudo usermod --expiredate 1 games
4. Configure sudo with least privilege
Do not give blanket sudo access. Use the sudoers file to grant specific commands to specific users or groups.
# /etc/sudoers.d/deploy
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp
SSH Hardening
5. Harden SSH configuration
SSH is your primary attack surface. Apply these critical settings:
# /etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3
AllowUsers admin deploy
6. Install fail2ban
Automatically ban IP addresses after repeated failed login attempts. Essential for any internet-facing server. Configure it to monitor SSH, and optionally your web server and application logs.
Firewall and Network Security
7. Enable a host firewall
Use ufw or iptables/nftables to allow only necessary ports. Default deny all incoming traffic.
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
$ sudo ufw allow 22/tcp # SSH
$ sudo ufw allow 443/tcp # HTTPS
$ sudo ufw enable
8. Disable unnecessary services
Every running service is a potential attack vector. List active services and disable anything not needed.
$ systemctl list-units --type=service --state=running
$ sudo systemctl disable --now cups avahi-daemon bluetooth
9. Configure network parameters
Harden the network stack with sysctl settings to prevent common network attacks.
# /etc/sysctl.d/99-hardening.conf
net.ipv4.conf.all.rp_filter = 1 # reverse path filtering
net.ipv4.conf.all.accept_redirects = 0 # ignore ICMP redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1 # ignore broadcast pings
net.ipv4.tcp_syncookies = 1 # SYN flood protection
System Updates and Package Management
10. Enable automatic security updates
Unpatched software is the leading cause of server compromises. Enable unattended security updates.
$ sudo apt install unattended-upgrades
$ sudo dpkg-reconfigure -plow unattended-upgrades
11. Remove unnecessary packages
Audit installed packages and remove anything that is not required. Compilers, development tools, and debugging utilities should not be on production servers — they make exploitation easier.
Filesystem Security
12. Set proper mount options
Use restrictive mount options to limit what can happen on each partition.
# /etc/fstab
/dev/sda2 /tmp ext4 defaults,nosuid,noexec,nodev 0 0
/dev/sda3 /var ext4 defaults,nosuid 0 0
/dev/sda4 /home ext4 defaults,nosuid,nodev 0 0
13. Find and fix insecure permissions
Regularly scan for world-writable files, files without owners, and SUID/SGID binaries.
# Find world-writable files
$ find / -xdev -perm -o+w -type f
# Find SUID binaries
$ find / -xdev -perm -4000 -type f
Logging and Auditing
14. Configure centralized logging
Ship logs to a central server or SIEM. If a server is compromised, local logs can be tampered with. Use rsyslog, systemd-journal-remote, or a log agent (Fluentd, Vector, Filebeat) to forward logs.
15. Enable the Linux audit framework
auditd provides detailed tracking of security-relevant events: file access, system calls, user actions.
$ sudo apt install auditd
# /etc/audit/rules.d/hardening.rules
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k sudo_changes
-w /var/log/ -p wa -k log_tampering
16. Set up log rotation
Ensure logs are rotated and retained for an appropriate period. Unrotated logs can fill disks and cause service outages. Configure logrotate for application-specific logs that are not managed by journald.
Kernel and Advanced Hardening
17. Restrict kernel modules
Prevent loading of unnecessary kernel modules to reduce the kernel attack surface.
# /etc/modprobe.d/hardening.conf
install cramfs /bin/false
install freevxfs /bin/false
install usb-storage /bin/false # if USB not needed
18. Enable SELinux or AppArmor
Mandatory Access Controls (MAC) provide an additional security layer beyond traditional file permissions. SELinux (RHEL/CentOS) or AppArmor (Ubuntu/Debian) restrict what each process can access, even if it runs as root. Do not disable these — learn to work with them.
19. Set up intrusion detection
Deploy file integrity monitoring to detect unauthorized changes to system files.
$ sudo apt install aide
$ sudo aideinit # initialize baseline
$ sudo aide --check # compare against baseline
20. Implement regular security scanning
Use tools like Lynis, OpenSCAP, or cloud-native scanners to regularly audit your server against security benchmarks. Automate these scans and review the reports. Security hardening is not a one-time task — it requires continuous monitoring and improvement.
$ sudo apt install lynis
$ sudo lynis audit system
Quick Reference Checklist
USER & ACCESS
□ 1. Create dedicated admin user
□ 2. Enforce strong password policies
□ 3. Lock unused accounts
□ 4. Configure least-privilege sudo
SSH
□ 5. Harden sshd_config
□ 6. Install fail2ban
NETWORK
□ 7. Enable host firewall (default deny)
□ 8. Disable unnecessary services
□ 9. Harden network parameters (sysctl)
UPDATES
□ 10. Enable automatic security updates
□ 11. Remove unnecessary packages
FILESYSTEM
□ 12. Set restrictive mount options
□ 13. Audit file permissions
LOGGING
□ 14. Configure centralized logging
□ 15. Enable auditd
□ 16. Set up log rotation
KERNEL & ADVANCED
□ 17. Restrict kernel modules
□ 18. Enable SELinux/AppArmor
□ 19. Set up intrusion detection (AIDE)
□ 20. Schedule regular security scans (Lynis)