Introduction
Most Linux hardening guides tell you what to fix, but not where you actually stand today. That gap is exactly where Lynis fills in. Lynis is an open-source security auditing tool that performs an in-depth scan of your Linux system — checking file permissions, kernel parameters, installed services, user accounts, authentication configuration, network settings, and more — then produces an actionable hardening index score.
Unlike vulnerability scanners that need a CVE database, Lynis works offline and tests configuration quality directly on the host. It is widely used by sysadmins, penetration testers, and compliance teams doing CIS Benchmark or STIG gap analysis. Running it takes under two minutes; the report gives you a prioritized list of what to actually fix.
This guide walks through installing Lynis, running your first audit, understanding the output, acting on the findings, and finally scheduling automated scans so your hardening posture stays visible over time.
Prerequisites
Before starting, confirm you have:
- A Linux system (Ubuntu 22.04/24.04, Debian 12, RHEL 9, or Rocky Linux 9 are tested in this guide)
sudoorrootaccess on the target host- Basic shell familiarity
- Optional: git, if you want to run directly from source
Step 1 — Install Lynis
From the official repository (recommended)
CISOfy, the maintainers of Lynis, publish a signed repository for Debian/Ubuntu and RHEL-family systems. Using this repository ensures you always get the latest stable release rather than the older version bundled in distribution repos.
Debian / Ubuntu:
# Import the GPG key
curl -fsSL https://packages.cisofy.com/keys/cisofy-software-public.key \
| sudo gpg --dearmor -o /usr/share/keyrings/cisofy-software.gpg
# Add the repository
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
# Install
sudo apt-get update && sudo apt-get install lynis -yRHEL / Rocky / AlmaLinux:
# Add the COPR or the CISOfy RPM repo
cat <<'EOF' | sudo tee /etc/yum.repos.d/cisofy-lynis.repo
[lynis]
name=CISOfy Lynis
baseurl=https://packages.cisofy.com/community/lynis/rpm/
enabled=1
gpgcheck=1
gpgkey=https://packages.cisofy.com/keys/cisofy-software-rpmsigning-key.asc
EOF
sudo dnf install lynis -yFrom Git (always latest)
If you prefer to run from source — which also lets you verify signatures and pin a specific version:
git clone https://github.com/CISOfy/lynis
cd lynis
# Optionally verify the release tag:
# git tag --verify 3.x.x
sudo ./lynis audit systemVerify the installation
lynis show version
# Expected output: Lynis 3.x.xStep 2 — Run Your First System Audit
Lynis provides several scan modes. The most useful for hardening is audit system, which runs all enabled tests against the local machine.
sudo lynis audit systemThe scan takes roughly 60–120 seconds on a typical system. You will see live output as each test category completes: boot loader, filesystem, kernel, authentication, networking, printers, mail, web server, databases, and so on.
What the output looks like
Each test result is colour-coded:
[OK]— configuration matches best practice[WARNING]— a potential issue worth investigating[SUGGESTION]— hardening improvement possible, not necessarily a risk[FOUND]/[NOT FOUND]— informational discovery
At the end of the scan you will see a summary including the Hardening Index — a score out of 100 based on the ratio of passed tests to applicable tests. A freshly installed minimal server typically scores 55–65. After applying common hardening steps you should reach 75–85. CIS Level 2 hardened systems typically land above 80.
Step 3 — Read the Full Report
The raw scan output scrolls by quickly. The machine-readable report is stored at:
cat /var/log/lynis.log # Full verbose log of every test
cat /var/log/lynis-report.dat # Key-value pairs: easy to grep and diffTo see only warnings and suggestions from the last scan:
# Warnings
grep "^warning\[]" /var/log/lynis-report.dat
# Suggestions
grep "^suggestion\[]" /var/log/lynis-report.dat
# Hardening index
grep "hardening_index" /var/log/lynis-report.datFiltering by category
Every Lynis test has an ID like AUTH-9262 or KRNL-6000. You can look up any test:
lynis show details AUTH-9262This prints the test description, what was checked, and a link to further reading — useful when a warning isn't immediately obvious.
Step 4 — Act on Common Findings
The following findings appear on almost every fresh Linux server. Work through them in order of severity (warnings before suggestions).
4.1 — Harden kernel parameters (sysctl)
Lynis commonly flags missing sysctl values. Add a drop-in file so your settings survive kernel upgrades:
sudo tee /etc/sysctl.d/99-hardening.conf <<'EOF'
# Disable IP forwarding (unless this is a router)
net.ipv4.ip_forward = 0
# Disable ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Enable SYN cookie protection
net.ipv4.tcp_syncookies = 1
# Disable source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
# Log martian packets
net.ipv4.conf.all.log_martians = 1
# Restrict dmesg to root
kernel.dmesg_restrict = 1
# Restrict ptrace to direct children
kernel.yama.ptrace_scope = 1
# Disable magic SysRq
kernel.sysrq = 0
# Protect symlinks and hardlinks
fs.protected_symlinks = 1
fs.protected_hardlinks = 1
# Randomise virtual address space
kernel.randomize_va_space = 2
EOF
sudo sysctl --system4.2 — Secure SSH configuration
Lynis checks /etc/ssh/sshd_config for weak defaults:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf <<'EOF'
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 30
AllowAgentForwarding no
AllowTcpForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
EOF
sudo sshd -t && sudo systemctl reload sshdImportant: Confirm you have key-based access working before setting
PasswordAuthentication no.
4.3 — Set a password policy
On Debian/Ubuntu install libpam-pwquality:
sudo apt-get install libpam-pwquality -y
sudo tee /etc/security/pwquality.conf <<'EOF'
minlen = 14
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
maxrepeat = 3
EOFOn RHEL-family, pam_pwquality is already installed — edit /etc/security/pwquality.conf directly with the same values.
4.4 — Enable and configure a firewall
Lynis checks whether a host firewall is active. On Ubuntu/Debian:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable
sudo ufw status verboseOn RHEL-family:
sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all4.5 — Install and configure auditd
If auditd is not present, Lynis will flag it. See the companion guide Linux Auditd Security Monitoring for a full ruleset. Minimal setup:
sudo apt-get install auditd audispd-plugins -y # Debian/Ubuntu
# or
sudo dnf install audit -y # RHEL-family
sudo systemctl enable --now auditd4.6 — File integrity monitoring (AIDE)
Lynis checks for a file integrity monitor:
sudo apt-get install aide -y
sudo aideinit
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# Schedule daily checks via cron:
echo "0 3 * * * root /usr/bin/aide --check" | sudo tee /etc/cron.d/aide-checkStep 5 — Re-run and Compare
After applying fixes, re-run the audit to verify your score improved and that specific warnings are resolved:
sudo lynis audit system 2>&1 | tee /tmp/lynis-after.txt
# Compare hardening index
grep "hardening_index" /var/log/lynis-report.datYou can also diff the report files between runs:
# Save the first run's report
sudo cp /var/log/lynis-report.dat /var/log/lynis-report-before.dat
# After hardening, diff:
diff /var/log/lynis-report-before.dat /var/log/lynis-report.datStep 6 — Automate Audits and Save Reports
Running Lynis manually is useful for spot-checks; automating it gives you a trend over time and catches configuration drift.
Scheduled cron job
sudo tee /etc/cron.d/lynis-weekly <<'EOF'
# Run Lynis every Sunday at 02:00 AM and archive the report
0 2 * * 0 root /usr/bin/lynis audit system --cronjob > /var/log/lynis-weekly-$(date +\%Y\%m\%d).log 2>&1
EOFThe --cronjob flag suppresses colour codes and interactive pauses, making the output clean for log archival.
Exporting to JSON for SIEM ingestion
Lynis Enterprise has a built-in JSON exporter, but the community edition's report file is easy to convert:
# Quick one-liner to dump key findings as JSON lines
grep "^warning\[\|^suggestion\[" /var/log/lynis-report.dat \
| awk -F'[][]' '{print "{\"type\":\"" $1 "\",\"id\":\"" $2 "\",\"detail\":\"" $3 "\"}"}' \
> /tmp/lynis-findings.jsonlThis can be shipped to Loki, Elasticsearch, or any SIEM that accepts JSON lines.
Step 7 — Custom Profile (Optional)
Lynis supports custom profiles to skip tests that are not relevant to your environment or to apply site-specific settings:
sudo cp /etc/lynis/default.prf /etc/lynis/custom.prfEdit /etc/lynis/custom.prf and add exclusions. For example, to skip printer-related tests on a server:
# Skip CUPS/printing tests
skip-test=PRNT-2307
skip-test=PRNT-2308
# Set a minimum password length expectation
minimum_password_length=14Run with your profile:
sudo lynis audit system --profile /etc/lynis/custom.prfVerification and Testing
After completing the hardening steps, run a final audit and check these three things:
1. Hardening index is above 70:
grep "hardening_index" /var/log/lynis-report.dat
# hardening_index[]=742. No critical SSH warnings remain:
grep "SSH" /var/log/lynis.log | grep "Warning"
# Should return empty or only minor suggestions3. Key controls are confirmed active:
# Firewall
sudo ufw status | grep "Status: active"
# sysctl
sysctl kernel.randomize_va_space # Should be 2
sysctl net.ipv4.tcp_syncookies # Should be 1
# auditd
sudo systemctl is-active auditd # Should be: active
# sshd
sudo sshd -T | grep -E "permitrootlogin|passwordauthentication|x11forwarding"
# permitrootlogin no
# passwordauthentication no
# x11forwarding noTroubleshooting
Lynis exits with "no tests performed":
The scan must run as root or with sudo. Non-privileged users cannot read many system files, so tests are skipped. Always run sudo lynis audit system.
Score did not improve after sysctl changes:
Run sudo sysctl --system to reload all drop-in files, then re-run Lynis. Some parameters require a reboot (kernel-level changes set at boot).
SSH lockout after setting PasswordAuthentication no:
Boot into recovery mode (or use your cloud provider's console/serial port), mount the filesystem, and revert /etc/ssh/sshd_config.d/99-hardening.conf. Always test key-based login in a second terminal before locking passwords.
AIDE initialisation takes a very long time:
This is normal on systems with large filesystems. AIDE hashes every file in scope. You can exclude large directories that change frequently (logs, tmp, var/cache) in /etc/aide/aide.conf:
!/var/log
!/tmp
!/var/cacheLynis reports a warning about an unknown or customised binary:
This is expected if you have compiled software in non-standard paths. Add the binary to your custom profile's bindir list or use skip-test for tests that cannot apply to your environment.
Summary
You now have a repeatable, evidence-based workflow for Linux security auditing with Lynis:
- Install Lynis from the CISOfy repository to stay on the latest release
- Audit with
sudo lynis audit systemand read/var/log/lynis-report.datfor machine-parseable findings - Harden iteratively: kernel sysctl, SSH, password policy, firewall, auditd, file integrity
- Re-scan to confirm your hardening index improves after each change
- Automate weekly cron scans with
--cronjoband archive the output for drift detection
A hardening index is not a compliance certificate — some CIS Benchmark controls are intentionally left manual — but it gives you a fast, objective baseline and a prioritised list of what to tackle next. Run it regularly and treat a score regression as an alert.