🎁 New User? Get 20% off your first purchase with code NEWUSER20 Register Now →
Menu

Categories

The Ultimate Linux Security Hardening Checklist for Production Servers

The Ultimate Linux Security Hardening Checklist for Production Servers

Deploying a Linux server without proper security hardening is like leaving your front door wide open. Automated scanners, botnets, and opportunistic attackers continuously probe the internet for vulnerable systems. A freshly installed server can receive its first attack within minutes of going online.

This checklist covers the essential security measures every production Linux server needs, organized from most critical to supplementary. Work through it systematically and your server will be significantly harder to compromise.

Phase 1: Immediate Actions (First 30 Minutes)

1.1 Update Everything

The single most important security measure. Unpatched software is the number one attack vector.

# Debian/Ubuntu
sudo apt update && sudo apt upgrade -y

# RHEL/AlmaLinux/Rocky
sudo dnf update -y

# Enable automatic security updates
# Debian/Ubuntu
sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades

# RHEL/AlmaLinux
sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic.timer

1.2 SSH Hardening

SSH is the primary access point to your server and the most attacked service. Lock it down immediately.

# /etc/ssh/sshd_config - Critical changes:

# Disable root login
PermitRootLogin no

# Use key-based authentication only
PasswordAuthentication no
PubkeyAuthentication yes

# Change default port (optional but reduces noise)
Port 2222

# Limit access to specific users
AllowUsers deploy admin

# Disable empty passwords
PermitEmptyPasswords no

# Set idle timeout (5 minutes)
ClientAliveInterval 300
ClientAliveCountMax 0

# Disable X11 forwarding
X11Forwarding no

# Disable TCP forwarding (if not needed)
AllowTcpForwarding no

# Use strong key exchange and ciphers
KexAlgorithms curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# Restart SSH (keep your current session open!)
sudo systemctl restart sshd

# Test new connection in a SEPARATE terminal before closing current one

1.3 Configure Firewall

Only allow traffic you explicitly need. Default policy: deny everything, allow specific ports.

# Using UFW (Ubuntu/Debian)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp    # SSH (custom port)
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS
sudo ufw enable

# Using firewalld (RHEL/AlmaLinux)
sudo firewall-cmd --set-default-zone=drop
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

📚 Recommended Reading

Comprehensive security guides for Linux administrators:

Phase 2: User and Access Management

2.1 Create a Non-Root Admin User

# Create admin user
sudo adduser deploy
sudo usermod -aG sudo deploy

# Set up SSH key for the new user
sudo mkdir -p /home/deploy/.ssh
sudo cp ~/.ssh/authorized_keys /home/deploy/.ssh/
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys

2.2 Password Policy

# Install password quality checker
sudo apt install libpam-pwquality

# /etc/security/pwquality.conf
minlen = 14
dcredit = -1     # At least 1 digit
ucredit = -1     # At least 1 uppercase
lcredit = -1     # At least 1 lowercase
ocredit = -1     # At least 1 special character
maxrepeat = 3    # Max 3 consecutive identical characters

# Set password aging policy
sudo chage -M 90 -m 7 -W 14 deploy

2.3 Sudo Configuration

# Use visudo for safe editing
sudo visudo

# Add timestamp timeout (re-enter password every 5 min)
Defaults timestamp_timeout=5

# Log all sudo commands
Defaults logfile="/var/log/sudo.log"

# Restrict specific users to specific commands
deploy ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl restart php*

Phase 3: File System Security

3.1 Critical File Permissions

# Secure critical system files
sudo chmod 600 /etc/shadow
sudo chmod 600 /etc/gshadow
sudo chmod 644 /etc/passwd
sudo chmod 644 /etc/group
sudo chmod 700 /root
sudo chmod 600 /boot/grub/grub.cfg

# Find world-writable files (potential security risk)
find / -type f -perm -o+w -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null

