Hardening a Linux system
A freshly installed system is a starting point, not a secure end state. Hardening reduces the attack surface and limits the damage if something is compromised.
Principles
Hardening follows a few principles: run only what is needed (minimise the attack surface), give every user and service the least privilege necessary, keep software patched, use defence in depth so one failure is not catastrophic, and log enough to detect problems. Security baselines such as the CIS Benchmarks give detailed checklists for common distributions.
Patching
Most successful attacks exploit known vulnerabilities for which patches already exist. Apply security updates promptly, automatically where appropriate with unattended-upgrades on Debian and Ubuntu or dnf-automatic on Fedora and RHEL. Kernel updates need a reboot, or live patching services, to take effect; needrestart or dnf needs-restarting shows which services still use old libraries.
Reducing services
Every running network service is a possible entry point. ss -tulpn lists listening TCP and UDP sockets with their processes. Disable and remove anything unnecessary with systemctl disable --now and the package manager. Services that only need local access should listen on 127.0.0.1 rather than all interfaces.
Host firewalls
Linux packet filtering is built into the kernel's netfilter framework, configured today with nftables (the successor to iptables). Friendlier front ends include ufw on Ubuntu (ufw allow 22/tcp; ufw enable) and firewalld on Fedora and RHEL (firewall-cmd --add-service=https --permanent). A typical server policy denies inbound traffic by default and allows only required ports.
Account and authentication security
Lock or remove unused accounts, require strong passwords or, better, SSH keys, disable direct root login over SSH, and use sudo with logging. Tools such as fail2ban watch logs and temporarily ban addresses that repeatedly fail to log in. Multi-factor authentication through PAM protects especially sensitive systems.
Confinement and integrity
Run services as dedicated unprivileged users, keep SELinux or AppArmor enforcing, and use systemd sandboxing options such as ProtectSystem=strict, ProtectHome=yes, PrivateTmp=yes, NoNewPrivileges=yes, and CapabilityBoundingSet=; systemd-analyze security service rates a unit's exposure. File-integrity tools such as AIDE detect unexpected changes to system files, and Secure Boot protects the boot chain.
Encryption and secrets
Encrypt disks, especially on laptops, with LUKS, so a stolen device does not expose data. Use TLS for network services. Store secrets such as database passwords in protected files with tight permissions (600), environment files loaded by systemd, or dedicated secret managers, never in world-readable files or version control. Back up regularly and test restores, keeping some backups offline as protection against ransomware.
Worked example
Hardening a new web server: apply updates and enable unattended security upgrades; ss -tulpn reveals an unused FTP server, which is removed; ufw default deny incoming, ufw allow OpenSSH, ufw allow 443/tcp, ufw enable; SSH is set to keys only with root login disabled; fail2ban protects SSH; the web app runs as user www-app with ProtectSystem=strict and NoNewPrivileges=yes; and systemd-analyze security confirms a much lower exposure score.
Key takeaways
Hardening minimises attack surface, applies least privilege and defence in depth, and keeps logs; CIS Benchmarks provide checklists. Patch promptly, automate security updates, and restart services or reboot for kernel fixes. ss -tulpn finds listening services; remove what is unneeded and bind local services to 127.0.0.1. nftables, ufw, and firewalld implement default-deny host firewalls. Secure accounts with keys, no root SSH, sudo, fail2ban, and MFA. Confine services with dedicated users, SELinux or AppArmor, and systemd sandboxing; AIDE and Secure Boot protect integrity. Encrypt disks with LUKS, protect secrets, and test offline backups.
Flashcard
Everything an attacker could target
Check your understanding
A database used only by an application on the same server is listening on 0.0.0.0:5432. What is the simplest hardening step?
