Linux Server Hardening Checklist for 2026 (Ubuntu/Debian/RHEL)

Published on March 9, 2026

A fresh Linux server is not a hardened Linux server. Whether you are spinning up a VPS, provisioning bare metal, or deploying a cloud instance, a consistent hardening pass before the box sees production traffic is non-negotiable. This checklist covers the essentials for Ubuntu/Debian and RHEL/AlmaLinux/Rocky systems in 2026.

1. SSH hardening

SSH is typically the only remote access vector on a new server, so lock it down first. Edit /etc/ssh/sshd_config (or drop a file in /etc/ssh/sshd_config.d/):

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
KbdInteractiveAuthentication no
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 20
AllowUsers deployer admin

Restart the daemon after changes:

sudo systemctl restart sshd

Use Ed25519 keys. If you still have RSA keys, ensure they are at least 4096 bits. Generate a new key pair:

ssh-keygen -t ed25519 -C "yourname@host"

Consider moving SSH to a non-standard port to reduce noise in logs. This is not security, but it cuts automated scan traffic significantly.

Ref: man sshd_config, man ssh-keygen

2. Firewall defaults

Default-deny inbound. Allow only what you need. On Ubuntu/Debian, ufw is the simplest front-end:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw enable
sudo ufw status verbose

On RHEL/AlmaLinux/Rocky, use firewalld:

sudo firewall-cmd --set-default-zone=drop
sudo firewall-cmd --zone=drop --add-service=ssh --permanent
sudo firewall-cmd --zone=drop --add-service=https --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

If you use raw nftables, define your ruleset in /etc/nftables.conf and enable nftables.service. Avoid mixing front-ends with direct nftables rules.

Ref: man ufw, man firewall-cmd, man nft

3. Unattended security updates

Patch delay is one of the most common root causes of compromise. Automate security patches at minimum.

Ubuntu/Debian — install and configure unattended-upgrades:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Verify the config in /etc/apt/apt.conf.d/50unattended-upgrades. Ensure "${distro_id}:${distro_codename}-security" is enabled. Optionally enable automatic reboot for kernel patches:

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

RHEL/AlmaLinux/Rocky — use dnf-automatic:

sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic-install.timer

Edit /etc/dnf/automatic.conf and set upgrade_type = security to restrict to security patches only.

Ref: man unattended-upgrades, man dnf-automatic

4. Brute-force protection: fail2ban and CrowdSec

Even with key-only SSH, brute-force attempts pollute logs and waste resources. Two solid options:

fail2ban is the established choice. It watches log files and bans IPs after repeated failures:

# Ubuntu/Debian
sudo apt install fail2ban

# RHEL (EPEL required)
sudo dnf install epel-release
sudo dnf install fail2ban

Create /etc/fail2ban/jail.local to override defaults without touching the package file:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 3

[sshd]
enabled = true
port    = ssh
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

CrowdSec is the newer, community-driven alternative. It parses logs like fail2ban but shares threat intelligence across its network, giving you blocklists crowdsourced from other nodes:

# Install CrowdSec (all distros)
curl -s https://install.crowdsec.net | sudo bash
sudo apt install crowdsec crowdsec-firewall-bouncer-iptables   # Debian/Ubuntu
sudo dnf install crowdsec crowdsec-firewall-bouncer-iptables   # RHEL

CrowdSec detects attacks via "scenarios" and blocks via "bouncers." The firewall bouncer plugs into iptables/nftables. Check decisions with:

sudo cscli decisions list

Choose one or the other; running both on the same logs is redundant.

Ref: man fail2ban, man jail.conf, CrowdSec docs at docs.crowdsec.net

5. Audit and logging

Without logs, you cannot investigate incidents. Configure the audit subsystem and centralize logs.

auditd — install and enable:

# Ubuntu/Debian
sudo apt install auditd

# RHEL (usually pre-installed)
sudo dnf install audit
sudo systemctl enable --now auditd

Add rules to watch sensitive files. Append to /etc/audit/rules.d/hardening.rules:

# Watch for changes to user/group databases
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers

# Watch SSH config
-w /etc/ssh/sshd_config -p wa -k sshd_config

# Log all commands run as root
-a always,exit -F arch=b64 -F euid=0 -S execve -k root_commands

Load the rules:

sudo augenrules --load

Search audit logs:

sudo ausearch -k identity --interpret

journald — ensure persistent storage is enabled. Check that /etc/systemd/journald.conf has:

Storage=persistent
SystemMaxUse=500M

Forward logs to a remote syslog collector (rsyslog, Loki, or a SIEM) so that an attacker who gains root cannot erase evidence from the local box.

Ref: man auditd, man audit.rules, man ausearch, man journald.conf

6. User and privilege management

