Hardening Linux Servers for Production
Essential security configurations including SSH hardening, firewall rules, fail2ban, and CIS benchmark compliance.
Hardening Linux Servers for Production
Every server exposed to the internet is a target. Whether you're running a single VM or managing a fleet of hundreds, security hardening is not optional — it's the baseline. Here are the essential configurations I apply to every production Linux server.
SSH Hardening
SSH is the front door to your server. Lock it down:
# /etc/ssh/sshd_config
# Disable root login
PermitRootLogin no
# Disable password authentication
PasswordAuthentication no
PubkeyAuthentication yes
# Restrict to specific users
AllowUsers deploy admin
# Use strong key exchange algorithms
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
# Limit authentication attempts
MaxAuthTries 3
LoginGraceTime 30
# Disable unused features
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
# Change default port (security through obscurity, but reduces noise)
Port 2222
After modifying sshd_config, always test with a new session before closing your current one. Getting locked out of a remote server is not fun.
Firewall with UFW
I use UFW (Uncomplicated Firewall) for its simplicity, backed by iptables:
# Reset and set defaults
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
# Allow SSH on custom port
ufw allow 2222/tcp comment 'SSH'
# Allow web traffic
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
# Rate limit SSH
ufw limit 2222/tcp
# Enable
ufw --force enable
The limit rule automatically blocks IPs that attempt more than 6 connections within 30 seconds — a simple but effective brute-force protection.
Fail2ban
Fail2ban monitors log files and bans IPs that show malicious patterns:
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
banaction = ufw
[sshd]
enabled = true
port = 2222
logpath = /var/log/auth.log
maxretry = 3
[nginx-http-auth]
enabled = true
logpath = /var/log/nginx/error.log
[nginx-limit-req]
enabled = true
logpath = /var/log/nginx/error.log
With this configuration, three failed SSH attempts within 10 minutes results in a 1-hour ban. For persistent attackers, I configure escalating ban times using fail2ban's recidive jail.
Automatic Security Updates
Enable unattended upgrades for security patches:
apt install unattended-upgradesdpkg-reconfigure -plow unattended-upgradesConfigure /etc/apt/apt.conf.d/50unattended-upgrades:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
};
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
CIS Benchmark Compliance
The CIS (Center for Internet Security) benchmarks provide comprehensive hardening guidelines. Key checks include:
# Ensure permissions on /etc/passwd
chmod 644 /etc/passwd
chmod 600 /etc/shadow
# Disable unused filesystems
echo "install cramfs /bin/true" >> /etc/modprobe.d/disable-filesystems.conf
echo "install freevxfs /bin/true" >> /etc/modprobe.d/disable-filesystems.conf
# Set sticky bit on world-writable directories
df --local -P | awk '{if (NR!=1) print $6}' | \
xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | \
xargs -I '{}' chmod a+t '{}'
# Audit system events
apt install auditd
systemctl enable auditd
For automated compliance checking, I use tools like lynis which audits the system against CIS benchmarks and provides a hardening score with actionable recommendations.
Monitoring and Alerting
Hardening without monitoring is incomplete. At minimum, set up:
- Log aggregation: Ship logs to a central location (Azure Monitor, ELK, Grafana Loki)
- File integrity monitoring: Use AIDE or OSSEC to detect unauthorized file changes
- Login notifications: Get alerted on SSH logins from unexpected IPs
Security is a continuous process, not a one-time setup. Review configurations regularly, keep systems updated, and always assume something is trying to get in.
Need help with your infrastructure?
Let's discuss your project and find the best solution together.
Get in touchRelated articles
Cloud Architecture Through the Shared Responsibility Model
How to design cloud systems with clear provider/customer boundaries for security, reliability, and operations.
Progressive Delivery in DevOps: Canary, Blue-Green, and Feature Flags
How to reduce deployment risk with progressive delivery patterns and measurable rollback criteria.