Linux server security audit checklist
A Linux server audit checks that the system is patched, that only expected services and accounts exist, that SSH and the firewall are locked down, and that logs and backups work. Use a benchmark such as a CIS Benchmark as the reference and a scanner such as Lynis to do the first pass.
Start from a published baseline
Pick one written standard and audit against it, so each finding has a reference.
- The Center for Internet Security describes its CIS Benchmarks as prescriptive configuration recommendations for vendor product families. Benchmarks exist for Ubuntu Linux, Debian Linux and Red Hat Enterprise Linux, among others.
- NIST SP 800-123, Guide to General Server Security, covers how to select, implement and maintain security controls for servers that provide network services.
- NIST SP 800-92, Guide to Computer Security Log Management, covers building and running log management.
Automated tools save time on the first pass. Lynis audits the host with lynis audit system. OpenSCAP checks a system against SCAP content with its oscap command.
The checklist
The last column shows what server_audit_notify.sh covers. "Lynis" means the script runs Lynis, which reports on the area, and copies its warnings into the email.
| Area | What to check | Command | Script |
|---|---|---|---|
| Security updates | Pending updates, automatic security updates on | apt list --upgradable or dnf check-update | No |
| SSH | Root login, password login, key login | sshd -T | Lynis |
| Failed logins | Repeated failures from the same address | lastb -n 20 | Yes |
| Accounts | Only root has UID 0, sudo group members | awk -F: '$3 == 0' /etc/passwd | Lynis |
| Listening services | Every open port has an owner and a reason | ss -tulpn | Yes |
| Firewall | Default deny for incoming traffic | nft list ruleset | Lynis |
| SUID files | No unexpected set-user-ID programs | find / -xdev -perm -4000 -type f | Lynis |
| Disk space | Room for logs and updates | df -h | Yes |
| Logging | Logs kept, rotated and sent off the host | journalctl --disk-usage | Lynis |
| Audit trail | auditd running with rules loaded | auditctl -s | Lynis |
| Time | Clock synchronized, so log times line up | timedatectl | No |
| Backups | Recent backup exists and a restore was tested | Depends on your tool | No |
Security updates
Updates close publicly known security bugs, so check them first. List what is pending with apt list --upgradable on Debian and Ubuntu or dnf check-update on Red Hat style systems.
Ubuntu applies security updates on its own through the unattended-upgrades package. The Ubuntu Server documentation says the schedule lives in /etc/apt/apt.conf.d/20auto-upgrades, the behavior in /etc/apt/apt.conf.d/50unattended-upgrades, and the logs in /var/log/unattended-upgrades.
SSH configuration
Run sshd -T as root to print the settings the SSH server uses, after all include files. Compare these lines with your policy. The defaults below come from the OpenSSH sshd_config manual; distributions can change them.
| Setting | OpenSSH default | Common hardening choice |
|---|---|---|
PermitRootLogin | prohibit-password | no |
PasswordAuthentication | yes | no, once keys work for every user |
PubkeyAuthentication | yes | yes |
MaxAuthTries | 6 | A lower number such as 3 |
Then look at failed attempts. lastb shows failed logins recorded in /var/log/btmp, and journalctl -u ssh (or -u sshd on Red Hat style systems) shows the SSH server log.
Accounts and privileges
List accounts with UID 0 using awk -F: '$3 == 0' /etc/passwd; only root should appear. Check who can use sudo with getent group sudo wheel. Remove accounts for people who left, and lock service accounts that never log in.
Open ports and firewall
ss -tulpn lists every listening TCP and UDP socket and the process behind it. For each line, you should know which service it is and whether it needs to accept connections from the internet. Then confirm the firewall matches: nft list ruleset, ufw status verbose or firewall-cmd --list-all, depending on the system.
Logs and audit trail
Logs only help if they exist when you need them. Check that the journal or syslog keeps enough history with journalctl --disk-usage, that log rotation works, and that copies go to another host, since an attacker with root can edit local files.
The Linux Audit System records system calls and events from privileged programs. Its project README describes each event as recording when it happened, who did it, what it acted on, and whether it succeeded. Check that it runs with auditctl -s and list the loaded rules with auditctl -l.
Repeat the audit on a schedule
One audit shows the state on one day. Schedule the scan, keep the results, and compare runs so that new warnings stand out. The install guide shows how to run server_audit_notify.sh daily with cron or a systemd timer and keep the reports for a set number of days.