Linux hardening in 60 seconds
A Linux hardening review often ends with a reassuring number. The package list is shorter, a few kernel parameters have changed, and the hardening index is higher. The number can track work. It cannot show whether an exposed service still runs as root, whether one administrator account can be reused across the fleet, whether a compromised process can reach a credential, or whether the system can survive the next reboot.
That difference is the subject of this methodology. I use Lynis as a broad local sensor and The Practical Linux Hardening Guide as a catalogue of rationale, policy families, and questions. Neither source becomes an automatic remediation engine. The final decision comes from the host’s role, current platform, exposed authority, operational dependencies, and a retest of the original security claim.
The central rule is simple:
A hardening change is complete only when the intended workload still works and the dangerous behavior that motivated the change now fails.
This note is source-reviewed methodology, not a hidden benchmark result. It does not publish a before-and-after Lynis score or claim that the three-state experiment below has already been run. The protocol is designed so that a future lab record can add those measurements without rewriting the conclusion around invented evidence.
A score is an observation, not an outcome
Lynis is useful precisely because it looks across many subsystems: boot configuration, kernel
settings, authentication, shells, filesystems, storage, networking, package state, logging,
schedulers, service configuration, and hardening features. It gives each test a stable identifier,
records technical detail in /var/log/lynis.log, and writes machine-readable findings to
/var/log/lynis-report.dat.
The tool’s own documentation preserves the important boundary. An OK result does not prove that
the target is safe, and a WARNING is not automatically a vulnerability. Suggestions express
possible room for improvement. Applicability and impact still belong to the auditor.
The hardening index has the same limit. It summarizes the controls Lynis tested and how its current profile scored them. It does not know the complete business role of the server, the trust carried by the application, the reachability of an administrative interface, the sensitivity of an attached secret, or the recovery process surrounding the host.
Two systems can therefore have similar scores and materially different risk:
- a public reverse proxy with narrow service authority and a tested rebuild path;
- an internal management server with a reusable deployment key, broad sudo access, and a backup agent that can execute privileged recovery actions across the fleet.
The second host may listen on fewer ports. It can still carry more authority.
Start with the server role, not the scanner
Before the first scan, write a one-page host contract. If this cannot be completed, the hardening review does not yet know what it is protecting.
| Question | Evidence to record |
|---|---|
| What does the host do? | Service owner, workload, data class, availability objective |
| Who can reach it? | Expected source networks, public exposure, management route |
| Which identities does it trust? | Human administrators, service users, workload identities, SSH principals |
| What can the workload control? | Files, sockets, databases, cloud APIs, orchestration or backup systems |
| How is it rebuilt? | Image or configuration source, package provenance, restore dependencies |
| What must never happen? | Named unauthorized action, credential access, privilege transition, or data route |
This contract turns a generic Lynis suggestion into a decision. A compiler on a disposable build worker has a different meaning from the same compiler on an immutable production appliance. A second name server may be essential for a server and irrelevant to an isolated single-purpose lab host. A service legitimately requiring network and device access should not be forced into a generic sandbox profile only to improve an exposure number.
The same rule applies to external baselines. CIS Benchmarks are consensus configuration recommendations for specific products and versions. OpenSCAP evaluates explicit SCAP content and profiles. The trimstray guide provides useful explanations and operational cautions, but its own README says that it is a checklist rather than an exhaustive standard and that its examples were built around RHEL 7 and CentOS 7.
Use the reasoning. Select current content for the exact platform. Never copy an old control into a modern host because its name still sounds secure.
Preserve a reproducible baseline
The first run should be boring, read-only, and attributable. Use a disposable lab clone or an approved test host before changing production. Record the exact distribution, kernel, Lynis version, active profile, virtualization context, running services, listening sockets, mounts, and package source.
The following commands collect a local baseline without changing configuration:
uname -a
cat /etc/os-release
systemd-detect-virt
lynis show version
lynis show profiles
lynis show settings
ss -lntup
systemctl --type=service --state=running --no-pager
findmnt -rn -o TARGET,SOURCE,FSTYPE,OPTIONS
Run the audit from a trusted package or a reviewed checkout. The common system audit is:
sudo lynis audit system --quick --nocolors --auditor "controlled-hardening-baseline"
Lynis purges its detailed log on the next scan. Preserve the evidence immediately, on the audited host, in a restricted case directory:
case_dir="/var/tmp/linux-hardening-case-001/baseline"
sudo install -d -m 0700 "$case_dir"
sudo cp --preserve=timestamps /var/log/lynis.log "$case_dir/"
sudo cp --preserve=timestamps /var/log/lynis-report.dat "$case_dir/"
sudo sha256sum "$case_dir/lynis.log" "$case_dir/lynis-report.dat" |
sudo tee "$case_dir/SHA256SUMS" >/dev/null
These files can expose hostnames, package inventory, services, filesystem paths, and policy state. Keep the originals inside the engagement evidence boundary. Publish only a redacted derivative, never the raw report from a customer or production host.
Turn every suggestion into a hypothesis
Do not sort the backlog only by warning versus suggestion or by the points available to the hardening index. Add the missing operational fields:
- Observation: what did the test actually see?
- Applicability: does the expected state apply to this platform and role?
- Authority: what additional action becomes possible because of the state?
- Reachability: from which realistic source can that action be attempted?
- Composition: which credential, service, mount, socket, or management plane completes the path?
- Change risk: what legitimate function can the remediation break?
- Security test: what exact action should fail afterward?
- Positive control: what exact workload action must continue to succeed?
- Rollback: how will the team recover if the positive control fails?
This produces four queues instead of one long list:
- path-breaking controls remove reachable privilege, exposed authority, or credential access;
- resilience controls improve detection, integrity, recovery, and safe operation;
- baseline obligations are required by policy even when direct attack-path impact is limited;
- accepted exceptions have a named reason, owner, compensating control, and expiry date.
An exception is not a silent skip. It is part of the evidence.
Prioritize the controls that change authority
The exact order depends on the host contract, but the following sequence usually creates better decisions than starting with cosmetic findings.
1. Reduce reachable surface
Inventory listening sockets and the process, namespace, interface, and firewall path behind each one. Remove or bind unnecessary services. Confirm the change from an approved external source as well as from the local socket table. A closed local process and a filtered network path are different controls; record which one changed.
2. Narrow administrative identity
List who can authenticate, who can use sudo, which commands are permitted, where SSH keys are authorized, and whether automation shares the same identity as humans. Prefer named principals, narrow command authorization, short-lived credentials, and an independently tested emergency route. Do not print private keys, password hashes, or secret values into the evidence bundle.
3. Constrain the service, not only the user account
A non-root Unix user is a useful boundary, but the service may still inherit broad filesystem,
device, network, capability, and IPC access. For systemd services, systemd-analyze security can
identify missing sandboxing directives and produce an exposure score. Its manual is explicit that
the analysis is incomplete when the service can ask other processes to act through IPC. Treat the
result as another candidate, not a proof of containment.
Start with the service’s real needs: writable paths, address families, devices, capabilities, system calls, temporary storage, home directories, and kernel interfaces. Add one restriction at a time in a lab or canary, restart the service, exercise the positive control, and inspect the logs.
4. Protect credentials and process boundaries
Ask which files, environment variables, agents, sockets, core dumps, and same-user processes can
expose credentials. The Linux Yama LSM documentation explains why unrestricted same-UID ptrace
can let one compromised application inspect another process and expand into SSH sessions or
credential agents. Whether a stricter ptrace_scope is appropriate depends on debugging,
observability, crash handling, and the platform’s existing policy.
This is why a sysctl should never be copied from a list without a positive control. A change that blocks the incident responder, profiler, or crash collector may be secure in one role and operationally destructive in another.
5. Make detection and recovery part of the hardening state
Package provenance, time synchronization, audit coverage, log forwarding, file integrity, configuration history, and tested rebuild instructions decide whether a future compromise can be bounded. A system with no unnecessary services but no trusted rebuild source is not finished.
NIST’s server security guidance frames hardening as part of a lifecycle: plan, configure, maintain, monitor, and preserve the ability to respond. The practical unit is therefore not one host at one moment. It is the host, its management plane, its evidence, and its recovery path.
Run the three-state experiment
Use a disposable clone of a supported Linux release and give it one realistic workload—for example, OpenSSH plus a small systemd-managed HTTP service. Snapshot it before changes. Keep the network isolated to the approved lab and use reserved identities and data.
State A — baseline
Record the host contract, local inventory, Lynis output, service health, reachable sockets, current administrative path, and rebuild time. Define one bounded security claim, such as:
CLAIM The web service cannot write outside its approved state directory
SOURCE a controlled request through the approved lab interface
PRINCIPAL the service account created for the lab
PROTECTED ASSET a root-owned canary file outside the writable path
POSITIVE CONTROL the service writes its expected application state
NEGATIVE CONTROL the service cannot modify the protected canary
Do not exploit a vulnerability or target a real service. The negative control should be a harmless permission or reachability test against a canary created for this experiment.
State B — score-driven
Choose several applicable, reversible findings that can improve the index but are not expected to change the named path. Apply them through the platform’s supported configuration mechanism. Reboot when required, repeat the workload test, re-run Lynis, and repeat the negative control.
The purpose is not to mock the controls. They may be valuable baseline or resilience work. The question is narrower: did the score change while the named path stayed the same? Record the answer, including a failed hypothesis.
State C — threat-driven
Change the earliest durable edge in the named path: service identity, writable path, capability, socket reachability, sudo rule, credential reader, or management-plane permission. Repeat the same positive and negative controls from the same source context. Re-run Lynis, but do not require the index delta to be large. The security result is the denied path plus the healthy workload.
The comparison record should contain observations, not adjectives:
| Measurement | State A | State B | State C |
|---|---|---|---|
| Lynis version and profile | Record | Same | Same |
| Hardening index | Measure | Measure | Measure |
| Warnings and suggestions | Preserve | Diff | Diff |
| Listening surface | Measure | Recheck | Recheck |
| Named authority path | Test | Test | Test |
| Positive workload control | Pass/fail | Pass/fail | Pass/fail |
| Negative security control | Pass/fail | Pass/fail | Pass/fail |
| Reboot and recovery | Time | Time | Time |
Until those cells contain captured evidence, the article should not publish a numeric conclusion.
What can break
Hardening is production change, and production change can remove availability as effectively as an attacker. Put dependency discovery and rollback beside every recommendation.
| Change family | Likely dependency | Positive control | Negative control |
|---|---|---|---|
| SSH authentication restriction | automation, break-glass access, bastions | approved administrator can connect through the intended route | removed identity or route is rejected |
| systemd filesystem isolation | upload paths, caches, certificates, Unix sockets | normal request can read and write only required state | protected canary remains unchanged |
| Capability reduction | low ports, time, network administration, tracing | service starts and completes its health check | removed privileged operation fails |
| Firewall or bind change | monitoring, load balancers, cluster peers | expected source reaches the service | unapproved source cannot reach it |
| Kernel or ptrace policy | debuggers, profilers, crash collection, EDR | approved diagnostic workflow succeeds | unrelated same-user process cannot inspect the canary process |
| Mount hardening | package scripts, temporary execution, containers | approved update and workload flow succeed | disallowed execution or write path fails |
| Audit and log changes | disk capacity, privacy, SIEM parsing | expected event arrives with correct time and identity | a controlled policy violation is not silent |
Apply changes in a canary, keep console or recovery access outside the path being modified, preserve the previous configuration, and define the rollback trigger before the window. A setting that is silently reverted after an outage is not a hardening success.
Evidence matrix
| Hardening claim | Evidence required | Negative control | What is not enough |
|---|---|---|---|
| Unnecessary network exposure is removed | process, socket, interface, firewall, and approved external reachability before and after | connect from the previously reachable unapproved source and require failure | ss output alone |
| Administrative access is narrow | named principals, SSH policy, sudo scope, successful approved login, and denied removed route | use the removed identity or source route and require rejection | a changed configuration file |
| The service is contained | runtime identity, effective capabilities, writable paths, devices, address families, IPC dependencies, and workload health | attempt the bounded canary action outside the declared authority | a good systemd-analyze security score |
| Kernel controls match the role | running value, persistent source, supported-platform documentation, dependency test, and reboot verification | repeat the harmless action the setting is meant to restrict | copying a sysctl list from another distribution |
| Lynis findings are remediated | preserved baseline report, applicable control ID, root-cause change, post-scan diff, owner, and retest | repeat the original security test from the original source | fewer warnings or a higher index |
| Logging is useful | controlled event, trusted timestamp, source identity, transport, storage, alert or query result, and retention owner | generate the canary event and require it to appear end to end | auditd installed or a SIEM agent running |
| Recovery is viable | trusted source, configuration history, isolated credentials, timed rebuild, restored workload, and integrity validation | rebuild without depending on the host or identity plane being recovered | a VM snapshot or successful backup job |
What the final record should contain
Do not hand the owner a terminal screenshot and a percentage. For each accepted control, record:
- host role, owner, environment, distribution, kernel, and workload version;
- Lynis version, active profile, test identifier, original observation, and evidence hashes;
- platform-specific baseline and the exact version used;
- applicability decision and any accepted exception;
- reachable source, effective principal, protected asset, and authority created by the state;
- configuration change, deployment mechanism, change owner, and rollback trigger;
- positive workload control and negative security control;
- reboot, failover, monitoring, and recovery results;
- remaining exposure, compensating controls, retest date, and evidence location.
This structure prevents two common errors. First, a scanner suggestion is not promoted directly to a finding. Second, a changed setting is not promoted directly to a closed finding.
The order I would use
If the review has one week, use this sequence:
- Define the host role, protected authority, and recovery boundary.
- Preserve a trusted local baseline and Lynis evidence.
- Validate reachable services and administrative identity paths.
- Select the few controls that remove the earliest durable edges.
- Apply one change family at a time with a rollback path.
- Reboot when required and test the intended workload.
- Repeat the exact negative security control.
- Re-run Lynis and record the diff without treating the score as the conclusion.
- Test log visibility and rebuild or restore the disposable host.
- Convert the remaining suggestions into owned work, policy obligations, or expiring exceptions.
The result is smaller than a universal checklist and stronger than one. It connects each control to a system role, a reachable action, a protected asset, an operational dependency, and a result that another engineer can repeat.
My conclusion
The Practical Linux Hardening Guide is valuable because it explains why controls exist and connects them to established policy families. Lynis is valuable because it quickly turns a live Unix-like system into a broad, attributable set of observations. Their best use is together—but not as an automatic sequence of scan, copy, paste, and celebrate.
Start with what the host is trusted to do. Use current platform content. Treat every tool result as a candidate. Remove the earliest reachable authority edge. Keep the service alive. Then repeat the original action and preserve the denial.
A higher score may accompany that result. The evidence is what makes it hardening.
MITRE ATT&CK mapping
| Tactic | Technique ID | Technique name | Defender verification signal |
|---|---|---|---|
| Execution | T1059.004 | Command and Scripting Interpreter: Unix Shell | Audit command execution in interactive sessions via auditd |
| Privilege Escalation | T1548.001 | Abuse Elevation Control: Setuid and Setgid | find / -perm -4000 -type f audits against baseline inventory |
| Persistence | T1543.002 | Create or Modify System Process: systemd Service | systemd-analyze security <unit> sandboxing posture audit |
| Credential Access | T1003.008 | OS Credential Dumping: /etc/passwd and /etc/shadow | Strict file mode 000 / 640 on /etc/shadow verified via Lynis |
| Defense Evasion | T1070.002 | Indicator Removal on Host: Clear Linux Logs | Remote syslog forwarding + immutable audit log directory |
Defender action checklist
Use this actionable checklist during post-assessment remediation:
- Enforce Yama ptrace restrictions: Write
kernel.yama.ptrace_scope = 2to/etc/sysctl.d/99-security.confand apply withsysctl -p. - Harden exposed systemd units: Add
ProtectSystem=strict,ProtectHome=yes, andNoNewPrivileges=yesto service drop-ins. - Audit privileged transitions: Add
-w /etc/sudoers -p wa -k identity_changesto/etc/audit/rules.d/audit.rules. - Verify workload survivability: Run test suite against target service before signing off on hardening baseline.
Sources reviewed
- trimstray: The Practical Linux Hardening Guide
- CISOfy: Lynis source repository
- CISOfy: Lynis installation and usage
- CISOfy: Lynis report and logging guide
- Center for Internet Security: CIS Benchmarks
- OpenSCAP 1.4.1 user manual
- NIST SP 800-123: Guide to General Server Security
- systemd-analyze manual
- Linux kernel documentation: Yama
How current is this note?
The latest source-review, content-update, or publication date is shown.
The author completed a technical review. This does not, by itself, claim lab reproduction.
