Linux Security Hardening Commands Cheat Sheet: RHEL, SLES and Ubuntu
A Linux security baseline is not created by running a single hardening script. Enterprise security is achieved through a combination of secure configuration, least privilege, patch management, access control, monitoring, and continuous validation. This cheat sheet provides practical commands that Linux administrators can use while hardening enterprise servers running Red Hat Enterprise Linux (RHEL), SUSE Linux Enterprise Server (SLES), and Ubuntu Server.
The examples focus on common enterprise security tasks:
- System inventory
- User and privilege management
- SSH hardening
- Firewall configuration
- SELinux/AppArmor
- File permissions
- Service management
- Kernel hardening
- Auditing and logging
- Vulnerability checks
For the reasoning behind each control, see Linux Security Hardening: A Practical Enterprise Guide.
Identify Linux Distribution and Version
Before applying security changes, identify the operating system.
cat /etc/os-release
Example output:
NAME="Ubuntu"
VERSION="26.04 LTS"
| Information | Command |
|---|---|
| Kernel release | uname -r |
| System summary | hostnamectl |
| Architecture | uname -m |
System Inventory Commands
Running Services
systemctl list-units --type=service --state=running
systemctl --failed
systemctl list-unit-files --state=enabled
Listening Network Ports
Always identify exposed services.
ss -lntup
Example:
tcp LISTEN 0 128 0.0.0.0:22
tcp LISTEN 0 128 0.0.0.0:443
Identify which process owns a port:
sudo ss -lntup | grep :443
sudo lsof -i :443
Installed Packages
| Task | RHEL / SLES | Ubuntu |
|---|---|---|
| List all packages | rpm -qa | dpkg -l |
| Search package | rpm -qa | grep nginx | dpkg -l | grep nginx |
Patch Management
| Task | RHEL | SLES | Ubuntu |
|---|---|---|---|
| Refresh repositories | sudo dnf check-update | sudo zypper refresh | sudo apt update |
| Apply updates | sudo dnf update -y | sudo zypper update | sudo apt upgrade -y |
| Security updates | sudo dnf update --security | sudo zypper list-patches | sudo unattended-upgrade |
| Automation status | dnf-automatic | zypper-timer.service | systemctl status unattended-upgrades |
User Account Hardening
List Users
cat /etc/passwd
awk -F: '$7 !~ /(nologin|false)$/ {print $1,$7}' /etc/passwd
Check UID 0 Accounts
Only trusted accounts should have UID 0.
awk -F: '$3 == 0 {print $1}' /etc/passwd
Expected:
root
Create, Lock and Age Accounts
sudo useradd -m adminuser
sudo passwd adminuser
sudo usermod -L username
sudo usermod -U username
sudo chage -l username
sudo chage -M 90 username
Example output:
Maximum password age: 90 days
sudo Privilege Management
sudo visudo
visudo -c
sudo -l
Example group access:
%linux-admins ALL=(ALL) ALL
Create the admin group and add the user:
sudo groupadd linux-admins
sudo usermod -aG linux-admins adminuser
visudo -c before saving. A syntax error in /etc/sudoers locks out every administrator on the box.SSH Security Hardening
SSH configuration lives at /etc/ssh/sshd_config.
sudo cp /etc/ssh/sshd_config \
/etc/ssh/sshd_config.backup
sudo sshd -t
| Control | Setting |
|---|---|
| Disable root login | PermitRootLogin no |
| Key-only authentication | PasswordAuthentication no |
| Enable public keys | PubkeyAuthentication yes |
| Restrict to a group | AllowGroups linux-admins |
Restart SSH per distribution:
# RHEL / SLES
sudo systemctl restart sshd
# Ubuntu
sudo systemctl restart ssh
Generate and distribute keys, and secure the SSH directory:
ssh-keygen -t ed25519
ssh-copy-id user@server
chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
Firewall Hardening
Ubuntu UFW
sudo ufw status verbose
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 10.10.10.0/24 \
to any port 22
sudo ufw delete allow 443/tcp
sudo ufw enable
Allow your administration path before enabling the firewall, otherwise you risk locking yourself out.
RHEL / SLES firewalld
sudo firewall-cmd --state
sudo firewall-cmd --list-all
sudo firewall-cmd \
--permanent \
--add-service=https
sudo firewall-cmd \
--permanent \
--add-service=ssh
sudo firewall-cmd --reload
nftables
sudo nft list ruleset
systemctl status nftables
SELinux Hardening (RHEL)
getenforce
sestatus
ls -Z
ausearch -m AVC -ts recent
getsebool -a
setsebool -P httpd_can_network_connect on
Expected state on a production RHEL system:
Enforcing
Never disable SELinux as a troubleshooting shortcut.
AppArmor Hardening (Ubuntu/SLES)
sudo aa-status
sudo aa-status --profiles
sudo aa-enforce /etc/apparmor.d/profile
sudo aa-disable profile
File Permission Auditing
Check Sensitive Files
ls -l /etc/passwd
ls -l /etc/shadow
ls -l /etc/sudoers
Expected:
-rw-r----- 1 root root /etc/shadow
Find World Writable Files and Directories
sudo find / \
-xdev \
-type f \
-perm -0002
sudo find / \
-xdev \
-type d \
-perm -0002
Find SUID Files
SUID binaries execute with owner privileges. Review carefully:
sudo find / \
-perm /4000 \
-type f
Secure Temporary Directories
findmnt /tmp
findmnt /var/tmp
Possible hardening options:
nodev
nosuid
noexec
Example /etc/fstab entry:
tmpfs /tmp tmpfs defaults,nodev,nosuid 0 0
Test carefully before production deployment, and validate against the workload before adding noexec.
Kernel Security Parameters
sysctl -a
sysctl net.ipv4.ip_forward
sudo sysctl -w net.ipv4.ip_forward=0
Persistent configuration:
/etc/sysctl.conf
/etc/sysctl.d/
Apply:
sudo sysctl --system
net.ipv4.ip_forward=1. Never apply a copied sysctl.conf without confirming the server's role.Disable Unnecessary Services
systemctl list-unit-files
sudo systemctl disable --now service_name
sudo systemctl disable --now telnet.socket
Audit and Logging
journald
journalctl
journalctl --since "1 hour ago"
journalctl -u sshd
journalctl -f
auditd
systemctl status auditd
ausearch -m USER_LOGIN
ausearch -m USER_AUTH
Time Synchronisation
systemctl status chronyd
chronyc tracking
chronyc sources -v
DNS Security Checks
resolvectl status
getent hosts example.com
dig example.com
dig -x 192.168.10.10
File Integrity Monitoring
| Task | Command |
|---|---|
| Install AIDE (RHEL) | sudo dnf install aide |
| Install AIDE (Ubuntu) | sudo apt install aide |
| Initialise database | sudo aide --init |
| Check for changes | sudo aide --check |
Vulnerability Scanning
# Ubuntu
sudo apt install lynis
# Run audit
sudo lynis audit system
Review:
Warnings
Suggestions
Hardening index
Other enterprise tools:
OpenSCAP
Tenable Nessus
Qualys
Rapid7
Greenbone
Trivy
Backup Security Checks
systemctl list-timers
crontab -l
Test restore procedures. A backup that has never been restored is not a verified backup.
Container Host Hardening
docker ps
docker inspect container_id
Avoid --privileged and review:
Container images
Secrets
Capabilities
Network policies
Host mounts
Root containers
Enterprise Linux Security Baseline Checklist
| Security Area | Validation Command |
|---|---|
| OS Version | cat /etc/os-release |
| Kernel | uname -r |
| Updates | dnf/apt/zypper update |
| Services | systemctl list-units |
| Ports | ss -lntup |
| Users | cat /etc/passwd |
| UID 0 | awk -F: '$3==0' /etc/passwd |
| sudo | visudo -c |
| SSH | sshd -t |
| Firewall | ufw status verbose / firewall-cmd --list-all |
| SELinux | getenforce |
| AppArmor | aa-status |
| Permissions | find / -perm -0002 |
| Audit | ausearch -m USER_LOGIN |
| Logs | journalctl -u sshd |
| Time | chronyc tracking |
| DNS | dig example.com / getent hosts |
| Integrity | aide --check |
| Vulnerability | lynis audit system |
Final Thoughts
Linux security hardening is not about applying hundreds of commands blindly. A secure enterprise Linux server follows a few fundamental principles:
- Install only required software.
- Expose only required network services.
- Use individual accounts and least privilege.
- Protect privileged access.
- Keep mandatory access controls enabled.
- Monitor and audit important activity.
- Patch continuously.
- Validate security posture regularly.
The strongest Linux administrators are not the ones who know the most commands. They are the ones who understand why a security control exists, what risk it reduces, and how to operate it safely in production.