Minimize attack surface from user accounts:

  • Remove or lock unnecessary user accounts: sudo usermod -L -s /usr/sbin/nologin olduser
  • Limit sudo access. Avoid ALL=(ALL) NOPASSWD: ALL. Grant specific commands per role.
  • Use visudo to edit sudoers safely. Drop role files in /etc/sudoers.d/.
  • Set password policy with PAM. On RHEL, authselect manages PAM profiles cleanly.
  • Enforce password aging: sudo chage -M 90 -W 14 username

Audit which users have sudo access:

grep -r 'NOPASSWD\|ALL' /etc/sudoers /etc/sudoers.d/

Ref: man sudoers, man chage, man authselect

7. Kernel and network parameters

Harden the network stack via /etc/sysctl.d/99-hardening.conf:

# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

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

# Enable SYN flood protection
net.ipv4.tcp_syncookies = 1

# Ignore source-routed packets
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

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

# Disable IP forwarding (unless this is a router/VPN gateway)
net.ipv4.ip_forward = 0

# Restrict kernel pointer exposure
kernel.kptr_restrict = 2

# Restrict dmesg access
kernel.dmesg_restrict = 1
sudo sysctl --system

Ref: man sysctl.conf, kernel docs at Documentation/networking/ip-sysctl.rst

8. Service minimization

Every running service is attack surface. List enabled services and disable what you do not need:

systemctl list-unit-files --type=service --state=enabled
sudo systemctl disable --now cups avahi-daemon rpcbind

Check listening ports and verify you recognise every one:

sudo ss -tlnp

Remove packages you do not need. On RHEL minimal installs this is less of an issue, but Ubuntu server can ship with extras.

9. File integrity and rootkit detection

Detect unauthorized file changes before they become incidents:

# AIDE (Advanced Intrusion Detection Environment)
sudo apt install aide        # Debian/Ubuntu
sudo dnf install aide        # RHEL

sudo aideinit                # Debian/Ubuntu: initialize database
sudo aide --init             # RHEL: initialize database

# Run a check
sudo aide --check

Schedule a daily check via cron or a systemd timer. Store the baseline database offline or on a separate system.

For rootkit scanning, rkhunter and chkrootkit remain useful as a quick sanity check:

sudo apt install rkhunter     # or sudo dnf install rkhunter
sudo rkhunter --update
sudo rkhunter --check --skip-keypress

Ref: man aide, man rkhunter

10. Backup validation

Backups you have never restored are not backups. They are hopes.

  • Test restores regularly. Schedule a quarterly restore drill to a scratch VM.
  • Verify integrity. Use checksums or cryptographic signatures on backup archives.
  • Follow the 3-2-1 rule: 3 copies, 2 different media types, 1 offsite.
  • Encrypt backups at rest. A stolen backup is a data breach.

A minimal verification script using restic (works on all distros):

# Check repository integrity
restic -r /path/to/repo check

# List snapshots
restic -r /path/to/repo snapshots

# Test restore of a specific path
restic -r /path/to/repo restore latest --target /tmp/restore-test --include /etc

Whatever tool you use (restic, borg, rsnapshot, Veeam), the principle is the same: automate the backup, but also automate the verification.

11. Patch cadence

Automated security updates (section 3) handle the urgent patches, but you still need a scheduled cadence for all updates:

  • Weekly: review pending updates, apply in staging.
  • Bi-weekly or monthly: apply tested updates to production with a maintenance window.
  • Immediately: critical CVEs with active exploitation. Subscribe to your distro's security mailing list.

Check for available updates:

# Ubuntu/Debian
apt list --upgradable

# RHEL
dnf check-update --security

On Ubuntu, ubuntu-advantage (now pro) provides Livepatch for kernel updates without reboot. RHEL offers kpatch. Both are worth evaluating for uptime-critical systems.

Security mailing lists:

  • Ubuntu: ubuntu-security-announce
  • Debian: debian-security-announce
  • RHEL: rhsa-announce via Red Hat mailing lists

Quick reference checklist

[ ] SSH: key-only auth, root login disabled, MaxAuthTries 3
[ ] Firewall: default-deny inbound, only required ports open
[ ] Auto-updates: unattended-upgrades or dnf-automatic for security patches
[ ] Brute-force: fail2ban or CrowdSec active on SSH (and web if applicable)
[ ] Audit: auditd rules for /etc/passwd, /etc/shadow, sudoers, sshd_config
[ ] Logging: journald persistent, logs forwarded to remote collector
[ ] Users: no unnecessary accounts, sudo scoped to specific commands
[ ] Kernel: sysctl hardening applied, IP forwarding off
[ ] Services: unused daemons disabled, listening ports reviewed
[ ] Integrity: AIDE or similar baselined, rootkit scanner scheduled
[ ] Backups: 3-2-1 rule, restore tested, encrypted at rest
[ ] Patches: cadence defined, security mailing lists subscribed

No checklist replaces understanding your threat model, but if you walk through these items on every new server, you are ahead of the majority. Revisit quarterly and after any major change.