Linux Server Hardening Techniques: A Beginner’s Practical Checklist
Server hardening is a critical practice aimed at minimizing the attack surface of a Linux server and reinforcing its defenses against cyber threats. For beginners looking to enhance their system security, this article provides actionable techniques to help safeguard your Linux environment. You’ll learn fundamental strategies for protecting against common vulnerabilities, managing packages, and implementing security measures such as firewalls and access controls. By the end of this checklist, you will be equipped with the knowledge to effectively harden your server and reduce its risks.
What’s Covered in This Guide
In this guide, we will discuss preparation steps, system updates, minimizing attack surfaces, securing authentication and accounts, network security measures, and a thorough approach to logging and monitoring. By following these steps, you will create a more secure Linux server environment.
Preparation: Inventory, Backups, and Staging
Before implementing any changes to production systems, it is essential to prepare:
-
Inventory Packages and Services
- For Debian/Ubuntu:
dpkg -l
- For RHEL/CentOS/Fedora:
rpm -qa
- Check listening services with:
ss -tuln
orss -tulnp
- Review systemd units using:
systemctl list-units --type=service --state=running
- For Debian/Ubuntu:
-
Backups and Recovery Plan
- Use automated backups like rsync snapshots or vendor solutions.
- Regularly test restore procedures—backups are only valuable if they restore successfully.
- For larger systems, consider secure clusters or resilient storage setups (see secure storage and backup options).
-
Staging Environment
- Test hardening changes in a non-production environment (like a VM, container, or home lab). Consider our home lab setup guide for practice.
- Ensure you have out-of-band console access before making significant changes.
Keep Your System Updated and Manage Packages
Utilize your distribution’s native package manager and enable security updates.
-
For Debian/Ubuntu:
- Use
sudo apt update && sudo apt upgrade -y
and considerunattended-upgrades
for lower-risk systems.
- Use
-
For RHEL/CentOS/Fedora:
- Use
dnf
oryum
; evaluatednf-automatic
for scheduling updates.
- Use
-
Tips
- Avoid holding back packages without strong justification; document exceptions.
- Subscribe to your distribution’s security mailing list and monitor end-of-life (EOL) dates.
Automate patching where feasible, but employ staged rollouts for critical services to prevent unexpected downtimes.
Minimize Attack Surface: Remove Unneeded Packages & Services
Lowering the software and services residing on a host reduces the likelihood of vulnerabilities.
-
Audit Services
- Disable unused services with:
sudo systemctl disable --now service-name
- List enabled services:
systemctl list-unit-files | grep enabled
- Disable unused services with:
-
Remove Unnecessary Packages
- Example removal:
sudo apt purge ftp exim4
(after confirming it’s not needed). - Maintain a change log and rollback plan.
- Example removal:
-
Check Listening Ports
- Use
ss -tuln
to list TCP/UDP listeners. Close or restrict any open services that are not essential.
- Use
When uncertain, remove the package but document the reasoning—some packages may be dependencies for others.
Secure Authentication and Accounts
Authentication vulnerabilities are often the starting point for many compromises. Key areas to focus on include SSH and user accounts.
- SSH Hardening
- Transition to key-based authentication and disable passwords by editing
/etc/ssh/sshd_config
:
- Transition to key-based authentication and disable passwords by editing
# /etc/ssh/sshd_config (example)
Port 22 # Change optional; not a strictly secure measure
PermitRootLogin no # Prevent direct root login
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers sysadmin # Restrict users that may log in
ChallengeResponseAuthentication no
UsePAM yes
-
Test with a separate session before closing your current SSH session to avoid lockout. After editing, reload SSH with:
sudo systemctl reload sshd
. -
SSH Key Best Practices
- Use modern key types (ed25519 or RSA 3072+).
- Protect private keys with a passphrase and utilize
ssh-agent
locally. - Prefer a bastion host for administrative access instead of opening SSH to the internet.
-
Disable Root Login and Implement Sudo
- Set
PermitRootLogin no
and add users to a sudo group (e.g.,wheel
orsudo
). - Edit sudoers via
sudo visudo
and reduceNOPASSWD
usage.
- Set
-
Password Policy and Account Locking
- Enforce password complexity with
libpam-pwquality
. - Lock accounts after repeated failures using
pam_faillock
(RHEL/Fedora) orpam_tally2
(older systems).
- Enforce password complexity with
-
Centralized Auth and MFA
- For multiple servers, consider centralized authentication (LDAP). See our guide on centralized authentication with LDAP for an integration tutorial.
- Implement Multi-Factor Authentication (MFA) for SSH where feasible (using OTP via Google Authenticator or hardware tokens).
Network Security – Firewalls and Packet Filtering
Adopt a default-deny inbound policy and only open necessary ports.
- Basic Firewall (ufw on Ubuntu)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp # Restrict IP for management
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.10 to any port 22
sudo ufw enable
sudo ufw status verbose
- Advanced: nftables
- Document rules in code and maintain version control.
Comparison Table: ufw vs nftables vs iptables
Tool | Beginner-friendly | Power & Flexibility | When to use |
---|---|---|---|
UFW | High | Low–Medium | Small servers, quick setups (Ubuntu) |
nftables | Medium | High | Modern, high-performance filtering with complex rules |
iptables | Low–Medium | High | Legacy systems with compatibility needs |
- Other Network Hardening Measures
- Restrict admin access by IP/subnet.
- Implement rate-limiting to mitigate brute-force attacks.
- Log firewall decisions and periodically review them.
For reproducibility, store firewall rules in infrastructure as code (IaC) and automate with a configuration management tool.
Mandatory Access Controls and Filesystem Protections
Adopt policy-driven access control and enhance filesystem protections.
-
SELinux/AppArmor
- Enable SELinux on RHEL-based systems and AppArmor on Ubuntu for added confinement beyond UNIX permissions.
- Refer to the Ubuntu documentation for practical implementation steps.
-
Secure File Permissions
- Identify world-writable files using:
find / -xdev -type f -perm -0002 -print
- Find SUID/SGID files with:
find / -xdev \( -perm -4000 -o -perm -2000 \) -print
- Carefully remove unnecessary SUID, testing functionality post-removal.
- Identify world-writable files using:
-
Mount Options and Immutable Flags
- Utilize
noexec,nodev,nosuid
for/tmp
in/etc/fstab
:
- Utilize
tmpfs /tmp tmpfs defaults,noexec,nodev,nosuid 0 0
- Set immutable flags with
chattr +i /etc/important.conf
; proceed with caution as updates may not succeed if the file is immutable.
Logging, Monitoring, and Intrusion Detection
You cannot protect what you cannot see; centralize logs and perform integrity checks.
-
Centralized Logging
- Configure log forwarding off-host (using rsyslog/syslog-ng/fluentd) to minimize tampering.
-
Auditd and Audit Rules
- Install
auditd
and establish rules to monitor changes, especially in/etc
, privileged binaries, and authentication events by adding:
- Install
# Add to /etc/audit/rules.d/hardening.rules
-w /etc/ -p wa -k etc_changes
-w /usr/bin/sudo -p x -k privileged
-
File Integrity and IDS
- Use AIDE (Advanced Intrusion Detection Environment) to detect file changes. Initialize the database and schedule checks using cron or Ansible.
-
Fail2ban
- Safeguard SSH and other services against brute-force attempts by banning IPs after repeated failed logins.
-
Alerting and Review
- Implement alerting systems (e.g., email, Slack, or PagerDuty) and regularly review high-severity incidents to refine your monitoring.
Application-Level Hardening and Container Considerations
Strengthen web servers, databases, and containers.
-
Web Servers & Databases
- Disable unused modules, enforce HTTPS, and implement strong TLS configurations. Utilize Let’s Encrypt or an internal CA.
-
Containers
- Conduct vulnerability scans on images, avoid running as root, employ read-only rootfs, and limit capabilities where possible.
- Explore network segmentation for containers and service meshes for advanced configurations; refer to our guide on container networking best practices.
-
Run Services as Non-Root Users
- Ensure systemd units specify
User=
andGroup=
as needed for security.
- Ensure systemd units specify
Backup, Recovery, and Incident Response Basics
Implementing robust backup and response strategies mitigates downtime and data loss.
-
Backup Best Practices
- Automate backups, encrypt data both in transit and at rest, and, if possible, maintain offline copies.
- Regularly test restore functions to confirm data integrity.
-
Incident Response Playbook (Short)
- Isolate affected hosts, preserve volatile data, and collect logs to inform stakeholders and escalate as needed.
- Maintain forensics-friendly logs and timestamps to assist with investigations.
-
Offline & Immutable Backups
- Utilize versioned snapshots and immutable backup storage to protect against ransomware threats.
Automate Hardening and Enforce Compliance
Implementing automation ensures consistency and assists with compliance requirements like CIS Benchmarks.
-
Configuration Management
- Utilize Ansible, Puppet, or similar tools to codify hardening changes. For a beginner-friendly introduction, see our guide on automating hardening with Ansible.
-
CIS Benchmarks and Compliance
- Align automation with CIS Benchmarks to create auditable baselines. These benchmarks are both prescriptive and testable.
-
Vulnerability and Compliance Scanning
- Schedule scans using OpenVAS, Nessus, or OpenSCAP and incorporate findings into your remediation processes.
Testing and Verification: What to Check Before Declaring a Server Hardened
Verify configurations and conduct testing to ensure elevated security.
-
Basic Checks
- Check SSH configurations using:
sshd -T
. - Confirm firewall status with:
ufw status
ornft list ruleset
. - Review Auditd status using:
sudo auditctl -s
. - Assess backup health by checking the last successful run and conducting a test restore.
- Check SSH configurations using:
-
Automated Tools
- Utilize tools such as Lynis, OpenSCAP, or CIS-CAT to identify misconfigurations and prioritize remedies. Focus on addressing high/critical findings first and document accepted risks.
-
Configuration Drift
- Store configuration in Git and implement CI for change checks. Small automation scripts can facilitate nightly audits; see our guide on small automation scripts.
Practical Checklist and Next Steps
Here’s a prioritized checklist of quick wins to implement in your first hour:
- Update your Operating System:
sudo apt update && sudo apt upgrade -y
or equivalent. - Enable unattended security updates or schedule patches.
- Restrict SSH access to key-based authentication and disable root login.
- Activate a firewall and set default-deny inbound rules (use ufw or nftables).
- Install and configure fail2ban or another rate-limiting tool.
- Enable auditd and set up basic audit rules.
- Activate AppArmor/SELinux and gradually transition to an enforcing mode.
- Set up automated encrypted backups and routinely test restores.
- Centralize logs off-host for security.
- Scan systems and images for vulnerabilities and address critical issues.
Next Learning Steps
- Learn to use Ansible for automating hardening (see automate hardening with Ansible).
- Review CIS Benchmarks for prescriptive security controls and refer to NIST SP 800-123 for general server security principles.
- Practice these techniques in a home lab environment (check our home lab guide).
When to Involve Specialists
If handling regulated or sensitive data, require compliance audits, or detect active compromises, it is advisable to engage security specialists or incident response teams.
Quick Resources and References
Here are some authoritative resources for deeper dives into server hardening:
- CIS Benchmarks – Center for Internet Security
- NIST SP 800-123 – Guide to General Server Security
- Ubuntu Server Guide – Security
Additional Internal Guides
- Centralized authentication with LDAP
- Automate hardening with Ansible
- Small automation scripts
- Container networking best practices
- Practice hardening in a home lab
- Secure storage and backup options
- Resilient storage setup (RAID)
Final Notes and Safety Reminders
- Always test changes in a staging environment and ensure you have console access or recovery pathways.
- Avoid employing commands blindly; adapt them according to your environment.
- Remember that hardening is an ongoing process: prioritize the most impactful controls first (patching, SSH, firewalls, backups), and evolve your strategy over time.
Printable 10-Step Checklist (Copy for Quick Reference)
- Update OS and packages
- Enable security updates
- Enforce SSH keys and disable root login
- Enable firewall with default deny policy
- Install Fail2ban
- Activate auditd and file integrity (AIDE)
- Enable AppArmor/SELinux
- Automate encrypted backups
- Centralize logs off-host
- Scan and remediate vulnerabilities
If you wish, I can create an Ansible role template that executes many of these checks idempotently or develop a simple bash script to run verification commands and produce a summary report for your server.