Server Hardening Guide
Server Hardening Guide
Section titled “Server Hardening Guide”Hardening reduces a server’s attack surface. The highest-impact controls are few and well-known; most breaches exploit the basics (exposed services, weak SSH, unpatched software), not exotic flaws. This guide is opinionated about what matters most for typical self-hosted boxes, using CIS benchmarks as a framework rather than gospel.
This expands on the checklist in the Server Guides index into an actionable, ordered guide.
Frame it with CIS benchmarks
Section titled “Frame it with CIS benchmarks”The CIS Benchmarks are consensus hardening
baselines per OS, with Level 1 (sensible, low-friction) and Level 2 (stricter,
higher-impact) profiles. Scan with CIS-CAT or OpenSCAP to measure against them — but
treat them as a guide, not a mandate; some controls are compliance theater for a
single-purpose host. Start at Level 1 and adopt Level 2 controls that fit your threat
model (see Threat Modeling).
SSH is the front door — lock it first:
PermitRootLogin noPasswordAuthentication no # key-only authKbdInteractiveAuthentication noAllowGroups ssh-users # only members of this group may log inClientAliveInterval 300ClientAliveCountMax 2Use SSH keys (ideally hardware-backed), disable password and root login, and restrict who
can log in. Changing the port cuts log noise but is obscurity, not security — don’t rely
on it. sshd -t before reloading, and keep a second session open so a typo can’t lock
you out.
Firewall: default deny
Section titled “Firewall: default deny”Allow only what you serve. With UFW:
sudo ufw default deny incomingsudo ufw default allow outgoingsudo ufw allow 22/tcp # SSH (allow BEFORE enabling, or you lock yourself out)sudo ufw allow 443/tcpsudo ufw enablenftables is the modern lower-level alternative when you need finer control. Don’t forget
IPv6 rules.
fail2ban
Section titled “fail2ban”fail2ban bans IPs after repeated auth failures, blunting brute-force and credential-stuffing:
[sshd]enabled = truemaxretry = 4bantime = 1hignoreip = 127.0.0.1/8 10.0.0.0/24 # never ban yourselfKernel hardening (sysctl)
Section titled “Kernel hardening (sysctl)”Tighten network and kernel behavior:
net.ipv4.tcp_syncookies = 1net.ipv4.conf.all.accept_redirects = 0net.ipv4.conf.all.accept_source_route = 0net.ipv4.conf.all.rp_filter = 1kernel.kptr_restrict = 2fs.protected_hardlinks = 1fs.protected_symlinks = 1Apply with sudo sysctl --system.
Automatic security updates
Section titled “Automatic security updates”Unpatched software is the most common entry point. Automate security updates:
# Debian/Ubuntusudo apt install -y unattended-upgradessudo dpkg-reconfigure -plow unattended-upgrades# RHEL/Fedora: dnf-automaticAuto-apply security patches; review feature/major upgrades manually. Pair with CVE awareness — see Tracking CVEs and Vulnerabilities.
Mandatory access control
Section titled “Mandatory access control”Keep AppArmor (Debian/Ubuntu) or SELinux (RHEL/Fedora) in enforcing mode — they confine a compromised service to what it’s allowed to touch. Don’t disable them to make an app “work”; write/adjust a profile instead.
Audit logging
Section titled “Audit logging”auditd records security-relevant events (privileged commands, auth, file changes) for
detection and forensics:
sudo apt install -y auditdsudo auditctl -w /etc/passwd -p wa -k identity # watch a sensitive filesudo ausearch -k identity # query the eventsForward logs off-box so an attacker can’t erase them, and feed them into detection — see
Blue Team Tools. Periodic rootkit scans (rkhunter,
chkrootkit) add a backstop, with the caveat that they detect known rootkits only.
Related
Section titled “Related”- Linux Server Initial Setup — the baseline this builds on
- PostgreSQL Server Guide — hardening a specific service
- Reverse Proxy with nginx — TLS and security headers at the edge
- Tracking CVEs and Vulnerabilities — staying ahead of what to patch