Security basics & server hardening
Updates, least privilege, SSH hardening, firewalls, fail2ban, auditing and a hardening checklist.
The moment a server gets a public IP address, bots start probing it: within minutes you'll see SSH login attempts in the logs. Security is not one product you install; it's a set of habits applied in layers (defence in depth), so that a single mistake doesn't become a breach. This final lesson brings together everything from the course into a practical hardening checklist for Ubuntu/Debian servers, with Fedora/RHEL equivalents.
The principles#
- Least privilege. Users, services and keys get only the access they need, and nothing runs as root that doesn't have to.
- Minimise the attack surface. Fewer installed packages, fewer listening ports, fewer accounts.
- Defence in depth. Firewall and SSH keys and updates and monitoring, so that one failure isn't fatal.
- Visibility. If you can't see logins, changes and failures, you can't respond to them.
- Assume you'll need to rebuild. Backups and documented, automated setup turn a disaster into an inconvenience.
1. Keep the system updated#
Most real-world compromises exploit known vulnerabilities that already have patches.
On Fedora/RHEL, install dnf-automatic (or dnf5-plugin-automatic on Fedora 41+), set apply_updates = yes in /etc/dnf/automatic.conf, and run sudo systemctl enable --now dnf-automatic.timer.
Kernel updates only take effect after a reboot. Schedule regular maintenance windows, or use live patching (Ubuntu Pro Livepatch, kpatch on RHEL).
2. Users and sudo#
- Create a personal account for each admin, with
sudorights (usermod -aG sudo adaon Ubuntu, thewheelgroup on Fedora/RHEL). Never share accounts. - Disable direct root login; use
sudo, which logs who did what. - Remove or lock accounts that are no longer needed:
sudo usermod -L olduserandsudo usermod -s /usr/sbin/nologin olduser, orsudo userdel -r olduser. - Give service accounts no shell and no password:
useradd --system --shell /usr/sbin/nologin myapp. - Review who has power:
This output is from a test machine. The sudo group has no members because sudo access is granted by a file in /etc/sudoers.d/ instead, so always check both places. The UID-0 check lists only root, which is what you want: any other account with UID 0 is a full root account and a classic sign of compromise.
3. Harden SSH#
SSH is the front door, so lock it properly. First make sure key login works (see the SSH lesson). Then create a drop-in config:
Keep your current session open and test a new login from a second terminal before you close it. Changing the port (Port 2222) reduces log noise from bots but isn't real security; keys and no passwords are.
💡 On cloud images, check whether a file in
/etc/ssh/sshd_config.d/(e.g.50-cloud-init.conf) already setsPasswordAuthentication yes. The first value read wins in sshd, which is why the hardening file uses a low number such as10-. Confirm the effective settings withsudo sshd -T | grep -E 'passwordauth|permitroot'.
4. Firewall: deny by default#
From the firewall lesson:
Then compare what's listening with what's allowed:
Anything listening on 0.0.0.0 that shouldn't be public should either be bound to 127.0.0.1 in its config, or blocked. Databases, caches and admin panels should never face the internet.
5. fail2ban: ban brute-force attackers#
Configure it in a .local file (never edit jail.conf, which upgrades overwrite):
Put your own static IP in ignoreip so you can't ban yourself.
6. Minimise what's installed and running#
Every service you remove is one you never have to patch or secure.
7. File permissions and secrets#
- Keep secrets (
.env, API keys, DB passwords) at600or640, owned by the service user, and out of Git. - Look for world-writable files and unexpected setuid binaries:
- Mount options can help:
/tmpwithnodev,nosuid,noexecblocks some attack techniques. - On a fresh install, check the home directories aren't readable by everyone:
ls -ld /home/*(Ubuntu 21.04+ creates them as750).
8. Mandatory access control: AppArmor and SELinux#
These kernel security modules confine programs even if they're running as root:
- AppArmor (Ubuntu, Debian, openSUSE) uses per-program profiles:
sudo aa-status. - SELinux (Fedora, RHEL, Rocky, Alma) uses labels on every file and process:
getenforceshould printEnforcing.
Leave them enabled. When SELinux blocks something legitimate (say nginx serving files from /srv/www), fix the label instead of disabling SELinux:
9. Logging, auditing and integrity#
- Review logins:
last,sudo lastb(failed logins),journalctl -u ssh --since today,/var/log/auth.log. - Review sudo use:
journalctl _COMM=sudo. - auditd (
sudo apt install auditd) records security-relevant events. For example,sudo auditctl -w /etc/passwd -p wa -k passwd-changeslogs writes to/etc/passwd, andsudo ausearch -k passwd-changesshows them. - Lynis (
sudo apt install lynis, thensudo lynis audit system) scans the system and prints a prioritised list of hardening suggestions. It's a great way to check your work. - Ship logs off the server: an attacker who gets root can edit local logs.
10. Backups and recovery#
Ransomware and mistakes are both answered by backups:
- Follow the 3-2-1 rule: 3 copies, on 2 kinds of storage, 1 off-site.
- Automate them (cron/systemd timers +
rsync,resticorborg, plus database dumps). - Test restores regularly. A backup you've never restored is a hope, not a backup.
- Keep server setup in code (shell scripts, Ansible, cloud-init) so you can rebuild a compromised machine quickly instead of trying to clean it.
The hardening checklist#
Common mistakes#
- Locking yourself out: disabling passwords before keys work, or enabling the firewall without SSH. Always keep a second session (or the provider's console) available.
- Disabling SELinux/AppArmor "because it was in the way" instead of fixing the policy.
chmod 777and running everything as root to make errors go away.- Exposing databases, Redis or admin dashboards to the internet "temporarily".
- Postponing reboots forever after kernel updates.
- Security through obscurity alone, like changing the SSH port and calling it done.
- No backups, or untested ones.
What's next#
Congratulations, you've completed the Linux course! 🎉 You can navigate and manage a Linux system, automate it with bash, and run and secure servers. From here, put it into practice: set up a small cloud VM, deploy an app behind nginx with a systemd service, automate its backups with a timer, and harden it with this checklist. Natural next steps are Docker and containers, Git, and configuration management with Ansible.
Check your understanding
Quick quiz
1.What is the single most effective routine security measure for a Linux server?
2.What does fail2ban do?
3.Which principle says every user and service should have only the permissions it needs?
Finished reading?
Mark this lesson complete to track your progress.