Most hardening guides are enormous and assume a security team. This is the short version: a checklist ordered by value per minute, for teams where the person securing the server also has other jobs.
It is deliberately only the list. Each group links to the matching part of the Linux server hardening guide, which gives every control in full: why it matters, the commands for Debian, Ubuntu, Rocky Linux and AlmaLinux, how to verify it, how to undo it, and how drift shows up afterwards. Use this page to keep track, and the guide when you need the detail.
Key Takeaways
- Order by value per minute. Patching, SSH keys, and default-deny inbound remove most of the realistic risk in under an hour.
- Every listening service is attack surface. If you cannot explain why it is there, that is the finding.
- Verify each item instead of assuming it. A firewall can be active and filter nothing; a setting can be overridden by a file you did not edit.
- An untested backup is a hope. Restore once before you need to.
- Hardening is point-in-time and servers drift. The ongoing part is the part that gets skipped, and it is the part that matters most over a year.
Table of Contents
- Before you start
- First 15 minutes
- First hour
- First day
- First week
- Ongoing, and this is the part that gets skipped
- What this list deliberately omits
Before you start
- Keep a second SSH session open for the whole job. A reload does not close existing sessions, so a mistake in the first window can be fixed from the second.
- Know how to reach the provider's web console or rescue mode, and confirm the login works today rather than during the incident.
- Take a snapshot if the provider offers one. It is the only rollback that covers everything at once.
First 15 minutes
The full controls, with commands per distribution: first 15 minutes.
- Install pending updates, and reboot if the system asks for it.
- Create a named administrator account with sudo. One per human; shared accounts destroy accountability.
- Confirm that key-based SSH login works for that account, in a new session, before you change anything about SSH.
- List what is listening, and explain every line.
sudo ss -tulpn
The thing to look for is the address a service is bound to. A database on 127.0.0.1 is fine; the same database on 0.0.0.0 is reachable from the internet, and that single distinction is behind a large share of real compromises. Redis, Elasticsearch, MongoDB, and Docker's API have all shipped in configurations that bind broadly, and each has been exploited at scale as a result.
- Turn on a firewall that denies inbound traffic by default, allowing SSH first so you do not lock yourself out.
- Check that the clock is synchronised. Logs with the wrong time are hard to use and easy to dispute.
First hour
The full controls: first hour.
- Turn off SSH password login and direct root login, then read the effective configuration with
sshd -Trather than trusting the file you edited. - Enable automatic security updates. Manual patching does not survive a busy month. Security-only is the sensible default; blanket automatic upgrades occasionally restart something at an inconvenient moment.
- Disable services you do not use, and remove packages you will never use.
- Move databases and caches off the public interface.
- Review who can use sudo, and look for
NOPASSWD: ALL. - Hide web server version banners and turn off directory listing.
- Check ownership and permissions on the account and SSH files, and save a list of setuid binaries while the server is known-good.
First day
The full controls: first day.
- Make the system journal persistent, and know where authentication events are written on your distribution. Log retention has to be long enough to investigate something you notice a month late.
- Send logs off the server as well as keeping them locally. Logs on the machine are only as trustworthy as the machine, and an attacker with root can edit them, which is precisely when you need them.
- Set up file integrity monitoring on
/etc, system binaries, and your web root. - Inventory installed packages and check them for known vulnerabilities.
- Configure off-server backups and test a restore. Restore into a scratch environment and confirm the data is usable. Also confirm the backup destination is not writable with credentials stored on the server being backed up, or ransomware takes both at once.
- Review the provider's firewall or security groups. It is a second layer that still works when the host firewall is misconfigured.
First week
The full controls: first week.
- Leave SELinux or AppArmor switched on, and fix the denial rather than disabling the system.
- Add brute-force protection for SSH: fail2ban or CrowdSec, and check that it is actually matching.
- Review user accounts and keys. Old contractor access is a classic finding.
- Document what normal looks like: expected processes, listeners, users, cron jobs. You cannot spot abnormal without this.
Capture it as a file rather than as knowledge in someone's head:
{
echo "== listeners"; ss -tulpn
echo "== processes"; ps -eo user,comm --sort=comm | uniq
echo "== suid"; find / -xdev -perm -4000 -type f 2>/dev/null
echo "== cron"; ls -la /etc/cron.d/ /etc/cron.*/
echo "== users"; awk -F: '$3 >= 1000 || $3 == 0 {print $1, $3}' /etc/passwd
} > ~/baseline-$(hostname)-$(date +%F).txt
Do this while the server is known-good, and store it off the machine. A baseline captured after a compromise records the intrusion as normal, which quietly defeats the point.
Ongoing, and this is the part that gets skipped
Hardening is a point-in-time action; servers drift. Packages update, someone opens a port for a demo, a config gets changed during an incident and never reverted.
- Patch on a schedule, and reboot when the kernel or a core library was updated.
- Review administrative access every quarter: accounts, keys, sudo.
- Re-run the verify step of each control, not the apply step. The question is whether the server still matches what you set.
- Restore a backup again. The one you tested in the first week proves nothing about this month.
What matters over time is noticing change: has a config file changed, is there a new listener, a new user, an unexpected outbound connection, a package with a newly published CVE.
Doing that manually across even a handful of servers does not survive a busy quarter. It has to be automated, and the automation has to be quiet enough that people keep paying attention to it.
That last clause is the whole difficulty. A monitoring system producing more findings than anyone reads has an effective true positive rate of zero regardless of how good its detections are, which is the constraint set out in why manual server monitoring fails at 3am.
That is the problem SecAI is built for: continuous monitoring of exactly these signals, with severity rules that keep the list of things needing a person short. See it alongside the rest of the detection stack. The category-level view is in the guide to Linux server security software.
What this list deliberately omits
Several things that appear on longer guides are left out here because the value per minute is poor for a small team.
Kernel hardening parameters. Worth doing once the items above are solid. As a first step for a team of three, a long list of sysctl changes consumes the attention the high-value items needed.
Intrusion detection tuning. Deploying a detection system you will not maintain produces a false sense of coverage. Better to have three controls that work than nine that have silently stopped.
Exhaustive CIS benchmark alignment. Useful when a framework requires it. As a starting point for a small team, it produces a long list of low-consequence changes.
The omission that matters most: nothing here defends against an application vulnerability. A hardened server running a vulnerable web application still gets compromised through it, and the attacker still leaves a webshell in your web root. Hardening the host is necessary and not sufficient.
Frequently Asked Questions
Is this checklist enough on its own? It removes most of the realistic risk for a small team, but it is point-in-time. Without something watching for drift afterwards, its value decays over the following months.
Where are the commands? In the Linux server hardening guide. Commands differ between Debian, Ubuntu, Rocky Linux and AlmaLinux, and each one needs a verify step and a way back, which does not fit in a checklist.
Should I enable automatic updates on production? Security-only updates, yes, on most servers. Blanket automatic upgrades of everything carries its own outage risk and is worth more care.
Do I need SELinux or AppArmor? If your distribution ships one enabled, leave it enabled; that costs nothing. Writing custom policy is valuable and expensive in time, so treat it as the next tier once the items above are solid.
What is the single highest-value change? Key-only SSH authentication. It removes brute force as a category rather than mitigating it.
How do I know if a listening service should be there? Trace it back to something you deliberately installed. If nobody can explain it, treat it as a finding and investigate before assuming it is benign, the sweep in how to tell if your Linux server has been compromised covers what to check.