$linuxjunkies
>

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.

AdvancedUbuntuDebianFedoraArch12 min readUpdated June 7, 2026

Before you start

  • Root or sudo access on the target system
  • Familiarity with a terminal text editor (nano, vim)
  • Sufficient disk space for audit logs (recommend at least 1 GB dedicated)
  • Basic understanding of Linux syscalls and file permissions

The Linux Audit subsystem gives you a kernel-level record of security-relevant events: file access, system calls, authentication attempts, privilege escalation, and more. auditd is the userspace daemon that collects those records and writes them to disk. Unlike log scrapers that work at the application layer, audit hooks sit inside the kernel itself, making them much harder for an attacker to silently bypass. This guide covers installing and starting auditd, writing persistent rules, watching specific files and directories, and extracting useful information from the audit log.

Install and Enable auditd

Most server-oriented distributions ship auditd by default. Check before installing.

Debian / Ubuntu

sudo apt update && sudo apt install -y auditd audispd-plugins

Fedora / RHEL / Rocky

sudo dnf install -y audit audit-libs

Arch Linux

sudo pacman -S audit

Enable and start the service with systemd:

sudo systemctl enable --now auditd

Verify it is running:

sudo systemctl status auditd

On RHEL 9 / Rocky 9 and newer, auditd is protected by systemd's RefuseManualStop; use service auditd stop or the provided init wrapper if you ever need to stop it during testing.

Understanding the Configuration File

The main configuration lives at /etc/audit/auditd.conf. The defaults are sane for most systems, but two settings are worth reviewing immediately:

  • max_log_file_action — controls what happens when a log file reaches max_log_file MB. Set to ROTATE for production systems; SUSPEND stops auditing rather than dropping records, useful for high-security environments.
  • space_left_action and admin_space_left_action — define reactions when disk space runs low. SYSLOG is the minimum; HALT enforces a strict "no audit, no run" policy.
sudo grep -E 'max_log_file|space_left' /etc/audit/auditd.conf

Writing Audit Rules

Rules are managed in two ways: transiently with auditctl (lost on reboot) or persistently in /etc/audit/rules.d/. Always write persistent rules; use auditctl only for live testing. The augenrules tool compiles everything under rules.d/ into /etc/audit/audit.rules and loads it.

Rule Syntax Primer

  • -a action,list — appends a rule; common lists are always,exit and never,exit.
  • -S syscall — matches a specific syscall by name or number.
  • -F field=value — filters (UID, GID, path, architecture, etc.).
  • -k key — tags records with a searchable keyword.
  • -w path / -p permissions — file/directory watch shorthand (r read, w write, x execute, a attribute change).

Create a Rules File

sudo nano /etc/audit/rules.d/50-local.rules

A practical starting ruleset:

# Remove any existing rules
-D

# Increase the buffers to handle bursts
-b 8192

# Failure mode: 1 = log failures, 2 = kernel panic (high-security only)
-f 1

# Watch critical authentication files
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers

# Watch SSH configuration
-w /etc/ssh/sshd_config -p wa -k sshd_config

# Log all uses of privileged commands
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=4294967295 -k root_commands

# Monitor changes to audit configuration itself
-w /etc/audit/ -p wa -k audit_config
-w /sbin/auditctl -p x -k audit_tools
-w /sbin/auditd -p x -k audit_tools

# Log time changes (potential log tampering indicator)
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time_change
-a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime -k time_change

# Detect module loading/unloading
-a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k kernel_modules

# Lock the ruleset (comment out during development)
-e 2

Warning: -e 2 makes the ruleset immutable until the next reboot. Comment it out while you are still testing; uncomment it for production.

Load the rules:

sudo augenrules --load

Confirm they loaded cleanly:

sudo auditctl -l

Watching Files and Directories

File watches are the fastest way to answer "who touched this file?" Add them with -w either in a rules file or transiently for quick investigation:

# Transient: watch /var/www/html for any writes or attribute changes
sudo auditctl -w /var/www/html -p wa -k webroot

Directory watches are recursive only one level deep by default in older kernels. On kernels 6.6+ with fanotify-backed audit watches, behavior may differ — check uname -r and your distribution's kernel notes. For deep trees on older kernels, add watches to each subdirectory or use an inotify-based tool alongside auditd.

