Audit a Linux Server with Lynis
Run Lynis on any Linux server, interpret the hardening index and findings, apply the most impactful fixes, and automate weekly audits with a systemd timer.
Before you start
- ▸Root or sudo access on the target server
- ▸Outbound HTTPS access to packages.cisofy.com for repository setup
- ▸Basic familiarity with sshd_config and sysctl parameters
- ▸A snapshot or backup taken before applying hardening changes
Lynis is an open-source security auditing tool that interrogates a running system and produces a hardening index score alongside prioritised findings. It works agentlessly, reads the live filesystem, and covers everything from kernel parameters and PAM configuration to file permissions and installed packages. Running it takes two minutes; understanding and acting on the output is where the real work begins.
Install Lynis
Use the official CISOfy repository where possible — the distro-packaged version is often months behind and may produce different scores against the current ruleset.
Debian / Ubuntu
curl -fsSL https://packages.cisofy.com/keys/cisofy-software-public.key \
| sudo gpg --dearmor -o /usr/share/keyrings/cisofy-software.gpg
echo "deb [signed-by=/usr/share/keyrings/cisofy-software.gpg] \
https://packages.cisofy.com/community/lynis/deb/ stable main" \
| sudo tee /etc/apt/sources.list.d/cisofy-lynis.list
sudo apt update && sudo apt install lynis -y
Fedora / RHEL / Rocky
sudo rpm --import https://packages.cisofy.com/keys/cisofy-software-public.key
sudo tee /etc/yum.repos.d/cisofy-lynis.repo <<'EOF'
[lynis]
name=CISOfy Lynis
baseurl=https://packages.cisofy.com/community/lynis/rpm/
enabled=1
gpgcheck=1
gpgkey=https://packages.cisofy.com/keys/cisofy-software-public.key
EOF
sudo dnf install lynis -y
Arch Linux
sudo pacman -S lynis
Confirm the version after install — anything below 3.0 is outdated.
lynis show version
Run a System Audit
Lynis must run as root to read privileged files. The --auditor flag embeds your name in the report; omit it if you prefer.
sudo lynis audit system --auditor "your-name"
The scan takes 60–180 seconds. Do not interrupt it. You will see category banners scroll past — Kernel, Authentication, File Systems, Networking, and so on — each populated with OK, WARNING, or SUGGESTION markers.
Useful runtime flags
--quick— suppress the five-second pause between sections (useful in scripts).--no-colors— plain output, good for piping to a log file.--report-file /path/to/report.dat— write a machine-readable report alongside the human output.--profile /etc/lynis/custom.prf— load a custom profile (covered below).
Reading the Output and Score
When the scan finishes, Lynis prints a summary block. The most important line is the Hardening index:
Hardening index : 62 [############ ]
Tests performed : 258
Plugins enabled : 0
The index runs from 0 to 100. Out-of-the-box servers typically score between 55 and 70. A production internet-facing server should target 80+. The score is relative to the tests Lynis actually ran — adding plugins or enabling enterprise checks will change the denominator.
Findings breakdown
Scroll up in the terminal (or pipe the run through tee) to see categorised findings. Three markers matter:
- WARNING — exploitable or directly non-compliant condition. Fix these first.
- SUGGESTION — best-practice improvement. Address these after warnings are clear.
- OK — test passed; no action needed.
Every warning and suggestion references a test ID such as AUTH-9286. Use that ID to look up the full rationale:
sudo lynis show details AUTH-9286
Log and report files
Two files are written after every run:
/var/log/lynis.log— verbose per-test output; useful for debugging why a test failed./var/log/lynis-report.dat— key=value pairs suitable for SIEM ingestion or diffing between runs.
grep 'warning\|suggestion' /var/log/lynis-report.dat
Applying Fixes
Work through warnings before suggestions. The following examples represent the most common findings on a freshly provisioned server.
SSH hardening (SSH-7408, SSH-7412)
sudo nano /etc/ssh/sshd_config
Set or confirm these values:
PermitRootLogin no
PasswordAuthentication no
X11Forwarding no
AllowTcpForwarding no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
sudo systemctl reload sshd
Kernel hardening via sysctl (KRNL-6000)
sudo tee /etc/sysctl.d/99-hardening.conf <<'EOF'
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
EOF
sudo sysctl --system
Password policy (AUTH-9286)
Install and configure libpam-pwquality (Debian/Ubuntu) or libpwquality (Fedora/RHEL):
# Debian / Ubuntu
sudo apt install libpam-pwquality -y
sudo sed -i 's/^# minlen/minlen/' /etc/security/pwquality.conf
sudo sed -i 's/minlen.*/minlen = 12/' /etc/security/pwquality.conf
# Fedora / RHEL
sudo dnf install libpwquality -y
sudo sed -i 's/# minlen/minlen/' /etc/security/pwquality.conf
sudo sed -i 's/minlen.*/minlen = 12/' /etc/security/pwquality.conf
File permissions (FILE-7524)
Lynis often flags world-writable files or incorrect umask values. Set a stricter default umask system-wide:
echo 'umask 027' | sudo tee /etc/profile.d/hardening-umask.sh
Using Custom Profiles
A profile (.prf file) tells Lynis which tests to skip, which to enforce, and what your environment's accepted values are. This is essential for avoiding false positives — for example, a database server intentionally running without a firewall because it sits behind a load balancer.
Create a profile
sudo cp /etc/lynis/default.prf /etc/lynis/server-production.prf
sudo nano /etc/lynis/server-production.prf
Common directives inside the profile:
# Skip a specific test entirely
skip-test=FIRE-4512
# Override the minimum password length check
minimum-password-length=14
# Tell Lynis which package manager is authoritative (avoids some false positives)
package-manager-binary=/usr/bin/dpkg
# Set the expected firewall state
firewall-expected-status=enabled
Run with your custom profile:
sudo lynis audit system --profile /etc/lynis/server-production.prf
Commit your profile to version control alongside your Ansible playbooks or Terraform configuration so infrastructure changes stay auditable.
Automate Recurring Audits
Use a systemd timer rather than a cron job so you get proper logging via journald and dependency management.
sudo tee /etc/systemd/system/lynis-audit.service <<'EOF'
[Unit]
Description=Lynis security audit
[Service]
Type=oneshot
ExecStart=/usr/bin/lynis audit system --quick --no-colors \
--profile /etc/lynis/server-production.prf
EOF
sudo tee /etc/systemd/system/lynis-audit.timer <<'EOF'
[Unit]
Description=Run Lynis audit weekly
[Timer]
OnCalendar=Mon 03:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now lynis-audit.timer
Verify Improvement
After applying fixes, re-run the audit and compare scores:
sudo lynis audit system --quick 2>&1 | tee /tmp/lynis-after.txt
grep 'Hardening index' /tmp/lynis-after.txt
For a diff between two report files, use the key=value format:
diff /var/log/lynis-report.dat.bak /var/log/lynis-report.dat
Keep a timestamped archive of lynis-report.dat after each weekly run so you can track the score over time and catch regressions introduced by package updates.
Troubleshooting
- Score unexpectedly drops after an OS update — Lynis may have been updated with new tests. Run
lynis show testsbefore and after to see if the test count changed. - Test shows WARNING but the fix is already applied — Check
/var/log/lynis.logfor the exact file or parameter Lynis inspected. The test may look in a location your config isn't using (e.g., distro overrides in/etc/ssh/sshd_config.d/). - Permission denied errors during scan — Lynis must run as root or with
sudo. Running as a sudoer without a full root shell can miss some privileged file checks. - Plugin tests all skipped — Plugins require the Lynis enterprise edition. Community edition ships zero plugins; the skip messages are expected.
Frequently asked questions
- Does Lynis make any changes to the system during a scan?
- No. Lynis is read-only during a standard audit. It inspects files and configuration but never modifies anything. All remediation is manual and intentional.
- What is a good hardening index target for a production server?
- A freshly built server typically scores 55–70. Aim for 80 or above on internet-facing production systems. Scores above 90 are achievable but usually require trade-offs like disabling features you may legitimately need.
- Can Lynis audit a remote server over SSH?
- Not directly — Lynis is designed to run on the system it is auditing. For remote auditing, copy Lynis to the target and run it there, or use an orchestration tool like Ansible to push and execute it.
- Why do some tests say SKIPPED even when the relevant software is installed?
- A test is skipped when Lynis cannot locate the binary or configuration file it expects. Check /var/log/lynis.log for the specific path it searched and confirm your installation matches.
- Is the community edition sufficient, or do I need the enterprise version?
- The community edition covers the full test suite and is adequate for most teams. The enterprise version adds compliance reporting (PCI-DSS, HIPAA, ISO 27001 templates), plugins, and a central dashboard for managing multiple hosts.
Related guides
Manage Secrets with Ansible Vault
Encrypt Ansible secrets with AES-256 using ansible-vault: encrypt files and inline vars, automate with password files, and isolate group-level secrets with vault IDs.
AppArmor Explained
Learn how AppArmor profiles work, how to switch between enforce and complain mode, create new profiles, and diagnose access denials on Ubuntu, Debian, and Arch.
Apply CIS Benchmarks with OpenSCAP
Use OpenSCAP and scap-security-guide to evaluate, report on, and remediate Linux systems against CIS Benchmarks — covering install, eval, and automation.
How to Audit a Linux System with auditd
Set up auditd on Linux to track file access, syscalls, and privilege use. Covers persistent rules, file watches, ausearch, and aureport across major distros.