This guide covers file integrity monitoring and audit logging on Linux using auditd, the kernel’s native audit subsystem: what to audit, how to forward it to Secure60, and — the part most deployments discover late — how to keep the volume it produces under control.
There are two documented ways to get file-change and audit events off a Linux host. Secure60 recommends auditd.
| auditd (recommended) | Auditbeat (legacy) | |
|---|---|---|
| Software to install | Already present on RHEL, Rocky, and most distributions; one package on Ubuntu | A third-party agent to package, deploy, patch, and keep current |
| Coverage | Kernel-level syscall auditing, file and directory watches, identity and privilege changes | File integrity module plus a subset of audit rules |
| Delivery | Existing syslog path — no new network flow | Logstash protocol to the collector on port 5044 |
| Rule format | auditctl rules, the format Linux auditors and benchmarks are written in |
Its own YAML, translated to audit rules |
| Where it fits | Every new deployment | Estates that already run it |
auditd needs no third-party agent, uses the syslog path already opened for Linux server logs, and its rule syntax is the one CIS benchmarks and audit standards are written against, so the ruleset you build is the evidence an assessor asks for.
If you already run Auditbeat, the FIM and Audit logs guide documents it and it continues to work. Existing deployments can stay as they are; new hosts should use auditd.
Most enterprise distributions ship auditd. Where it is missing, install it along with the dispatcher plugins:
# Ubuntu / Debian
sudo apt install -y auditd audispd-plugins
# RHEL / Rocky / Alma
sudo dnf install -y audit
Enable the syslog plugin so audit records leave the audit log and enter the system log stream:
sudo nano /etc/audit/plugins.d/syslog.conf
# set: active = yes
sudo systemctl restart auditd
On older releases this file lives at /etc/audisp/plugins.d/syslog.conf.
systemctl restart auditd is refused on some distributions because auditd is started by the kernel rather than by systemd. Use service auditd restart there, and confirm with auditctl -s that the daemon is enabled and its process ID has changed.
Audit records reach the journal via the syslog plugin, so rsyslog needs the journal input loaded. Add it to your Secure60 forwarding file (/etc/rsyslog.d/10-tls-forward.conf):
module(load="imjournal")
$DefaultNetstreamDriver gtls
$ActionSendStreamDriverMode 1
$ActionSendStreamDriverAuthMode anon
*.* @@<S60_COLLECTOR_IP_ADDRESS>:6514
sudo systemctl restart rsyslog
The full rsyslog setup, including the plaintext option and TLS certificates, is in the Linux Server - Integration Guide.
Create /etc/audit/rules.d/50-secure60.rules. The baseline below covers the four things that matter for detection: what ran, who exists, who can escalate, and what will run again after a reboot.
## Secure60 - baseline audit rules
## Place at: /etc/audit/rules.d/50-secure60.rules
############################
# 1) Process execution
# See "Managing the volume" below before deploying this fleet-wide.
############################
-a always,exit -F arch=b64 -S execve -k s60_exec
-a always,exit -F arch=b32 -S execve -k s60_exec
############################
# 2) Identity and group management
# Captures useradd/usermod/groupadd/passwd changes via file writes.
############################
-w /etc/passwd -p wa -k s60_identity
-w /etc/shadow -p wa -k s60_identity
-w /etc/group -p wa -k s60_identity
-w /etc/gshadow -p wa -k s60_identity
############################
# 3) Privilege configuration changes
############################
-w /etc/sudoers -p wa -k s60_privcfg
-w /etc/sudoers.d/ -p wa -k s60_privcfg
############################
# 4) SSH and authentication control changes
############################
-w /etc/ssh/sshd_config -p wa -k s60_authcfg
-w /etc/pam.d/ -p wa -k s60_authcfg
############################
# 5) Persistence mechanisms
############################
-w /etc/crontab -p wa -k s60_persist
-w /etc/cron.d/ -p wa -k s60_persist
-w /etc/cron.hourly/ -p wa -k s60_persist
-w /etc/cron.daily/ -p wa -k s60_persist
-w /etc/cron.weekly/ -p wa -k s60_persist
-w /etc/cron.monthly/ -p wa -k s60_persist
-w /var/spool/cron/ -p wa -k s60_persist
-w /etc/systemd/system/ -p wa -k s60_persist
-w /usr/lib/systemd/system/ -p wa -k s60_persist
-w /lib/systemd/system/ -p wa -k s60_persist
-w /etc/profile -p wa -k s60_persist
-w /etc/bashrc -p wa -k s60_persist
-w /etc/profile.d/ -p wa -k s60_persist
Load and validate:
sudo augenrules --load
sudo auditctl -l
augenrules merges every file in rules.d into one ruleset, so an error is reported against the merged output — check the source files if it complains.
A watch is a path, a permission mask, and a key:
-w /etc/nginx/ -p wa -k s60_fim_web
-w /opt/payments/config -p wa -k s60_fim_app
-w /usr/local/bin/ -p wa -k s60_fim_bin
w catches writes and a catches attribute changes. Adding r (read) to a busy directory produces an event for every file access, which is rarely worth the volume. Watch configuration and binary directories rather than data directories — a changing /var/lib/mysql carries no signal.
Read this before rolling the baseline out to a fleet. The execve rules audit every process launch, on both the 64-bit and 32-bit interfaces, with no filtering. On a typical server that rule pair is the largest source of events on the host — larger than the application logs beside it — and every one of those events is ingest volume you pay for. Measure it before committing to a volume estimate.
Each process launch produces a SYSCALL record and an EXECVE record as a pair, plus auxiliary records unless you exclude them.
-a always,exclude -F msgtype=PATH
-a always,exclude -F msgtype=CWD
-a always,exclude -F msgtype=EOE
-a always,exclude -F msgtype=PROCTITLE
PROCTITLE is frequently left enabled. It repeats, hex-encoded, the command line the EXECVE record already carries, so exclude it unless you decode it.
These exclusions do not affect the core execution telemetry — SYSCALL (executable path, user context, success or failure) and EXECVE (command-line arguments) still arrive in full.
If volume is still the constraint, narrow what you audit — in rough order of benefit per unit of effort:
Drop the 32-bit rule on 64-bit-only hosts. If nothing on the host runs 32-bit binaries, arch=b32 produces nothing of value:
-a always,exit -F arch=b64 -S execve -k s60_exec
Exclude execs with no logged-in user behind them. Daemons and system services run with an unset audit UID. Excluding them keeps every human-initiated command and removes most of the background churn:
-a never,exit -F arch=b64 -S execve -F auid=unset
On older audit versions, write -F auid=4294967295 instead of auid=unset.
Exclude specific noisy binaries. Monitoring agents, backup jobs, and health checks are usually the top few entries:
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/node_exporter
-a never,exit -F arch=b64 -S execve -F exe=/usr/lib/nagios/plugins/check_disk
Audit privileged execution only. The narrowest useful option — everything running as root, nothing else:
-a always,exit -F arch=b64 -S execve -F euid=0 -k s60_exec_root
Order matters: never rules must appear before the always rule they are meant to suppress, because the kernel evaluates the list in order and stops at the first match.
In Search, query for the host and use Analytics to group by host_name over 24 hours, then compare per-host event counts before and after a rule change. A step change appears within minutes of augenrules --load. See Search.
Process execution auditing on a busy server is commonly the dominant share of that host’s ingest. When estimating volume for a new deployment, enable the baseline on one representative host, measure a full day, and multiply that figure across the fleet rather than using a general estimate.
Open Search and confirm records are arriving:
message_text:audit
You should see SYSCALL and EXECVE records tagged with the keys you set (s60_exec, s60_identity, s60_persist). Searching for a key confirms that a specific rule is live:
| Query | What it shows |
|---|---|
message_text:s60_identity |
Changes to /etc/passwd, /etc/shadow, and group files |
message_text:s60_privcfg |
Changes to sudo configuration |
message_text:s60_persist |
New cron jobs, systemd units, and profile scripts |
message_text:s60_exec |
Process execution across the estate |
To extract structured fields — the executable, the invoking user, the audit key as their own searchable fields rather than text — add a Log Parser under Integrations → Secure60 Collector → Log Parsers. See Collectors for the parser workflow, and Common Information Model for the field names to map onto (process_name, process_path, user_name, file_path, operation = process-create or file-write).