A Linux server exposed to the Internet starts receiving automated intrusion attempts within minutes of its IP going live. Bots guessing SSH passwords, scanners probing for vulnerable services, exploits against unpatched software. Hardening — the process of reducing a system's attack surface — is not an optional task for production environments: it is the difference between a server that shrugs off that constant background noise and one that ends up in a botnet.
The good news is that Linux hardening is extremely well documented, and most of the measures are low cost and high impact. The bad news is that the default configuration of nearly every distribution favours convenience over security, so the work has to be done deliberately. If you are still deciding which base to build on, our overview of the most used Linux distributions for servers will help you choose.
In this article we walk through a complete checklist organised by area, with the concrete measures for each one and a summary table with priorities so you can audit your servers today.
SSH: The Front Door Everyone Attacks
SSH is the number-one target of automated attacks, so it is the first service to harden. The essential measures in /etc/ssh/sshd_config:
- check_circle Key-based authentication, not passwords: generate a key pair (ed25519 is the current recommended choice), deploy the public key on the server and set PasswordAuthentication no. Brute-force attacks become pointless.
- check_circle Disable root login: with PermitRootLogin no you force everyone to log in with a named user and escalate via sudo, which keeps a trail of who did what.
- check_circle Restrict who can connect: the AllowUsers (or AllowGroups) directive limits SSH to the users who genuinely need it. Everyone else is rejected even with valid credentials.
- check_circle fail2ban: automatically bans IPs that pile up failed attempts, cutting off dictionary attacks and reducing load and noise in your logs.
About changing the SSH port:
Moving SSH off port 22 reduces the noise of mass scanning and keeps logs cleaner, but it is not a security measure: any targeted scanner finds it in seconds. Treat it as operational hygiene, never as a substitute for keys, fail2ban or MFA.
Users, Privileges and Automatic Updates
Identity management is the second layer. The guiding principle is least privilege: every user and every process should have exactly the permissions it needs, and none beyond that. It is the same principle behind the modern security architectures we cover in our practical guide to Zero Trust.
- check_circle Least-privilege sudo: avoid handing out the blanket ALL=(ALL) ALL. Define in sudoers which specific commands each role can run, and review those rules regularly.
- check_circle Strong passwords: even with key-based SSH, local passwords still guard sudo and the console. Enforce minimum length and complexity with pam_pwquality and expire accounts where required.
- check_circle Remove unused accounts: users of employees who have left, service accounts of uninstalled software or test users are backdoors waiting to be used. Inventory /etc/passwd and lock or delete anything that is left over.
As for patching, the vast majority of intrusions exploit known vulnerabilities with a patch already available. Automate it: unattended-upgrades on Debian/Ubuntu and dnf-automatic on RHEL/AlmaLinux/Rocky apply security updates without human intervention. Also define a reboot strategy: kernel and glibc patches do not take effect until a restart, so schedule regular maintenance windows or use live patching on systems that cannot stop.
Firewall and Services: Expose Only What Is Essential
The golden rule of the firewall is deny by default: everything closed except what explicitly needs to be open. The tool matters less than the policy — nftables directly, ufw on Ubuntu/Debian or firewalld on the RHEL family — what counts is: inbound denied by default, selective opening of service ports (80/443 for web, the SSH port restricted by source where possible) and logging of dropped traffic to spot attack patterns.
The natural companion to the firewall is reducing the services that run. Every active daemon is attack surface: review with systemctl list-unit-files --state=enabled and ss -tulpn what is running and listening, and disable what you do not use: printing, avahi, bluetooth or databases pulled in as dependencies that nobody queries.
For the services that must run, systemd offers per-unit hardening with very little effort: directives such as ProtectSystem=strict, PrivateTmp=yes, NoNewPrivileges=yes or ProtectHome=yes confine each process to what it needs. The systemd-analyze security command scores the exposure of every unit and tells you where to start.
Kernel, sysctl and Mandatory Access Control
The kernel's network behaviour is tuned via sysctl (files under /etc/sysctl.d/). Three classic settings that should be on every server:
- check_circle Disable ICMP redirects (accept_redirects and send_redirects set to 0): prevents an attacker on the network from manipulating the server's routes to intercept traffic.
- check_circle rp_filter = 1 (reverse path validation): drops packets with a spoofed source IP, the first line of defence against spoofing.
- check_circle SYN cookies enabled (tcp_syncookies = 1): keep the service available during SYN flood attacks without exhausting the connection table.
The second piece is mandatory access control (MAC): SELinux on RHEL, AlmaLinux, Rocky and Fedora, and AppArmor on Ubuntu, Debian and SUSE. Both confine what each process can touch even if it has been compromised: a web service under a MAC policy cannot read /etc/shadow or spawn a reverse shell even if the attacker manages to execute code. The rule is simple: enforcing mode, always. Disabling it "because it causes problems" is like removing your seatbelt because it is uncomfortable; the right fix is to adjust the policy for that specific service.
Auditing, Logs, File Permissions and MFA
If you do not record what happens, you can neither detect an intrusion nor investigate it afterwards. Three baseline measures:
- check_circle auditd: records kernel-level events — access to sensitive files, changes to sudoers, privileged calls — with rules aligned to the CIS Benchmarks.
- check_circle Persistent journald: with Storage=persistent logs survive reboots; on many default installations they are lost at shutdown.
- check_circle Shipping to remote syslog or a SIEM: an attacker with root wipes the local logs. Streaming them in real time to an external collector guarantees the evidence survives the compromise.
On the filesystem, review the permissions of sensitive files (/etc/shadow, private keys, configurations containing credentials), hunt for unnecessary SUID binaries and set a restrictive umask (027 or 077) so new files are not born world-readable. On partitions, mount /tmp, /var/tmp and /dev/shm with noexec and nodev where applicable: many exploits download their payload into temporary directories and fail if they cannot execute it from there.
Finally, MFA: add a second factor (TOTP with google-authenticator via PAM, or native FIDO2 keys in OpenSSH) to SSH access and to any administrative panel. If a private key leaks from a stolen laptop, the second factor still keeps the door shut.
Summary Table: Hardening Checklist by Priority
This table condenses the full checklist. Start with the critical measures and work your way down:
| Area | Measure | Priority |
|---|---|---|
| SSH | Keys instead of passwords, PermitRootLogin no, AllowUsers, fail2ban | Critical |
| Updates | unattended-upgrades / dnf-automatic + reboot strategy | Critical |
| Firewall | nftables/ufw/firewalld with default deny, only required ports open | Critical |
| Users | Least-privilege sudo, strong passwords, remove unused accounts | High |
| Services | Disable unused daemons, systemd unit hardening | High |
| MAC | SELinux/AppArmor in enforcing mode | High |
| MFA | Second factor for SSH and administrative access | High |
| Auditing | auditd, persistent journald, shipping to remote syslog/SIEM | High |
| Kernel/sysctl | Disable ICMP redirects, rp_filter, SYN cookies | Medium |
| Files | Permissions, restrictive umask, partitions with noexec/nodev | Medium |
How to Audit It: CIS Benchmarks and Lynis
There is no need to invent the standard: the CIS Benchmarks publish secure configuration guides for every distribution (Ubuntu, Debian, RHEL, AlmaLinux…), with hundreds of verifiable controls organised in levels. They are the reference used by auditors and compliance frameworks such as ISO 27001 or Spain's ENS.
For day-to-day work, Lynis is the most practical tool: an open-source audit script that analyses the system in minutes, scores its hardening level (hardening index) and produces a prioritised list of recommendations. Running it quarterly — and after every significant change — turns hardening into a measurable process instead of an act of faith.
All of this takes time and discipline, which is why on EasyDataHost managed servers these tasks are included as a service: initial CIS-aligned hardening, automatic patching with agreed reboot windows, monitoring, log management and periodic audits. And if you want an additional layer of perimeter protection — managed firewall, DDoS filtering, VPN — our security page details every option available on our infrastructure in Spain.
Frequently Asked Questions
Does changing the SSH port improve server security?
It reduces the noise from automated scans and keeps logs cleaner, but it is not a real security measure: any port scanner finds it in seconds. Effective protection comes from key-based authentication, disabling root login, fail2ban and MFA.
Should I use SELinux or AppArmor?
Use whichever your distribution ships with: SELinux on RHEL, AlmaLinux, Rocky Linux and Fedora; AppArmor on Ubuntu, Debian and SUSE. What matters is not which one you choose, but that it runs in enforcing mode: a MAC system in permissive mode or disabled protects nothing.
How often should hardening be audited?
At least a quarterly audit with Lynis or the CIS Benchmarks, and always after significant changes: new services, OS version upgrades or architecture changes. Security patches, on the other hand, should be applied continuously and automatically.
Conclusion
Hardening is not a project you close: it is a state you maintain. But most of the risk is eliminated with a set of well-known, automatable measures:
- arrow_right SSH with keys, no root login and fail2ban, plus MFA for administrative access: the front door, locked down.
- arrow_right Automatic patching and a default-deny firewall: the two measures with the best effort-to-impact ratio on the whole list.
- arrow_right Least privilege everywhere: scoped sudo, disabled services, hardened systemd units and SELinux/AppArmor in enforcing mode.
- arrow_right Continuous auditing: persistent and remote logs, auditd, and periodic verification with the CIS Benchmarks and Lynis so hardening stays measurable.
If you would rather have a specialised team do this work, at EasyDataHost it comes included with our managed servers. Contact our team and we will prepare a proposal with no obligation.