← Blog / Linux & Shell

Linux Server Hardening — Complete Production Checklist

Introduction

A freshly installed Linux server — whether Debian, Ubuntu or Rocky Linux — is not ready for a production environment. The default configuration is optimised for user convenience, not security. This article provides a complete hardening checklist we apply to every new server.


1. System Update

First thing after installation — full package update.

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

# RHEL / Rocky Linux / AlmaLinux
dnf update -y && dnf autoremove -y

Set up automatic security updates:

# Debian / Ubuntu
apt install unattended-upgrades -y
dpkg-reconfigure --priority=low unattended-upgrades

# RHEL / Rocky
dnf install dnf-automatic -y
systemctl enable --now dnf-automatic-install.timer

2. SSH Configuration

SSH is the most frequently attacked entry point. The following changes to /etc/ssh/sshd_config eliminate most common attacks.

nano /etc/ssh/sshd_config

Key settings:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Port 2222
AllowUsers deploy admin
MaxAuthTries 3
MaxSessions 5
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
PermitEmptyPasswords no

Restart SSH and test the connection before closing the current session:

sshd -t
systemctl restart sshd

3. Firewall (nftables / ufw / firewalld)

Ubuntu / Debian — UFW

apt install ufw -y
ufw default deny incoming
ufw default allow outgoing
ufw allow 2222/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status verbose

RHEL / Rocky — firewalld

systemctl enable --now firewalld
firewall-cmd --set-default-zone=drop
firewall-cmd --permanent --add-port=2222/tcp
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload

4. Fail2Ban — Brute-Force Protection

apt install fail2ban -y
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

SSH configuration:

[DEFAULT]
bantime  = 3600
findtime = 600
maxretry = 3
backend  = systemd

[sshd]
enabled  = true
port     = 2222
logpath  = %(sshd_log)s
maxretry = 3
systemctl enable --now fail2ban
fail2ban-client status sshd

5. Password Policies and User Accounts

userdel games
userdel news
passwd -l root
apt install libpam-pwquality -y
# /etc/security/pwquality.conf
minlen = 14
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
dictcheck = 1
# /etc/login.defs
PASS_MAX_DAYS   90
PASS_MIN_DAYS   7
PASS_WARN_AGE   14

6. SELinux / AppArmor

SELinux (RHEL / Rocky Linux)

sestatus
setenforce 1
sed -i 's/SELINUX=permissive/SELINUX=enforcing/' /etc/selinux/config
ausearch -m avc -ts recent

AppArmor (Ubuntu / Debian)

apt install apparmor apparmor-utils -y
systemctl enable --now apparmor
aa-status
aa-enforce /etc/apparmor.d/usr.sbin.nginx

7. System Audit — auditd

apt install auditd audispd-plugins -y
systemctl enable --now auditd

Audit rules (/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 sudoers
-w /etc/ssh/sshd_config -p wa -k ssh_config
-a always,exit -F arch=b64 -S open -F exit=-EACCES -k access_denied

8. Kernel sysctl Parameters

# /etc/sysctl.d/99-hardening.conf
net.ipv4.ip_forward = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.log_martians = 1
fs.suid_dumpable = 0
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1
sysctl --system

Checklist — Quick Summary

#TaskPriority
1System update + auto-updatesCritical
2Disable root SSH loginCritical
3Key-only SSH authenticationCritical
4Change SSH portHigh
5Configure firewall (deny all + whitelist)Critical
6Install and configure Fail2BanHigh
7Password policies and expiryHigh
8SELinux/AppArmor in enforce modeHigh
9Enable auditd with rulesMedium
10sysctl parameters for network and kernelHigh

Summary

Hardening is not a one-time action — it’s a process. The steps above form a solid foundation for any production server. In upcoming articles we’ll show how to automate this process with Ansible and how to monitor the server for anomalies using Falco and Grafana Loki.