GICT knowledge base
How to Track Configuration File Changes in Linux with auditd
Published
An unexpected configuration change can break a website or weaken a server’s security. Linux Audit records filesystem activity alongside the account, executable, and time involved, helping you trace changes without relying on shell history. A focused audit rule is especially useful for settings edited by several administrators or deployment tools.
Requirements
Use an Ubuntu 24.04 server with sudo access. If you need a server, an InterServer Linux VPS provides an environment where you can manage audit rules. Containers generally cannot manage the host’s audit subsystem; run these commands on the server itself.
The example monitors /etc/site-config/. Substitute your application’s configuration directory consistently. Auditing starts when the rule becomes active; it cannot reconstruct earlier changes.
1. Install and inspect the audit service
$ sudo apt update
$ sudo apt install auditd
$ sudo systemctl enable --now auditd
$ sudo systemctl is-active auditd
$ sudo auditctl -s
$ sudo auditctl -l
The service should report active. In the status output, enabled 1 means auditing is enabled and rules can change. enabled 2 means the rules are immutable until reboot. Coordinate changes with the server’s administrator rather than attempting to disable that protection.
Review existing rules before adding another. Do not clear them with auditctl -D: they may cover authentication, administrative commands, or other security requirements. Check that the lost counter is zero; lost events make an audit trail incomplete.
Also note the pid value: a running audit daemon should have a nonzero process ID. If installation fails to start the service, inspect sudo journalctl -u auditd -n 50 --no-pager before continuing. Missing kernel support or restricted virtualization cannot be repaired by adding more filesystem rules.
2. Choose a narrow configuration directory
For a standalone example, create the directory:
$ sudo install -d -m 0755 /etc/site-config
$ sudo nano /etc/site-config/app.conf
Add this harmless setting:
maintenance=false
For an existing application, use its real configuration directory instead of creating another one. The directory must exist before you load its rule. Avoid watching all of /etc unless you genuinely need that volume of events.
A directory rule follows activity beneath the selected directory, including temporary files and rename-based replacements. That matters because many editors save by replacing the original file. Separate mounted filesystems beneath it need their own coverage; the recursive directory match does not cross mount boundaries.
3. Add persistent rules
Open a new, uniquely named rules file:
$ sudo nano /etc/audit/rules.d/70-site-config.rules
For an x86-64 server, add:
-a always,exit -F arch=b64 -F dir=/etc/site-config/ -F perm=wa -k site_config
-a always,exit -F arch=b32 -F dir=/etc/site-config/ -F perm=wa -k site_config
The two lines cover native 64-bit and compatible 32-bit system calls. On a 64-bit ARM server, use the b64 line only. The w permission selects writes; a selects attribute changes such as permissions and ownership. Reads are excluded, keeping routine configuration loading out of this trail.
The key site_config labels matching events for later searches. Use a distinct key for each monitoring purpose. There is deliberately no login-user filter: changes made by background services should appear too.
Load and inspect the rules:
Preserve required runtime-only rules in persistent configuration first: the existing ruleset may contain a reset directive that clears them during loading.
$ sudo augenrules --load
$ sudo auditctl -l
Confirm that the active list contains the directory, perm=wa, and site_config. Saving the file alone does not activate it. augenrules assembles the files under rules.d into the persistent ruleset and attempts to load it; read its output for errors, especially on immutable systems.
After the next scheduled reboot, check systemctl is-active auditd and the active rule list again. Persistent configuration is useful only if the service loads it successfully. Avoid editing the generated /etc/audit/audit.rules directly, because a later regeneration can replace those edits.
4. Confirm that an edit is recorded
Open the example file again and change maintenance=false to maintenance=true:
$ sudo nano /etc/site-config/app.conf
$ sudo ausearch --input-logs -k site_config -ts recent -i
recent searches the last ten minutes. Look for the configuration path and a successful write or replacement event. An editor can create several events, so multiple records do not necessarily mean several people edited the file.
Records sharing the same msg=audit(...:EVENT_ID) belong to one event. Read the group together:
- SYSCALL:
success, the system call,exe, and process identifiers explain the attempted operation. - PATH:
nameandnametypeidentify affected paths, including files created or deleted during a replacement. - Identity:
auididentifies the original login account;uidandeuiddescribe the process’s user credentials. - PROCTITLE: records command-line information when available.
The -i option resolves numeric values into readable names. After sudo, the effective user may be root while auid still identifies the account that logged in. An unset login identity commonly indicates a process without an assigned login session. A shared account identifies that account, not necessarily an individual person.
Check success=yes before treating an attempted operation as completed. The executable tells you which program accessed the file, while the path records explain its targets. A shell redirect may appear under the shell executable rather than the command whose text you expected. Preserve the complete event when investigating, not just a matching filename line.
5. Search and retain useful events
Search today’s matching events:
$ sudo ausearch --input-logs -k site_config -ts today -i
Narrow the results to one file:
$ sudo ausearch --input-logs -k site_config -f /etc/site-config/app.conf -ts today -i
Use the event number from a result to inspect its complete record group:
$ sudo ausearch --input-logs -a EVENT_ID -ts today -i
Replace EVENT_ID with the numeric identifier. Keep the time window narrow because event numbers can recur across boots. For rename-based saves, also review the broader key search to include temporary paths.
Audit logs record operations, not before-and-after file contents. Use configuration backups or version control when you need to compare exact changes. Retention depends on /etc/audit/auditd.conf, including rotation and space-handling settings. Protect the logs: paths and command arguments can reveal sensitive operational details.
The usual log location is /var/log/audit/audit.log. --input-logs explicitly selects configured logs, including when commands run without an interactive terminal.
These local records are not tamper-proof against a sufficiently privileged attacker. For incident investigations, combine them with independently retained logs and access records rather than treating one local file as conclusive evidence.
6. Troubleshoot or remove the rule
If no events appear, check the active rules, directory spelling, search window, and lost counter. Existing exclusion rules, including never,task, can prevent the expected records. Review those rules with their owner instead of removing them indiscriminately. A successful service status does not prove your particular directory is monitored.
To retire this monitoring, remove only its dedicated persistent file:
$ sudo unlink /etc/audit/rules.d/70-site-config.rules
$ sudo augenrules --load
$ sudo auditctl -l
If the matching rules remain active on a mutable x86-64 system, remove them explicitly:
$ sudo auditctl -d always,exit -F arch=b64 -F dir=/etc/site-config/ -F perm=wa -k site_config
$ sudo auditctl -d always,exit -F arch=b32 -F dir=/etc/site-config/ -F perm=wa -k site_config
On ARM, omit the second command. Immutable systems require a planned reboot to apply removal. Confirm that only the intended rules disappeared; deleting a rule does not delete the existing audit records.
Related guides
Plan a Safe Redis-to-Valkey Migration
Plan a Redis-to-Valkey migration: check version compatibility, rehearse recovery, stop writers for cutover and protect against lost writes during rollback.
Linux AdministrationHow to Restrict an SSH Key to One Command
Restrict an SSH key to one command with authorized_keys options. Protect the command and check that unwanted shell and forwarding access are denied.
Linux AdministrationHow to Schedule Tasks with systemd Timers
Schedule tasks with systemd timers. Verify service results separately from timer status, test missed-run handling and use an explicit UTC schedule.
Linux AdministrationHow to Restrict a Linux Service with systemd Security Settings
Restrict a Linux service with systemd drop-ins, a dedicated account, read-only paths, private temporary storage, and controlled writable directories.