# Persistent: watch a specific application config
echo '-w /etc/nginx/nginx.conf -p rwa -k nginx_config' | sudo tee -a /etc/audit/rules.d/50-local.rules
sudo augenrules --load

Reading the Audit Log

Raw logs land in /var/log/audit/audit.log. They are readable but dense. Use ausearch and aureport for human-usable output.

ausearch — Event-Level Queries

# Search by key tag
sudo ausearch -k identity --interpret

# Search by a specific user (by login UID)
sudo ausearch -ua 1001 --interpret

# Search events in the last 30 minutes
sudo ausearch -ts recent --interpret

# Search for failed events only
sudo ausearch --success no --interpret

The --interpret (or -i) flag translates numeric UIDs, syscall numbers, and architecture codes into human-readable strings. Always use it when reading output manually.

aureport — Summary Reports

# High-level summary of all event types
sudo aureport

# Summary of authentication events
sudo aureport --auth

# Failed authentication attempts
sudo aureport --auth --failed

# All executable events
sudo aureport --executable

# Events tagged with a specific key
sudo aureport --key --summary

Parsing a Raw Record

When you need the raw log, each record looks similar to this (output will vary):

sudo tail -f /var/log/audit/audit.log | grep 'key="identity"'

A typical record contains: type (event class), msg (timestamp and serial), syscall, pid, uid/auid (real UID vs. login UID), comm (command name), exe (full path), and key. The auid field survives sudo and su transitions, making it the reliable field for attribution.

Verification

Trigger a known event and confirm it appears in the log:

# Trigger the identity watch
sudo touch /etc/passwd

# Search for it
sudo ausearch -k identity -ts recent -i

You should see a record with type=SYSCALL referencing open or openat, the path /etc/passwd, and your login UID in auid. If the search returns nothing, run sudo auditctl -l to confirm the rule is loaded, and check sudo auditctl -s for the enabled/backlog status.

Troubleshooting

No events appearing

  • Run sudo auditctl -s and check that enabled is 1 or 2. If it shows 0, the subsystem is disabled at the kernel level (rare; check kernel config with grep AUDIT /boot/config-$(uname -r)).
  • Confirm augenrules --load exited cleanly; a bad rule silently fails to load the entire file on some versions. Check journalctl -u auditd for parsing errors.

Log fills disk rapidly

  • The -a always,exit -S execve rule on busy systems generates enormous volume. Narrow it with additional -F filters (e.g., -F euid=0) or move it to a separate rules file behind a higher number so you can disable it quickly.
  • Adjust max_log_file and num_logs in auditd.conf, or integrate with systemd-journal via the audisp-syslog plugin and let journald handle rotation.

Rules lost after reboot

Rules placed only via auditctl do not persist. Always write them to /etc/audit/rules.d/ and run sudo augenrules --load. Also confirm the auditd service is enabled: sudo systemctl is-enabled auditd.

tested on:Ubuntu 24.04Debian 12Fedora 40Rocky 9

Frequently asked questions

What is the difference between auid and uid in audit records?
uid is the effective user ID at the time of the syscall, which changes when you run sudo or su. auid (audit UID) is stamped at login time and persists across those transitions, making it the reliable field for tracing an action back to the original human user.
Will auditd catch actions taken by the root user?
Yes. Kernel-level audit hooks fire regardless of privilege level. Root can clear the log after the fact if given the opportunity, which is why shipping logs off-host to a SIEM in real time is recommended for high-security environments.
Does -w on a directory watch files recursively?
On most production kernels (pre-6.6), directory watches cover only the immediate directory and its direct children, not deeper subdirectories. For deep trees, add explicit watches per subdirectory or supplement with an inotify-based solution.
What does -e 2 actually do and can it be reversed without rebooting?
-e 2 sets the kernel audit subsystem to immutable mode; no rule changes or configuration modifications are permitted until the next reboot. It cannot be reversed at runtime by any user, including root. Only use it once your ruleset is stable and tested.
How do I reduce audit log noise from high-frequency syscalls?
Narrow rules with additional -F filters such as euid=0, auid>=1000, or specific exe paths. You can also prepend a -a never,exit rule for known noisy processes before the broad catch-all rule, since the kernel evaluates rules top-to-bottom and stops at the first match.

Related guides