Back to Blog
Security24 September 2024Michael Hettwer5 min read

File integrity monitoring with AIDE

How we set up file integrity monitoring: a lean AIDE baseline, a daily diff with disciplined follow-up, and a database stored elsewhere.

Most incident evidence hangs on one question: what changed, and when? Package managers report what they did themselves, logs report what services announced, but for the quiet changes nobody ordered, a separate instrument is needed. AIDE is that instrument: a tool that records a hash-based state of the filesystem and checks it against the running state.

The model in short form

On the first run, AIDE builds a database of checksums for the files the configuration selects: which directories, which attributes, which hash methods. Every later run compares the current state against that database and reports deviations: new files, changed files, deleted files, altered permissions. The usefulness stands or falls with two decisions that both happen before the first real incident: what gets watched, and where the database lives.

The watch rules are set deliberately lean. System directories, configuration areas, binary paths: those are the places where unauthorized changes matter. Temporary directories, caches and logs stay out, because they generate permanent noise that smothers the real leads. A rule that watches everything is a rule nobody reads anymore.

The database is the trust anchor

The real crux of integrity monitoring is more philosophical than technical: if an attacker fully controls the system, they can also tamper with the database describing the intended state. So the database does not live on the monitored server itself but somewhere a server-side attacker cannot reach: a separate storage system, a writable medium that gets sealed after writing, or simply a copy outside. On the servers we manage, the reference database sits outside the monitored machine and the check run loads it from there rather than building it locally.

The daily rhythm that holds

Integrity monitoring becomes useful when its result gets read. The rhythm is unspectacular: a run happens daily, the result lands as a report in the logs or as an alert in the monitoring; the post Managing Linux server logs properly covers how we lay that log basis. The report has two possible outcomes, and only two: the change is explained, and then it gets recorded into the database, or it is unexplained, and then it is an incident with an investigation. Updating the database is the step that demands discipline: it happens after clarification, never before, and with a note recording the reason.

The most common failure in practice is silent chasing: because reports nag, the database gets updated automatically, and with that the monitoring ends as a machine that approves every state as correct. An integrity system that never objects has no function.

The limits, stated honestly

AIDE sees file states, not processes and not kernel memory. Attack patterns that fully control the system at evaluation time can bypass the check itself; the tool is an informant, not a shield. Its value lies in provability: after an incident, we know which files were changed and when it became visible. That is the difference between an investigation with leads and one without.

Second, the tool is only as good as the preparation of the baseline: an intended state recorded during an ongoing problem blesses the broken state. The recording belongs in a state known to be orderly, and the recording time belongs in the log.

Getting started in four steps

  • Set the watch rules lean: system areas, configurations, binary paths; nothing that churns constantly in normal operation anyway.
  • Record the baseline in an orderly state and document the moment.
  • Store the database outside the monitored server and build the check run so it loads from there.
  • Set up the daily run, feed the reports into logs and monitoring, and establish the follow-up as the normal case.

What the reports contain in practice

A report carrying only a list of changed files rarely gets read; a report that puts the change into its context does. The practical upgrade is therefore small: the report includes the classification of whether the change falls into a package event. Laying the previous day's package lists beside it makes it obvious at a glance that a report entry matches yesterday's update, and the remaining entries are the actual work. The reduction from report to report often turns a hundred lines into five, and five is a size somebody actually reads.

The second practical addition concerns keeping the reports themselves. An archive of the daily reports, even when each one was uneventful, is gold during an incident: it answers the question of when a certain state first became visible without anybody reconstructing from memory. A month of retention covers daily needs, three months for systems where incidents actually get investigated. The cost is one directory and one retention rule, the same mechanism the log management post of this blog describes anyway.

A thought on the honesty of the baseline deserves a place, because it decides the reliability of the whole system: the database is a promise, and a promise recorded during a week of disorder promises the disorder. In practice that reads: the baseline is not recorded between two update waves but after a state whose orderliness somebody verified. The effort is an hour on a quiet day, and it pays back every time a report appears and the question becomes whether the reported change is new or was present since the recording. Exactly that question decides the value of every report, and it is only as good as the state the database came from.

Those four steps leave you with an instrument that answers the next "what changed there" question with data instead of speculation. If you want integrity monitoring established as part of your servers' hardening, the security hardening and audits page describes the matching service, and the contact page is the fastest way to reach us.

Sources

  • AIDE project, documentation, https://aide.github.io/ (accessed 2026-11-03)
  • The aide(1) and aide.conf(5) manual pages ship with the package; no permanently stable public URL exists for the manual pages, and checking the concrete page is noted for integration day.