Cyber Security

File Integrity Monitoring with AIDE — Know What Changed on Your Home Server

File Integrity Monitoring with AIDE — Know What Changed on Your Home Server

A home server can look perfectly healthy while an important file has quietly changed. A modified SSH configuration, an unexpected binary, or a rewritten web file may not crash a service, so ordinary uptime monitoring will happily keep showing green. File Integrity Monitoring gives us a different kind of signal: not “is the machine running?” but “is the machine still the one I intended to run?”

In this guide, we will set up AIDE (Advanced Intrusion Detection Environment) on Debian or Ubuntu, build a trustworthy baseline, run automatic checks with a systemd timer, and decide what to do when a change appears. The goal is not to treat every changed byte as an emergency. It is to make meaningful changes visible before they disappear into the background noise of daily administration.

What File Integrity Monitoring Actually Sees

AIDE walks through selected paths and records attributes such as file type, permissions, owner, size, modification time, and cryptographic hashes. On a later run, it compares the current filesystem with that database. The report lists files that were added, removed, or changed.

Think of the baseline as a photograph of a workshop at closing time. The photograph cannot tell us who moved a screwdriver or why, but it makes the movement visible the next morning. In the same way, AIDE does not understand whether a package upgrade was legitimate or whether an attacker replaced a command. It supplies evidence; context turns that evidence into a decision.

This distinction matters. AIDE is not antivirus, real-time blocking, backup, or a complete intrusion detection system. An attacker with root access may try to alter both AIDE and its local database. File Integrity Monitoring is therefore one layer in a broader setup that still needs patching, least privilege, useful logs, and recoverable backups.

Install AIDE and Understand the Configuration

On Debian and Ubuntu, install the packaged version and inspect its configuration directory:

sudo apt update
sudo apt install aide
sudo ls -la /etc/aide/aide.conf.d/

Debian assembles the effective configuration from snippets under /etc/aide/aide.conf.d/. Existing package rules are a useful starting point because they already account for many system paths. A rule associates a path with a group of attributes. Hash-heavy rules are appropriate for executables and configuration, while fast-changing runtime directories usually need exclusions.

Before adding anything, identify what is valuable on this particular server. For a small web host, that might be /etc, application code under /var/www, system binaries, systemd units, and a few deployment scripts. Monitoring everything without thought often creates a report so noisy that nobody reads it.

Add Focused Rules for a Home Server

Create a local snippet so custom policy stays separate from package-managed files:

sudo nano /etc/aide/aide.conf.d/99_aide_local

A practical starting policy could look like this:

/etc                         CONTENT_EX
/usr/local/bin               CONTENT_EX
/var/www                     CONTENT_EX
/etc/systemd/system          CONTENT_EX

!/var/www/.*/cache
!/var/www/.*/storage/logs
!/var/www/.*/public/uploads
!/var/lib/docker
!/var/log
!/run
!/tmp

CONTENT_EX tracks metadata and file content with strong hashes. The exclusions remove paths where legitimate writes are frequent or where scanning is expensive. Adapt them to the actual application layout: uploads may deserve separate monitoring for unexpected executable files, but hashing every user image on every run may offer little value.

Exclusions are not declarations that a directory is safe. They are a noise budget. Like a smoke detector placed beside a toaster, a badly positioned rule can produce so many harmless alarms that the important alarm is ignored. Start with critical, relatively stable paths and expand only when reports remain understandable.

Build the First Baseline Carefully

The initial database is the reference for every future comparison, so create it only when the server is in a known-good state. Apply pending security updates, inspect active services, and check for unexplained processes or recent logins first. Building a baseline on an already compromised host merely records the compromise as normal.

sudo aideinit
sudo aide --check

Depending on the distribution package, aideinit creates a new database and installs it in the expected location. The first check should report no unexplained difference. If it reports many changes immediately, do not blindly accept them. Confirm whether a scheduled package job, deployment, or application write happened between initialization and verification.

Keep an additional protected copy of the baseline outside the server. An offline disk or a backup repository with immutable snapshots is better than another writable file on the same machine. Record its checksum too:

sudo sha256sum /var/lib/aide/aide.db.gz
sudo cp /var/lib/aide/aide.db.gz /mnt/offline-backup/aide.db.gz

Run Checks Automatically with systemd

A security check that depends on memory eventually stops happening. Create a service that runs AIDE and lets systemd record the output in the journal:

# /etc/systemd/system/aide-check.service
[Unit]
Description=Daily AIDE file integrity check

[Service]
Type=oneshot
ExecStart=/usr/bin/aide --check

Then create a timer:

# /etc/systemd/system/aide-check.timer
[Unit]
Description=Run AIDE file integrity check daily

[Timer]
OnCalendar=*-*-* 03:20:00
RandomizedDelaySec=20m
Persistent=true

[Install]
WantedBy=timers.target

Enable it and perform one manual test:

sudo systemctl daemon-reload
sudo systemctl enable --now aide-check.timer
sudo systemctl start aide-check.service
sudo systemctl status aide-check.service
sudo journalctl -u aide-check.service

Persistent=true runs a missed check after a powered-off server returns. RandomizedDelaySec avoids stacking every maintenance task at exactly the same minute. For a home server, daily checks are often a sensible balance, although exposed or high-change systems may need a different schedule.

Read a Report Without Panicking

AIDE summarizes added, removed, and changed entries, then shows which attributes differ. A changed configuration after your own edit is expected. A new executable in /usr/local/bin, an altered SSH key, or a web entry point changed outside a deployment window deserves immediate attention.

Classify each finding with three questions: Was there an approved change? Does the timestamp match that work? Can package records, deployment history, or logs explain the exact file? On Debian, package verification can add context:

sudo dpkg -V
sudo journalctl --since "24 hours ago"
sudo stat /path/to/suspicious-file
sudo sha256sum /path/to/suspicious-file

Do not update the baseline simply to make a warning disappear. That is like erasing a dashboard warning light without opening the hood. First explain the difference. If compromise is plausible, preserve logs, isolate the host from untrusted networks, rotate exposed credentials from a clean device, and restore from known-good sources where appropriate.

Update the Baseline After Legitimate Changes

Operating systems and applications legitimately change. After an upgrade or deployment, review the AIDE report against the work you performed. Only then promote the new database:

sudo aide --update
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
sudo aide --check

Paths can differ slightly between distributions, so verify the database locations in the effective AIDE configuration before moving files. Make baseline updates part of the maintenance checklist, not an automatic command appended after every package upgrade. Automatic acceptance removes the review step that gives File Integrity Monitoring its value.

Also tune the policy over time. Exclude a generated cache only after confirming its role; add a newly deployed configuration directory as soon as it becomes important. The best policy is not the longest one. It is the smallest policy that reliably protects assets you would struggle to rebuild or explain.

A Small Sensor with a Useful Question

AIDE will not stop every attack, and it cannot prove that a server is clean. What it does well is ask a disciplined question every day: what changed? With a carefully created baseline, focused rules, off-host copies, and a timer whose results are actually reviewed, that question becomes a practical security control rather than another installed package.

Start with the paths you understand, trigger one harmless test change, and practice reading the result before relying on the system. If you already use File Integrity Monitoring on a home server, share which directories create useful signals and which exclusions keep your reports readable.