How to harden a Linux server safely in 2026
Linux has no centralized console to push 250 security settings across 400 servers. A flat list of 50 hardening steps leaves the work unguided. Start with the controls that reduce unauthorized access, then work toward deeper system restrictions.
Secure a Linux server by matching the CIS benchmark to its operating system. Lock down SSH and privilege escalation, restrict network exposure, apply compatible filesystem and kernel controls, patch the host, forward audit events to a SIEM, and check service health after every batch.
Use this guide to order the work and expose common failure modes. Certification still depends on the host’s workload, effective configuration, and test results.
In this article
- Linux hardening is configuration management, not a settings hunt
- Choose the benchmark that matches the operating system
- Lock down SSH before touching kernel settings
- Protect the paths that reach root
- Close network paths you do not need
- Harden temporary filesystems carefully
- Use sysctl for controls you understand
- Patch the host, then promote a tested profile
- Forward audit events so they can drive detection
- What will this break on a real server?
- Verify the server instead of declaring victory
Linux hardening is configuration management, not a settings hunt
Linux hardening lives across package settings, service managers, authentication files, security modules, permissions, and kernel parameters. Ownership matters more than memorizing filenames.
Keep a profile for each server. Record its role and required services. Add approved controls, exceptions, rollback steps and verification evidence. Debian-family and RHEL-family systems need separate procedures and, at scale, separate Ansible roles. A setting copied from a RHEL guide can be wrong for Debian even when the filename looks familiar.
Apply the work in this order:
- secure SSH, accounts, and privilege escalation;
- close unnecessary network paths;
- restrict filesystems and system behavior;
- patch and maintain the host;
- make audit events useful for detection;
- verify configuration and service health.
Keep SELinux enforcing on RHEL-family systems and AppArmor enabled on Ubuntu or Debian where the application has a working profile. Test policies before enforcing them.
Our approach is deliberately boring: small batches, recorded changes, and a tested recovery path. That beats collecting shell commands from incompatible checklists.
Choose the benchmark that matches the operating system
CIS Benchmarks provide the right starting structure for Linux server hardening. The CIS Benchmark portal offers benchmark PDFs free for non-commercial use.
Which Linux versions appear in the 2026 list?
| Platform | Benchmark version |
|---|---|
| AlmaLinux OS 8 | 4.0.0 |
| AlmaLinux OS 9 | 3.0.0 |
| AlmaLinux OS 10 | 1.0.0 |
| Amazon Linux 2 | 4.0.0 |
| Amazon Linux 2023 | 1.0.0 |
| Debian Linux 11 | 2.0.0 |
| Debian Linux 12 | 2.0.0 |
| Debian Linux 13 | 1.1.0 |
| Ubuntu 22.04 | 3.0.0 |
| RHEL 10 STIG | 1.0.0 |
The 2026 release activity includes Debian 13 and Ubuntu 22.04 coverage, while RHEL 10 STIG 1.0.0 arrived during the year. The CIS January 2026 update records additional new and revised benchmark activity.
Start with Level 1 for most production systems. Move to Level 2 when the security requirement warrants tighter restrictions and the application has passed its tests. CIS is a baseline, not a production deployment script.
A benchmark gives you a defensible control set. It does not know whether your monitoring agent needs to read Nginx logs or whether PostgreSQL depends on a particular shared-memory limit.
Lock down SSH before touching kernel settings
Disabling password SSH authentication is more valuable than arguing over a perfect cipher list. Close the account-access path first.
Assume a production Ubuntu or Debian host running Nginx, PostgreSQL, and a monitoring agent, administered by a small operations team over SSH.
Before changing SSH, open a second administrative session with a tested key. Keep the current session open. Confirm that another approved administrator can connect. Then review a profile such as:
PermitRootLogin no
PasswordAuthentication no
MaxAuthTries 4
LoginGraceTime 60
ClientAliveInterval 300
ClientAliveCountMax 3
AllowGroups ssh-admins
Banner /etc/issue.net
PermitRootLogin no removes direct remote root login. PasswordAuthentication no removes password authentication through SSH once key-based access works. AllowGroups limits SSH access to approved accounts; use AllowUsers when an explicit user list is more appropriate.
The keepalive settings express an intended liveness policy: probe an inactive connection every 300 seconds and close it after three unanswered probes. Verify the effective configuration, especially when included files or drop-ins may override the main file.
Algorithm tuning comes later. The following is an example policy from the source material, not a universal recommendation:
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-256,hmac-sha2-512
KexAlgorithms ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha256
Check every algorithm against the installed OpenSSH version and the client fleet before deploying it. A cipher list that strands your only administrative client is a security control with poor operational judgment. Banner /etc/issue.net supports legal or compliance notices; it is not a security boundary.
Validate with sshd -t, open the new connection, and test administrative access. Use your distribution’s service manager to reload OpenSSH only after both checks pass. Preserve the existing session until the new one works.
Protect the paths that reach root
On the systems covered here, root remains part of the privilege model. Protect the paths that reach it.
Use named human accounts and require sudo. Restrict administrative-group membership. Review which commands each administrator may run. Keep human identities separate from service accounts. Nginx, PostgreSQL, backups, and monitoring should run under the narrow identities their work requires.
Audit sudo execution and changes to sudo policy. SSH controls entry; sudo controls what an authenticated user can do afterward. Review both boundaries.
Be careful with pam_faillock. Lockout can reduce repeated interactive authentication attempts, while also locking an automated service account after stale credentials or a failed job. Scope it to interactive PAM services such as SSH and login, then test scheduled tasks separately.
Close network paths you do not need
Start with a listener inventory. Map SSH, web services and databases to the source networks that require them. Do the same for monitoring, backups and administration interfaces.
Identify listeners and owners. Document required source networks and allow recovery access for SSH. Then apply an allow-list policy. Afterward, inspect exposure from a separate administrative session.
Once required allows are defined, deny unsolicited inbound traffic by default. Choose the firewall tooling that fits the distribution and existing estate. UFW, nftables, and iptables all have legitimate uses, but mixing frameworks on one host makes ownership unclear.
For the example host, Nginx may need public access while PostgreSQL and monitoring should accept connections only from approved networks. The exact ports and networks belong in your inventory.
Disabling IPv6 because a checklist says so is security theater until you have checked what listens on it. Java applications, Redis, and some database listeners may bind IPv6 by default. Audit listeners and routes first. Check the clients too. Secure IPv6 alongside IPv4, or disable it only when the workload proves it is unused.
Harden temporary filesystems carefully
These options often have limited impact, but a production host can still depend on execution, device access, or SUID behavior in those paths. Test each mount before rollout.
Where compatible, set noexec, nosuid, and nodev for /tmp, /dev/shm, and /var/tmp in /etc/fstab.
noexecblocks binary execution from the mount.nosuidprevents set-user-ID and set-group-ID execution there.nodevprevents device files from functioning there.
Test installers and application launchers that use these directories. Test agents and scheduled jobs too.
For PAM-managed sessions that do not need core dumps, use limits such as:
* hard core 0
* soft core 0
Core files can contain credentials, keys, and application data. This limits PAM-managed sessions; it may not govern every systemd-managed daemon. Check the daemon’s effective limit separately.
Verify ASLR with:
kernel.randomize_va_space = 2
Most distributions already enable it. Check the effective value instead of assuming.
Treat umask 027 as a compatibility decision. On the example host, test whether the monitoring agent can still read Nginx logs. Check that applications can create the temporary, socket or PID files they need.
Use sysctl for controls you understand
Vucense describes sysctl hardening as a high-impact, low-effort Level 1 area. That supports selected controls, not a generic kernel file deployed everywhere.
Use net.ipv4.tcp_syncookies=1 as an example to assess against the selected benchmark and workload. Do not call any isolated sysctl value universally safe.
Database-host kernel limits copied from a generic benchmark are overrated. Values such as kernel.shmmax, kernel.shmall, and kernel.sem depend on database configuration and vendor requirements. Record the previous value and define a rollback path before changing any of them.
Transparent huge page disablement is one area where CIS guidance and database vendors including MongoDB, Redis, and Oracle point in the same direction (for containers, see our guide to securing Docker containers in production). The exact operational method and impact still require database-specific validation.
Patch the host, then promote a tested profile
Patching is a hardening control with a deadline attached. Inventory pending updates and test them in a comparable environment where possible. Schedule the maintenance window, apply the updates, reboot when required, then check the affected services.
The “under 30 minutes” claim applies to a fresh Ubuntu server and a narrow Level 1 pass across five areas. It says little about a production host with application dependencies.
After updates, check the service manager’s active state and the application health endpoint. Test the database connection and monitoring heartbeat. Check the backup and administrative access. Record the result and any exception.
For fleet rollout, promote the tested profile through separate Debian-family and RHEL-family Ansible roles. Apply controls in batches, review exceptions, and release the role to production only after the profile passes its service checks.
Forward audit events so they can drive detection
auditd sitting on the server is not a detection strategy. If an attacker can clear the local log, the improvement is mostly cosmetic; forward the events to a SIEM.
“A hardened server without auditd configured provides compliance improvements but limited detection capability. auditd with the right rule set turns the hardened server into a detection system.”
Prioritize privileged command execution and changes to /etc/passwd, /etc/shadow, /etc/sudoers, and /etc/sudoers.d/. Cover sudo policy and authentication too. Include su, SSH logins and network socket creation.
Representative rules include:
-a always,exit -F arch=b64 -F euid=0 -S execve
-w /etc/passwd -p wa
-w /etc/shadow -p wa
-w /etc/sudoers -p wa
-w /etc/sudoers.d/ -p wa
-a always,exit -F arch=b64 -S socket
Do not copy this block as a complete production profile. Rule syntax, architecture coverage, persistence, and the selected CIS profile must match the host. -S socket can create substantial event volume, so prioritize events and configure rate limits deliberately.
Forward through the auditd dispatcher or an audisp-syslog plugin into the host’s supported syslog transport, then to the SIEM. The exact path varies by distribution. Confirm it:
auditd → audit dispatcher or plugin → supported syslog transport → SIEM
Generate a privileged command and an authentication event. Change a watched file as well. Confirm that the SIEM receives searchable records and that the relevant detections work.
What will this break on a real server?
Treat this table as a pre-change review: find the control, identify the dependent service, and write the test before changing the setting.
| Control | Likely failure | Safer response |
|---|---|---|
umask 027 | Monitoring can’t read Nginx or Apache logs; applications lose expected access to temporary, socket, or PID files. | Test file creation and reader permissions for each service; scope the umask where necessary. |
pam_faillock | An automated service account becomes locked. | Apply lockout to interactive services such as SSH and login; test automation separately. |
| Disable IPv6 | Java, Redis, or a database listener fails because it binds IPv6 by default. | Audit listeners and clients; secure IPv6 or disable it only with evidence. |
Restrict kernel.shmmax or kernel.shmall | PostgreSQL may fail to start. | Check the required shared memory against shared_buffers plus overhead, then test startup against the host’s memory mechanism and configuration. |
Restrict kernel.sem | Oracle’s documented semaphore requirements conflict with benchmark values. | Follow Oracle’s installation guidance and record the benchmark exception. |
nosuid on /var | An unusual database installation relying on SUID binaries under /var stops working. | Check the installation layout before applying the mount restriction. |
A roughly 250-control Level 1 profile applied without workload testing will break production systems predictably, often through failed startup or lost monitoring rather than an obvious crash. A green benchmark score beside a broken monitoring agent is a failed hardening job.
Verify the server instead of declaring victory
Use one acceptance sequence after each batch:
- Recheck SSH from a new session with a tested administrative key.
- Confirm root login and password authentication behave as intended.
- Compare firewall exposure with the service inventory.
- Inspect mount options, core-dump limits, ASLR, and approved sysctl values.
- Generate or inspect privileged, authentication, sudo, and watched-file audit events.
- Confirm a corresponding event arrives in the SIEM and remains searchable.
- Run the selected CIS assessment and record justified exceptions.
- Check the service manager’s active state and application health endpoint. Test the database connection and monitoring heartbeat. Check the backup and automation.
A benchmark assessment measures configuration against a profile. It does not prove that the application still works. The workload checks complete the evidence.
Record seven artifacts: benchmark version, effective SSH configuration, firewall exposure, mount and sysctl values, service checks, a SIEM event identifier, and approved exceptions.
No artifact, no rollout.