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
| # | Task | Priority |
|---|---|---|
| 1 | System update + auto-updates | Critical |
| 2 | Disable root SSH login | Critical |
| 3 | Key-only SSH authentication | Critical |
| 4 | Change SSH port | High |
| 5 | Configure firewall (deny all + whitelist) | Critical |
| 6 | Install and configure Fail2Ban | High |
| 7 | Password policies and expiry | High |
| 8 | SELinux/AppArmor in enforce mode | High |
| 9 | Enable auditd with rules | Medium |
| 10 | sysctl parameters for network and kernel | High |
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.