Linux server hardening checklist (2026)
A 14-step Ubuntu/Debian server hardening checklist: updates, SSH, firewall, fail2ban, auditd and backups, with commands to verify each control.
On this page
- 1. Turn on automatic security updates
- 2. Lock down SSH: keys only, no root login
- 3. Turn on a firewall (ufw or nftables)
- 4. Block brute-force attempts with fail2ban
- 5. Set up least-privilege users and sudo
- 6. Audit running services and open ports
- 7. Synchronise the clock
- 8. Turn on logging and auditd
- 9. Add file integrity monitoring
- 10. Configure backups before you need them
- 11. Enforce TLS everywhere
- 12. Keep secrets out of code and images
- 13. Apply sysctl network hardening
- 14. Add monitoring and alerting
- Linux server hardening checklist: control, why, how to verify
- What to do next
A Linux server hardening checklist turns "secure the server" into a short, ordered list of controls you can actually finish in an afternoon: patch automatically, lock down SSH, turn on a firewall, block brute-force attempts, limit who can do what, and log the changes that matter. Below is that checklist for Ubuntu and Debian servers, in the order we'd apply it on a fresh box, with the command to verify each one actually worked. It pairs with our wider guide to cloud servers, VPS and managed hosting — this post is the "what to do once the server exists" half.
Hardening reduces risk; it isn't a substitute for patching cadence, tested backups or someone watching for incidents. For the operational side of running a server long-term, see security and DevSecOps.
1. Turn on automatic security updates#
Most breaches exploit a known, already-patched vulnerability. unattended-upgrades is installed by default on Ubuntu Server and applies security updates on its own schedule.
sudo apt update && sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
sudo unattended-upgrade --dry-run -dCheck /etc/apt/apt.conf.d/50unattended-upgrades to confirm the -security line is uncommented, and /etc/apt/apt.conf.d/20auto-upgrades shows "1" for both settings.
2. Lock down SSH: keys only, no root login#
This is the single highest-value change on the list. Edit /etc/ssh/sshd_config:
# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers deploy adminKeep your current session open, test the syntax, then restart:
sudo sshd -t
sudo systemctl restart sshVerify by opening a new terminal and confirming a fresh connection still works before you close the old session. Moving SSH off port 22 is optional and only cuts scanner noise — it is not a substitute for the settings above.
3. Turn on a firewall (ufw or nftables)#
A default-deny inbound firewall stops everything you haven't explicitly allowed.
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verboseAllow SSH before enabling, or you will lock yourself out. On Ubuntu 20.10 and later, ufw's rules are enforced through an nftables backend, so avoid hand-writing separate nftables rules alongside it — Ubuntu's security documentation recommends picking one tool.
4. Block brute-force attempts with fail2ban#
fail2ban watches your logs and temporarily bans IPs after repeated failed logins.
sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local# /etc/fail2ban/jail.local
[sshd]
enabled = true
maxretry = 3
findtime = 10m
bantime = 1hsudo systemctl enable --now fail2ban
sudo fail2ban-client status sshdNever edit jail.conf directly — package updates overwrite it; jail.local is read on top of it.
5. Set up least-privilege users and sudo#
Nobody, including you, should work as root day to day.
sudo adduser deploy
sudo usermod -aG sudo deploy
sudo visudoVerify with sudo -l -U deploy to see exactly what a user can run, and lock accounts that leave the team with sudo passwd -l <user> rather than deleting them mid-investigation.
6. Audit running services and open ports#
Every running service is something you have to patch and something an attacker can try. Remove what you don't need.
systemctl list-units --type=service --state=running
sudo ss -tulpn
sudo apt remove --purge <unused-package>Re-run ss -tulpn after each change and confirm only the ports you expect (SSH, web, database if remote) are listening.
7. Synchronise the clock#
Accurate time matters for TLS certificate validation, log correlation across servers, and cron jobs firing when you expect. Ubuntu 24.04 LTS defaults to systemd-timesyncd; Ubuntu 25.10 and newer default to chrony, which handles patchy connectivity better and is worth installing on any server you rely on for accurate timestamps.
timedatectl status
sudo apt install chrony -y
chronyc trackingVerify timedatectl status reports System clock synchronised: yes.
8. Turn on logging and auditd#
Application logs show what your app did. auditd shows who touched the operating system: file edits, new users, privilege escalation.
sudo apt install auditd audispd-plugins -y
sudo systemctl enable --now auditd# /etc/audit/rules.d/hardening.rules
-w /etc/passwd -p wa -k identity
-w /etc/ssh/sshd_config -p wa -k sshd_configsudo augenrules --load
sudo ausearch -k sshd_config9. Add file integrity monitoring#
AIDE takes a snapshot of file hashes and permissions, then tells you what changed since.
sudo apt install aide aide-common -y
sudo aideinit
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
sudo aide --checkSchedule the check on a cron job and copy the baseline database somewhere off the server — a database an attacker can also edit isn't proof of anything.
10. Configure backups before you need them#
A hardened server that isn't backed up is still one disk failure or one mistake away from data loss. Set up automated, encrypted, off-server backups and — this is the part people skip — actually restore from one to prove it works. We cover the full method, including the 3-2-1 rule and a restore drill, in backups that actually restore.
11. Enforce TLS everywhere#
TLS 1.0 and 1.1 were formally deprecated by the IETF in RFC 8996; use TLS 1.2 as a floor and prefer 1.3.
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;Automate renewal with certbot (or your provider's ACME client) and verify it before you need it:
sudo certbot renew --dry-run12. Keep secrets out of code and images#
Database passwords, API keys and signing certificates should never sit in a Git repository or a container image layer.
chmod 600 .envUse environment variables injected at deploy time or a secrets manager, rotate anything a departing team member could have seen, and grep your Git history for accidental commits (git log -p | grep -i "api_key" as a rough first pass).
13. Apply sysctl network hardening#
A handful of kernel network parameters close off common attack classes with no application changes.
# /etc/sysctl.d/99-hardening.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.rp_filter = 1
kernel.randomize_va_space = 2sudo sysctl --system
sudo sysctl net.ipv4.tcp_syncookiesFull parameter definitions are in the kernel's own sysctl documentation — read what a setting does before you copy it onto a router or a host that genuinely needs forwarding.
14. Add monitoring and alerting#
Hardening tells you a server is configured safely today. Monitoring tells you when that stops being true — a service dies, disk fills up, or login attempts spike. A minimal stack (uptime checks, resource alerts, log-based alerting) is enough for most small teams; see monitoring vs observability for small teams for how to build one without alert fatigue.
Linux server hardening checklist: control, why, how to verify#
Control | Why it matters | How to verify |
|---|---|---|
Automatic updates | Closes known vulnerabilities without waiting on a human |
|
SSH keys only, no root login | Blocks the most common automated attack path | New session connects after restart; password login is refused |
Firewall (ufw/nftables) | Default-deny stops unplanned exposure |
|
fail2ban | Slows and blocks brute-force attempts |
|
Least-privilege users/sudo | Limits blast radius of a compromised account |
|
Service audit | Fewer running services, smaller attack surface |
|
Time sync | Correct logs, valid TLS checks, reliable cron |
|
Logging/auditd | Tells you who changed what on the OS |
|
File integrity (AIDE) | Detects unexpected file changes |
|
Backups | Recovery when everything else fails | A completed restore drill |
TLS everywhere | Encrypts data in transit, meets current standards |
|
Secrets management | Stops credential leaks via code or images |
|
sysctl hardening | Closes common network-level attack classes |
|
Monitoring/alerting | Tells you when a hardened server stops being healthy | An alert fires in a test |
What to do next#
Work through the checklist in order on any server you manage directly, and re-run the verification commands rather than trusting that a setting "should" be applied. If you'd rather have this done and kept up to date for you — including the monitoring, patching cadence and restore testing — see how we handle it on managed cloud servers, or view current plans and prices.
Frequently asked questions
Is ufw enough, or do I also need iptables or nftables?
For most single-server setups, ufw is enough. On Ubuntu 20.10 and later, ufw's rules are enforced through an nftables backend, so you already get nftables underneath. Write raw nftables rules only for logic ufw can't express, and avoid running both at once — Ubuntu's own security documentation warns against mixing them.
Should I move SSH off port 22?
It cuts down log noise from opportunistic scanners, but it is not a real security control by itself. Keys-only authentication, no root login and fail2ban do the actual work. Treat a custom port as an optional extra, never a replacement for those three.
How often should I redo this checklist?
Run through it on every new server, after any major OS upgrade, and at least once or twice a year as a review. Re-run the verification commands rather than trusting memory — configuration drifts as people and packages change.
Do I need auditd if my application already logs everything?
Yes. Application logs show what your app did; auditd shows who touched the operating system itself — edited a config file, added a user, escalated privileges. You need both to reconstruct an incident properly.
What's a fast way to check how hardened a server already is?
Lynis (open source, from CISOfy) is a good first pass: it scans the system and returns a hardening index with specific, numbered suggestions. Treat it as a starting checklist, not a certification — you still need to verify each fix yourself.
Sources
- Automatic updates — Ubuntu Server documentation — accessed 18 September 2026
- UFW — Ubuntu Community Help Wiki — accessed 18 September 2026
- nftables — Ubuntu security documentation — accessed 18 September 2026
- sshd_config(5) — OpenBSD manual pages — accessed 18 September 2026
- CIS Ubuntu Linux Benchmarks — Center for Internet Security — accessed 18 September 2026
- auditd(8) — Linux manual page — accessed 18 September 2026
- AIDE Manual — accessed 18 September 2026
- About time synchronisation — Ubuntu Server documentation — accessed 18 September 2026
- fail2ban — GitHub repository — accessed 18 September 2026
- RFC 8996: Deprecating TLS 1.0 and TLS 1.1 — accessed 18 September 2026
- IP Sysctl — The Linux Kernel documentation — accessed 18 September 2026
- Lynis — GitHub repository (CISOfy) — accessed 18 September 2026
Facts in this article were last checked on 18 September 2026.
Inventure Engineering Team
Engineers at Inventure Technologies who build, host and run software for clients in Nepal and Australia. We write about what we do every day.
Keep reading
Cloud servers explained: VPS, dedicated servers and managed hosting (2026 guide)
Cloud server vs VPS vs dedicated server vs managed hosting, explained in plain English, with a decision table and a glossary.
Read articleManaged vs unmanaged VPS: what's included, and the hidden cost of DIY
What a managed VPS includes, what you do yourself on an unmanaged one, and a simple way to work out which is cheaper for your team.
Read articleVPS vs dedicated server vs cloud hosting: which does your business need?
An honest comparison of VPS, dedicated servers and cloud hosting, with a "not ideal for" case for each and a simple decision flow.
Read articleWant engineers who handle this for you?
We build, host and run software for teams in Nepal and Australia — with dedicated support on every plan.