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.

ONE HOST ROLE · THREE CONTROL STATES A · BASELINEreachable servicebroad authorityentry → privileged effect B · SCORE-DRIVENseveral checks passsame authority survivespath still open C · THREAT-DRIVENdurable edge removedworkload remains healthyCUTpath denied · service passes MEASUREfindings · index · reachable surface · effective privilege · workload health · rollback PASSapproved function succeeds AND the original unauthorized behavior is denied
The useful comparison keeps the workload and threat model constant. State B asks whether a better score can coexist with the same path; State C requires both security and functional evidence.

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.

QuestionEvidence 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:

  1. Observation: what did the test actually see?
  2. Applicability: does the expected state apply to this platform and role?
  3. Authority: what additional action becomes possible because of the state?
  4. Reachability: from which realistic source can that action be attempted?
  5. Composition: which credential, service, mount, socket, or management plane completes the path?
  6. Change risk: what legitimate function can the remediation break?
  7. Security test: what exact action should fail afterward?
  8. Positive control: what exact workload action must continue to succeed?
  9. 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.

FROM CONTROL SIGNAL TO VERIFIED STATE CandidateLynis ID Applicablerole + version Pathreach + authority Changerollback ready Retestallow + deny POSITIVE CONTROLexpected workload succeeds NEGATIVE CONTROLdangerous behavior fails FAIL → REOPEN TRIAGE
A scanner result earns priority only after applicability, reachability, and authority are connected. Closure requires the expected function to pass and the original dangerous behavior to fail.

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:

MeasurementState AState BState C
Lynis version and profileRecordSameSame
Hardening indexMeasureMeasureMeasure
Warnings and suggestionsPreserveDiffDiff
Listening surfaceMeasureRecheckRecheck
Named authority pathTestTestTest
Positive workload controlPass/failPass/failPass/fail
Negative security controlPass/failPass/failPass/fail
Reboot and recoveryTimeTimeTime

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 familyLikely dependencyPositive controlNegative control
SSH authentication restrictionautomation, break-glass access, bastionsapproved administrator can connect through the intended routeremoved identity or route is rejected
systemd filesystem isolationupload paths, caches, certificates, Unix socketsnormal request can read and write only required stateprotected canary remains unchanged
Capability reductionlow ports, time, network administration, tracingservice starts and completes its health checkremoved privileged operation fails
Firewall or bind changemonitoring, load balancers, cluster peersexpected source reaches the serviceunapproved source cannot reach it
Kernel or ptrace policydebuggers, profilers, crash collection, EDRapproved diagnostic workflow succeedsunrelated same-user process cannot inspect the canary process
Mount hardeningpackage scripts, temporary execution, containersapproved update and workload flow succeeddisallowed execution or write path fails
Audit and log changesdisk capacity, privacy, SIEM parsingexpected event arrives with correct time and identitya 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 claimEvidence requiredNegative controlWhat is not enough
Unnecessary network exposure is removedprocess, socket, interface, firewall, and approved external reachability before and afterconnect from the previously reachable unapproved source and require failuress output alone
Administrative access is narrownamed principals, SSH policy, sudo scope, successful approved login, and denied removed routeuse the removed identity or source route and require rejectiona changed configuration file
The service is containedruntime identity, effective capabilities, writable paths, devices, address families, IPC dependencies, and workload healthattempt the bounded canary action outside the declared authoritya good systemd-analyze security score
Kernel controls match the rolerunning value, persistent source, supported-platform documentation, dependency test, and reboot verificationrepeat the harmless action the setting is meant to restrictcopying a sysctl list from another distribution
Lynis findings are remediatedpreserved baseline report, applicable control ID, root-cause change, post-scan diff, owner, and retestrepeat the original security test from the original sourcefewer warnings or a higher index
Logging is usefulcontrolled event, trusted timestamp, source identity, transport, storage, alert or query result, and retention ownergenerate the canary event and require it to appear end to endauditd installed or a SIEM agent running
Recovery is viabletrusted source, configuration history, isolated credentials, timed rebuild, restored workload, and integrity validationrebuild without depending on the host or identity plane being recovereda 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:

  1. Define the host role, protected authority, and recovery boundary.
  2. Preserve a trusted local baseline and Lynis evidence.
  3. Validate reachable services and administrative identity paths.
  4. Select the few controls that remove the earliest durable edges.
  5. Apply one change family at a time with a rollback path.
  6. Reboot when required and test the intended workload.
  7. Repeat the exact negative security control.
  8. Re-run Lynis and record the diff without treating the score as the conclusion.
  9. Test log visibility and rebuild or restore the disposable host.
  10. 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

TacticTechnique IDTechnique nameDefender verification signal
ExecutionT1059.004Command and Scripting Interpreter: Unix ShellAudit command execution in interactive sessions via auditd
Privilege EscalationT1548.001Abuse Elevation Control: Setuid and Setgidfind / -perm -4000 -type f audits against baseline inventory
PersistenceT1543.002Create or Modify System Process: systemd Servicesystemd-analyze security <unit> sandboxing posture audit
Credential AccessT1003.008OS Credential Dumping: /etc/passwd and /etc/shadowStrict file mode 000 / 640 on /etc/shadow verified via Lynis
Defense EvasionT1070.002Indicator Removal on Host: Clear Linux LogsRemote syslog forwarding + immutable audit log directory

Defender action checklist

Use this actionable checklist during post-assessment remediation:

  1. Enforce Yama ptrace restrictions: Write kernel.yama.ptrace_scope = 2 to /etc/sysctl.d/99-security.conf and apply with sysctl -p.
  2. Harden exposed systemd units: Add ProtectSystem=strict, ProtectHome=yes, and NoNewPrivileges=yes to service drop-ins.
  3. Audit privileged transitions: Add -w /etc/sudoers -p wa -k identity_changes to /etc/audit/rules.d/audit.rules.
  4. Verify workload survivability: Run test suite against target service before signing off on hardening baseline.

Sources reviewed

Sources & freshness

How current is this note?

Sources checkedAugust 25, 2026

The latest source-review, content-update, or publication date is shown.

ReviewAuthor review complete

The author completed a technical review. This does not, by itself, claim lab reproduction.