# Find files with SUID/SGID bits set
find / -type f \( -perm -4000 -o -perm -2000 \) -not -path "/proc/*" 2>/dev/null

# Find files with no owner
find / -nouser -o -nogroup 2>/dev/null | head -20

3.2 Mount Point Hardening

# /etc/fstab - Add security options to mount points
# /tmp with noexec, nosuid, nodev
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev,size=2G 0 0

# /var/tmp linked to /tmp or similarly restricted
# /home with nosuid
/dev/mapper/vg-home /home ext4 defaults,nosuid,nodev 0 2

Phase 4: Kernel and Network Hardening

4.1 Sysctl Hardening

# /etc/sysctl.d/99-security.conf

# Disable IP forwarding (unless this is a router)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# Prevent IP spoofing
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.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Don't send ICMP redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Enable SYN cookies (protect against SYN flood)
net.ipv4.tcp_syncookies = 1

# Log suspicious packets
net.ipv4.conf.all.log_martians = 1

# Ignore broadcast ping requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Restrict kernel pointer exposure
kernel.kptr_restrict = 2

# Restrict dmesg access
kernel.dmesg_restrict = 1

# Disable core dumps
fs.suid_dumpable = 0
# Apply changes
sudo sysctl -p /etc/sysctl.d/99-security.conf

Phase 5: Intrusion Detection and Monitoring

5.1 Install Fail2Ban

# Install
sudo apt install fail2ban

# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
destemail = admin@example.com
action = %(action_mwl)s

[sshd]
enabled = true
port = 2222
maxretry = 3
bantime = 86400

[nginx-http-auth]
enabled = true
port = http,https

[nginx-botsearch]
enabled = true
port = http,https
# Start and check status
sudo systemctl enable --now fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd

5.2 File Integrity Monitoring with AIDE

# Install AIDE
sudo apt install aide

# Initialize database
sudo aideinit

# Move new database into place
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Run a check
sudo aide --check

# Add to cron for daily checks
0 5 * * * /usr/bin/aide --check | mail -s "AIDE Report $(hostname)" admin@example.com

📚 Advanced Security Topics

Go deeper into Linux security:

Phase 6: Application Security

6.1 Web Server Hardening (Nginx)

# /etc/nginx/nginx.conf or server block

# Hide version number
server_tokens off;

# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# Limit request size
client_max_body_size 10m;

# Limit request rate
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req zone=general burst=20 nodelay;

6.2 Database Security

# PostgreSQL - pg_hba.conf
# Use md5 or scram-sha-256 authentication
local   all   all                 scram-sha-256
host    all   all   127.0.0.1/32  scram-sha-256
host    all   all   ::1/128       scram-sha-256

# Never allow remote connections without SSL
hostssl all   all   0.0.0.0/0     scram-sha-256

Security Hardening Checklist Summary

CategoryActionPriority
UpdatesEnable automatic security updatesCritical
SSHDisable root login, use key-based auth onlyCritical
FirewallDefault deny, allow only needed portsCritical
UsersNon-root admin user, strong password policyHigh
Fail2BanBrute force protection for SSH and webHigh
KernelSysctl network and kernel hardeningHigh
FilesCorrect permissions, mount optionsMedium
AIDEFile integrity monitoringMedium
Web ServerSecurity headers, rate limiting, hide versionMedium
AuditRegular security audits and log reviewMedium

Conclusion

Security hardening is not a one-time task — it is an ongoing process. Start with the Critical items in Phase 1 (they take 30 minutes), then work through the remaining phases over the following days. Schedule monthly security reviews to verify your configurations remain intact and update your practices as new threats emerge.

The goal is not to make your server impenetrable (nothing is), but to make it hard enough that attackers move on to easier targets. By following this checklist, you raise the bar significantly above the vast majority of internet-facing servers.

Share this article:

Stay Updated

Subscribe to our newsletter for the latest tutorials, tips, and exclusive offers.