How to Detect Changed Files With AIDE or Tripwire Safely
Detect changed files with AIDE: build the baseline database, run checks, read the report, tune rules, update after upgrades and protect the database.

If an attacker replaces /usr/bin/ssh or adds a line to /etc/ld.so.preload, the system looks normal and the only evidence is that a file is different. File integrity monitoring turns that into an alert. AIDE, the Advanced Intrusion Detection Environment, is the standard open-source tool, and Tripwire the older one with the same idea. This post sets it up on a Debian server and explains the care that makes it useful. It complements audit rules, which record who changed a file, where AIDE records what. The commands assume AIDE 0.19 on Debian 13.
Install and build the baseline
sudo apt install aide aide-common
sudo aideinit
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.dbaideinit reads the rules in /etc/aide/aide.conf.d/ and hashes every file they select, which takes some minutes on a large system. The result is aide.db.new; copying it to aide.db makes it the reference. The value of the whole exercise depends on this step happening on a clean machine. A baseline taken from a system that is already compromised records the compromise as normal.
Run a check
sudo aide --checkAIDE found differences between database and filesystem!!
Summary:
Total number of entries: 112934
Added entries: 2
Removed entries: 0
Changed entries: 3
Changed entries:
f > ... mc..H.. : /usr/bin/ssh
f ... .C...... : /etc/ssh/sshd_config
The flags on each line say what changed: m mtime, c ctime, C checksum, H hash, p permissions, u owner and so on. A changed checksum on a binary you did not update is the line to investigate. Compare with the package manager's view: sudo debsums -c or dpkg -V openssh-client on Debian, or rpm -Va on Red Hat systems, tells you whether a file differs from what the package shipped.
Tune the rules
# skip volatile areas
!/var/log
!/var/cache
!/var/lib/docker
!/home/.*/\.cache
# watch these closely
/etc p+i+n+u+g+s+m+c+sha256
/usr/bin p+i+n+u+g+s+m+c+sha256
/usr/sbin p+i+n+u+g+s+m+c+sha256
Rules say which attributes to track for which paths. Lines starting with ! exclude a path. Without exclusions, logs and caches make every report huge, and people stop reading. A good report is empty most days. Start with the places an attacker must touch: binaries, /etc, boot files and cron directories.
Schedule and update
sudo systemctl enable --now dailyaidecheck.timer
sudo aide --update
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.dbDebian ships a daily check that mails the result to root when there are differences. After a planned change, such as a package upgrade, review the report, then update the database so that it becomes the new baseline. Updating without reading means accepting whatever changed. On a system that upgrades often, expect a daily report; some teams run the update inside the same maintenance script that installs upgrades, after checking.
Protect the database
An intruder with root can edit aide.db to hide changes, and the check would pass. Keep a copy elsewhere: after each update, compute sha256sum /var/lib/aide/aide.db and store it off the host, or ship the database to read-only storage and compare during the check. Running the check from a trusted external system over SSH, or from a read-only mount, makes it harder to defeat. The AIDE binary itself and its configuration need the same protection.
Where this does not apply
On containers and frequently rebuilt hosts, compare images at build time instead. Systems that change constantly, such as development machines, produce too much noise to be useful. AIDE detects change, not cause or time; combine it with checking who changed a file, and respond with the compromise playbook when the result is real.
What the database holds and why it matters
AIDE reads a configuration of paths and the attributes to watch, then walks those paths and stores, for each file, a record of permissions, ownership, size, timestamps and cryptographic hashes. That record is the baseline. A later check walks the same paths again and reports every difference: added files, removed files and changed ones, with the attributes that changed. The value is that it tells you what changed, regardless of how, which is different from an audit rule that tells you who did something while it happened. It detects a modified system binary, a new setuid file, an altered configuration, a new file in a directory that should never change. It does not prevent anything, and it cannot tell a legitimate change from a malicious one. A package upgrade changes hundreds of files, and the report after one is long, so the useful workflow is to run a check before an upgrade, upgrade, then update the baseline after reviewing.
The record is only as trustworthy as the machine it sits on. An attacker with root who knows AIDE is installed can edit the database, so the baseline needs protection, discussed below.
Choosing what to watch
The configuration defines groups of attributes and applies them to paths. Strict groups with hashes suit the files that should not change, such as /bin, /sbin, /lib, /usr, /boot and /etc. Looser groups, with only permissions and ownership, suit places where content changes but access should not, and exclusions with a leading exclamation mark remove noisy places entirely: /var/log, /var/cache, /proc, /tmp and mail spools. The balance is between coverage and noise. A report with fifty irrelevant lines each day trains people to ignore it, while a report that lists only meaningful changes gets read. Start with a narrow set, such as system directories and key configuration, run it for a week, add exclusions for the noise you see, and widen coverage gradually. Keep the configuration in version control, and deploy it with the rest of your machine setup.
Hashing is the expensive part, and a full run on a large system can take minutes to hours and uses disk bandwidth. Run it at a quiet time with low priority, using nice and ionice.
Scheduling, updating and protecting the baseline
Run the check daily from a timer, mail or ship the report to a place a person reads, and alert on a non-empty report for the locked-down paths. Distribution packages ship a wrapper and a cron job or timer with defaults, and customizing them is better than writing your own. After reviewing a legitimate change, update the database with aide --update, which writes a new file that you move into place, and keep the previous one for comparison. Store a copy of the database and of the configuration, with a checksum, somewhere the machine cannot write: read-only media, another host, or a write-once bucket. Compare the live database with the off-host copy during the check, so tampering is noticed. A baseline taken after a compromise records the compromise as normal, so build the first one on a freshly installed, trusted system, and rebuild from scratch when you cannot vouch for the state of the machine.
Reading a report without drowning
An AIDE report starts with a summary of added, removed and changed counts, followed by the details. Read the summary first: a count of zero on a locked-down system is the good outcome, and a few changed files after a package upgrade is expected. Look at the changed entries for the attribute that differs. A change in timestamps only is usually harmless, a change in the hash of a binary needs an explanation, and a change in permissions or ownership of a system file deserves attention. Match the changes to the package manager's log to explain each, and investigate whatever has no matching update.
See the AIDE project and the aide.conf manual.


