Linux Server Hardening: Essential Security Checklist
1. Introduction
Linux server hardening remains the task with the highest security return per hour invested, and yet it is the one most often left to improvisation. A freshly installed server connected to the public Internet receives brute-force login attempts within minutes, and most automated scans look for exactly what an unhardened server exposes: password-based SSH, open administration ports and unpatched packages. In this article I have prepared a complete Linux server hardening checklist that can be applied in order to any distribution (Debian, Ubuntu, RHEL or Rocky), with real sshd configuration, UFW firewall rules, fail2ban and SELinux, plus the verification commands that let you prove the outcome in an audit. When you finish, you leave a defensible server: patched, with minimal access, default-deny policy and auditable logging of what happens on it. The content assumes you already own the box and looks for verifiable results, as any serious Linux server hardening plan should.
2. Initial assessment and updates
Linux server hardening starts before touching a single service: you need to know what is installed, what is listening and which system version you run. The first checklist block is a quick inventory and a full package update, because every remaining control runs on a system that no longer has known vulnerabilities pending:
# Initial inventory: exposed services and operating system
ss -tulpn | column -t
cat /etc/os-release | head -3
uname -r
# Full update and packages with known vulnerabilities
sudo apt update && sudo apt full-upgrade -y
apt list --upgradable
sudo reboot
Fig. 1 – Inventory of exposed services and full system update, the starting point of Linux server hardening.
The ports shown by ss -tulpn are your real attack surface: everything listening on 0.0.0.0 is reachable from outside unless the firewall forbids it. The practical rule of Linux server hardening is simple: if a port is not in the service inventory, it must not be opened. For production updates, schedule monthly windows and enable automatic security patches in parallel; critical servers cannot wait thirty days for a manual cycle. The inventory is the first evidence any Linux server hardening audit will ask for.
One tool I recommend running before and after the checklist is Lynis, a Unix system security auditor that scores hardening and suggests concrete remediations with standard references. The first pass report becomes your baseline and the second one your improvement evidence. For formal compliance, the CIS Benchmarks profiles for your distribution are the standard most third-party audits require. A scientific comparison baseline turns Linux server hardening into a measurable process.
3. SSH service hardening
SSH is the most attacked component of any server and the first item on the checklist. Linux server hardening requires banning password access, disabling root login and limiting who can connect and from where. This /etc/ssh/sshd_config configuration is the one we deploy by default:
Port 2222
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
MaxSessions 4
PermitEmptyPasswords no
AllowUsers ops jaymon
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
Protocol 2
Fig. 2 – Hardening directives in /etc/ssh/sshd_config.
Changing the port to 2222 is not security by obscurity —it is detected within hours— but it removes most automated noise, so we keep it, always with the firewall closed in parallel. The critical verification before reloading the service is sudo sshd -t: if the output is empty, the syntax is valid. Then reload with sudo systemctl reload ssh, and most importantly: open a second session in parallel and confirm key-based access works from that same terminal before closing the current connection. A single mistake here locks the whole team out of the server. This parallel-test discipline is itself a key habit of Linux server hardening.
3.1 Key-based authentication with restrict
On that foundation, the next level of Linux server hardening is applying restrict to authorized keys so each operator can only do what they need: no agent or port forwarding, and a single assigned command. A line like this in ~/.ssh/authorized_keys turns the key into a role credential instead of a master key. Restricted keys shrink the blast radius of any leak, a constant goal of Linux server hardening. An example:
restrict,port-forwarding="none",command="/usr/local/bin/backup-run" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
Fig. 3 – SSH key with restrict options and a single assigned command.
4. Default-deny firewall with UFW
The second major checklist block is networking: explicit firewall policies, default denial and opening only the inventoried ports. On Ubuntu and Debian, UFW is the easiest iptables/nftables management layer to audit. Application sequence:
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp
sudo ufw allow 80,443/tcp
sudo ufw allow from 10.10.10.0/24 to any port 3306 proto tcp
sudo ufw enable
sudo ufw status verbose
Fig. 4 – UFW configuration with default-deny policy.
Look at the direction of the MySQL rule: it does not open the port to the whole Internet, only to the administration subnet. That is the difference between a decorative firewall and a real network policy in Linux server hardening. Rule order matters and UFW evaluates by priority, so review sudo ufw status numbered before considering the service configured. The final attack-surface check is repeating ss -tulpn and cross-referencing listening ports with those allowed in UFW: anything that does not match is a hole. With this sequence, the network layer of Linux server hardening is closed and verified.
5. Attack detection with fail2ban
A hardened server is still attacked; what it cannot afford is for those attacks to go unlogged and unmitigated. fail2ban watches authentication logs and blocks sources that fail repeatedly. The /etc/fail2ban/jail.local configuration we use combines temporary bans with permanent bans after persistence:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 3
ignoreip = 127.0.0.1/8 10.10.10.0/24
[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 4
bantime = 24h
Fig. 5 – fail2ban jail for SSH with a 24-hour ban after 4 attempts.
After reloading with sudo systemctl restart fail2ban, the operational verification is sudo fail2ban-client status sshd, which shows the number of banned IPs and the accumulated ban count. The ratios I observe in real environments are revealing: a server with standard SSH receives dozens of attempts per minute on the public Internet, and with the directives above almost one hundred percent of those connections are aborted before authentication. The fail2ban project includes jails for other services (Apache, Nginx, Postfix); add them to match your inventory, but the SSH jail is non-negotiable. Brute-force detection is the third line of Linux server hardening and the one that prevents dirty lockouts.
5.1 Monitoring the blocks
Linux server hardening does not end when the rule is active: you also have to consume those events. IPs that recur in fail2ban across several servers are candidates for blocking at the network level in the firewall or the edge router, and ban logs must reach your SIEM just like any other authentication event. That way an automated ban stops being noise and becomes intelligence about the adversary. Turning blocks into intelligence is the final maturity level of Linux server hardening.
6. SELinux and final administrative controls
The last checklist block raises the bar with mandatory access control. On RHEL, Rocky and AlmaLinux, SELinux is active by default but often in permissive mode: the system keeps behaving as before and logs what it would have enforced. Linux server hardening means fixing its state to enforcing, reviewing denials and fixing root causes instead of applying patches:
getenforce
sudo setsebool -P httpd_can_network_connect on
sudo semanage port -a -t ssh_port_t -p tcp 2222
ls -Z /etc/passwd
sudo ausearch -m AVC -ts recent | grep denied | head
Fig. 6 – Basic SELinux administration in enforcing mode.
Recommended workflow: first setenforce 1 to switch to enforcing live and confirm critical services still respond; then tune booleans and contexts with semanage and setsebool when a legitimate denial shows up in ausearch; finally, force permissive to enforcing in /etc/selinux/config so it survives reboot. If your distribution uses AppArmor (Ubuntu), the equivalent is checking active profiles with aa-status and enabling the missing ones for exposed processes. Mandatory access control is what separates advanced Linux server hardening from basic setup.
6.1 Final verification checklist
Close the walk with a complete pass, item by item, with the state each control must meet. This final pass is the moment Linux server hardening becomes documented procedure. The table below is the final verification checklist of our procedure:
| # | Control | Verification command | Correct state |
|---|---|---|---|
| 1 | Packages up to date | apt list –upgradable | No pending updates |
| 2 | SSH root login | grep PermitRootLogin /etc/ssh/sshd_config | no |
| 3 | SSH passwords | grep PasswordAuthentication /etc/ssh/sshd_config | no |
| 4 | Firewall active | sudo ufw status verbose | Status: active, deny incoming |
| 5 | Active bans | sudo fail2ban-client status sshd | Jail active and bans > 0 |
| 6 | SELinux/AppArmor | getenforce / aa-status | Enforcing / profiles active |
| 7 | Remote logging | rsyslog + forward to SIEM | Events in SIEM within 5 min |
Table 1 – Final verification checklist for Linux server hardening.
Beyond the seven points, three administrative controls that the table does not list but no serious checklist leaves out: keep backups out of band and tested, set a rotation policy for keys and credentials, and review users with access quarterly. Linux server hardening without a review process is a photo that ages; the quarterly checklist keeps it current.
7. Conclusion
Linux server hardening is a finite set of actions with an order and a verification step, and when executed completely it transforms a generic server into a defensive asset: minimal attack surface, key-only access with restrictions, default-deny firewall, automated brute-force detection and active mandatory access control. All of it measurable with the commands in the final table.
Order matters: update and assess, harden SSH, close the network with UFW, add fail2ban, and finish with SELinux and administrative controls. Then run Lynis again to quantify the improvement and keep both reports as evidence. When the next pentest or the next audit asks “what does this hardened server have?”, you will have not only the answer but the verification record to prove it. Repeat the cycle quarterly and your Linux server hardening becomes a program, not a one-off action.
Related articles: evidence removal after an intrusion and cybersecurity training and awareness resources.
Need help with Linux server hardening?
At Jaymon Security, we help organizations protect their systems. From security audits to SIEM/SOC implementation, our expert team designs custom solutions.
Contact us for a free infrastructure assessment.


