Overview
A freshly installed Linux server is not secure by default. This guide covers essential hardening steps to protect production systems against common attacks and align with CIS benchmark recommendations.
Who Should Use This Guide
- System administrators deploying production servers
- Security engineers auditing Linux infrastructure
- DevOps teams hardening container hosts
Hardening Philosophy
| Principle | Description |
|---|---|
| Minimize Attack Surface | Remove unnecessary software and services |
| Least Privilege | Users and processes get minimum required access |
| Defense in Depth | Multiple overlapping security layers |
| Assume Breach | Prepare detection and containment mechanisms |
Requirements
System Requirements
| Component | Requirement |
|---|---|
| Operating System | Ubuntu 22.04+, Debian 12+, RHEL 8+, Rocky 8+ |
| Access | Root/sudo privileges |
| Network | Console access recommended as backup |
Tools Referenced
| Tool | Purpose |
|---|---|
auditd | System auditing |
fail2ban | Intrusion prevention |
ufw / firewalld | Host firewall |
aide | File integrity monitoring |
Process
Step 1: Update the System
Apply all available security patches.
Debian/Ubuntu:
sudo apt update && sudo apt upgrade -yRHEL/Rocky/Alma:
sudo dnf update -yEnable Automatic Security Updates (Debian/Ubuntu):
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgradesVerification:
# Check for remaining updates
apt list --upgradable # Debian/Ubuntu
dnf check-update # RHELExpected Result: No security updates pending.
Step 2: Create Administrative User
Never use root directly for administration.
Create User:
useradd -m -s /bin/bash <admin-username>
passwd <admin-username>Add to Sudo Group:
# Debian/Ubuntu
usermod -aG sudo <admin-username>
# RHEL/Rocky
usermod -aG wheel <admin-username>Verification:
su - <admin-username>
sudo whoamiExpected Output: root
Step 3: Disable Root Login
Prevent direct root access.
Lock Root Account:
sudo passwd -l rootOr Set Nologin Shell:
sudo usermod -s /usr/sbin/nologin rootImportant: Ensure sudo access works before disabling root.
Step 4: Configure Password Policy
Enforce strong password requirements.
Install PAM Module:
sudo apt install libpam-pwquality -yConfigure /etc/security/pwquality.conf:
# Minimum password length
minlen = 14
# Require at least one of each character type
dcredit = -1
ucredit = -1
ocredit = -1
lcredit = -1
# Minimum character classes
minclass = 3
# Maximum consecutive identical characters
maxrepeat = 3Configure Account Lockout:
Add to /etc/pam.d/common-auth (Debian) or /etc/pam.d/system-auth (RHEL):
auth required pam_faillock.so preauth silent deny=5 unlock_time=900
auth required pam_faillock.so authfail deny=5 unlock_time=900
Step 5: Configure Firewall
Enable host-based firewall with default deny.
UFW (Debian/Ubuntu):
# Install and configure
sudo apt install ufw -y
# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow required services
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP (if needed)
sudo ufw allow 443/tcp # HTTPS (if needed)
# Enable firewall
sudo ufw enablefirewalld (RHEL):
sudo systemctl enable --now firewalld
# Allow services
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reloadVerification:
sudo ufw status verbose
# or
sudo firewall-cmd --list-allStep 6: Disable Unnecessary Services
Reduce attack surface by stopping unused services.
List Running Services:
systemctl list-units --type=service --state=runningList Listening Ports:
ss -tulpnDisable Common Unnecessary Services:
# Printing (if not needed)
sudo systemctl disable --now cups
# mDNS/Bonjour
sudo systemctl disable --now avahi-daemon
# Bluetooth
sudo systemctl disable --now bluetooth
# Modem manager
sudo systemctl disable --now ModemManagerMask Services to Prevent Reactivation:
sudo systemctl mask cupsStep 7: Harden Kernel Parameters
Apply security-focused sysctl settings.
Create /etc/sysctl.d/99-security.conf:
# Disable IP forwarding (unless router/VPN)
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0
# Disable source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
# Disable ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Enable SYN cookies (SYN flood protection)
net.ipv4.tcp_syncookies = 1
# Log suspicious packets
net.ipv4.conf.all.log_martians = 1
# Ignore ICMP broadcasts
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Ignore bogus ICMP errors
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Enable reverse path filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Restrict kernel pointer exposure
kernel.kptr_restrict = 2
# Restrict dmesg access
kernel.dmesg_restrict = 1
# Restrict ptrace scope
kernel.yama.ptrace_scope = 2
# Enable ASLR
kernel.randomize_va_space = 2Apply Settings:
sudo sysctl -p /etc/sysctl.d/99-security.confVerification:
sysctl net.ipv4.tcp_syncookiesExpected Output: net.ipv4.tcp_syncookies = 1
Step 8: Secure File Permissions
Set appropriate permissions on sensitive files.
System Files:
sudo chmod 600 /etc/shadow
sudo chmod 600 /etc/gshadow
sudo chmod 644 /etc/passwd
sudo chmod 644 /etc/groupSSH Configuration:
sudo chmod 700 /etc/ssh
sudo chmod 600 /etc/ssh/sshd_configCron Directories:
sudo chmod 700 /etc/cron.d
sudo chmod 700 /etc/cron.daily
sudo chmod 700 /etc/cron.hourlyFind Problematic Permissions:
# World-writable files
find / -type f -perm -002 -exec ls -l {} \; 2>/dev/null
# SUID/SGID files (review for unnecessary entries)
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \; 2>/dev/nullStep 9: Secure Mount Options
Add security options to filesystem mounts.
Edit /etc/fstab:
# Add noexec, nosuid, nodev where appropriate
/dev/sda1 /tmp ext4 defaults,noexec,nosuid,nodev 0 2
/dev/sda2 /var ext4 defaults,nosuid 0 2
/dev/sda3 /var/tmp ext4 defaults,noexec,nosuid,nodev 0 2
/dev/sda4 /home ext4 defaults,nosuid,nodev 0 2Secure Shared Memory:
# Add to /etc/fstab
tmpfs /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0Apply Changes:
sudo mount -o remount /tmp
sudo mount -o remount /dev/shmStep 10: Configure System Auditing
Install and configure auditd for security monitoring.
Installation:
sudo apt install auditd audispd-plugins -y
sudo systemctl enable --now auditdCreate /etc/audit/rules.d/security.rules:
# Log authentication events
-w /var/log/auth.log -p wa -k auth_log
-w /etc/passwd -p wa -k passwd_changes
-w /etc/shadow -p wa -k shadow_changes
-w /etc/group -p wa -k group_changes
-w /etc/sudoers -p wa -k sudoers_changes
# Log privilege escalation
-w /bin/su -p x -k priv_esc
-w /usr/bin/sudo -p x -k priv_esc
# Log network configuration changes
-w /etc/hosts -p wa -k hosts
-w /etc/network/ -p wa -k network
# Log cron changes
-w /etc/crontab -p wa -k cron
-w /etc/cron.d/ -p wa -k cronLoad Rules:
sudo augenrules --loadVerification:
sudo auditctl -lStep 11: Install File Integrity Monitoring
Detect unauthorized file changes with AIDE.
Installation:
sudo apt install aide -yInitialize Database:
sudo aideinit
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.dbRun Integrity Check:
sudo aide --checkSchedule Daily Checks:
Create /etc/cron.daily/aide-check:
#!/bin/bash
/usr/bin/aide --check > /var/log/aide/aide-check-$(date +%Y%m%d).log 2>&1chmod 700 /etc/cron.daily/aide-checkAudit User Accounts
Regularly review user accounts for anomalies.
# Users with UID 0 (should only be root)
awk -F: '($3 == "0") {print}' /etc/passwd
# Users without passwords
awk -F: '($2 == "") {print}' /etc/shadow
# Users with login shells
grep -v '/nologin\|/false' /etc/passwdTroubleshooting
| Symptom | Possible Cause | Solution |
|---|---|---|
| Locked out after root disable | No sudo access | Use recovery mode or console |
| Services won't start | Missing permissions | Check journalctl -xe for details |
| Network issues after sysctl | Forwarding disabled | Adjust settings for routers/VPNs |
| Audit logs filling disk | Verbose rules | Tune audit rules or increase rotation |
Verification Checklist
Initial Setup
- System fully patched
- Automatic security updates enabled
- Non-root admin user created
- Root login disabled
Authentication
- Strong password policy enforced
- Account lockout configured
- SSH hardened (see SSH guide)
Network
- Firewall enabled with default deny
- Only required ports open
- IPv6 disabled if not used
Services
- Unnecessary services disabled
- Running services audited
- Service accounts use nologin shell
File System
- Sensitive file permissions verified
- Mount options hardened
- No unnecessary SUID/SGID files
Monitoring
- Auditd configured and running
- Log rotation enabled
- AIDE or similar installed
- Alerting configured
Ongoing Maintenance Schedule
| Frequency | Task |
|---|---|
| Weekly | Review authentication logs |
| Weekly | Check for failed login attempts |
| Monthly | Apply security patches |
| Monthly | Review user accounts |
| Monthly | Run vulnerability scan |
| Quarterly | Full security audit |
| Quarterly | Test backup restoration |
| Quarterly | Review firewall rules |
References
Last Updated: January 2026