Security

Linux Security: Using aide for File Integrity Monitoring on VPS

AIDE builds a checksum database of your system files and reports anything that changed. This guide installs it, creates a baseline, tunes the rules and schedules daily checks on a Linux VPS.

AdvancedLinux server6 min read

AIDE file integrity monitoring gives you a checksum database of the files that matter on your server, then tells you exactly what changed since that database was built. It will not stop an intruder, but it is one of the fastest ways to notice that /etc/passwd, sshd_config or a system binary has been touched without your knowledge. This guide installs AIDE on a Linux VPS, builds a clean baseline, tunes the rules so you are not flooded with noise, and schedules a daily check.

Before you start

You need:

  • Root or sudo access to a Linux VPS running Ubuntu 22.04/24.04, Debian 12, AlmaLinux 8–9 or Rocky 8–9.
  • A few hundred MB of free disk space. The database grows with the number of files you watch.
  • A rough idea of what matters on this host: usually /etc, /bin, /sbin, /usr/bin, /usr/sbin, /lib and /boot.

Warning: AIDE detects changes, it does not prevent them. Build your baseline on a server you believe is clean. If you already suspect a compromise, rebuild the host first and preserve evidence before you start.

Install AIDE

On Ubuntu and Debian:

Bash
sudo apt update
sudo apt install -y aide aide-common

On AlmaLinux and Rocky:

Bash
sudo dnf install -y aide

Confirm the binary and version:

Bash
aide --version

The package ships a default configuration that already watches most of the system. You will narrow it down in a moment.

Build the baseline database

The first run hashes every file in scope and writes a database. On a typical VPS this takes a few minutes and produces noticeable disk I/O, so run it off-peak.

On Ubuntu and Debian, aideinit handles the whole process, including moving the new database into place:

Bash
sudo aideinit -y

On AlmaLinux and Rocky, run the init step yourself and then promote the database:

Bash
sudo aide --init
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

Tip: Keep a copy of the finished database somewhere off the server, for example in a private object store. If the server is compromised, an attacker with root can rewrite the local database to hide their tracks.

Configure AIDE file integrity monitoring rules

AIDE rules are built from single-letter flags. The common ones are p (permissions), i (inode), n (link count), u (user), g (group), s (size), m (mtime), c (ctime) and a hash such as sha256. A rule name groups these flags, and you apply it to a path.

Debian and Ubuntu read /etc/aide/aide.conf and then every file in /etc/aide/aide.conf.d/. Add a drop-in file so your changes survive package upgrades:

INI
# /etc/aide/aide.conf.d/99-local
/etc/hosts Full
/etc/ssh/sshd_config Full
/etc/passwd Full
/etc/shadow Full
/etc/sudoers Full
/etc/crontab Full
/etc/systemd/system Full

!/var/log
!/var/spool
!/var/cache
!/var/tmp
!/run
!/proc
!/sys

On AlmaLinux and Rocky the same rules go directly into /etc/aide.conf, which uses the same syntax. The leading ! excludes a path, and = can be used to define your own rule names.

Note: Logs, caches, mail spools and PID files change constantly. Leaving them in scope produces a report nobody reads, which defeats the point. Exclude them and watch the configuration that generates them instead.

Run a check

A check compares the live filesystem against the database and prints a report. On Debian and Ubuntu use the packaged wrapper, which handles the database copy correctly:

Bash
sudo aide.wrapper --check

On AlmaLinux and Rocky:

Bash
sudo aide --check

The report lists added, removed and changed entries, with the specific attributes that differ. AIDE also returns an exit code as a bitmask: 0 means nothing changed, while other values indicate added, removed or modified files. That is what makes it easy to wire into monitoring.

Update the database after legitimate changes

Every package upgrade, config edit or new user changes files. Once you have read the report and confirmed the changes are yours, promote a new baseline:

Bash
sudo aide.wrapper --update

On AlmaLinux and Rocky:

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

Warning: Never update the database without reading the report first. Promoting a database that already contains an attacker's changes turns your monitoring into a rubber stamp.

Schedule daily checks

Debian and Ubuntu ship a daily cron job, but a systemd timer gives you clearer logs and better scheduling control. Create the service:

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

[Service]
Type=oneshot
ExecStart=/usr/bin/aide.wrapper --check
Nice=10
IOSchedulingClass=idle

Then the timer:

INI
# /etc/systemd/system/aide-check.timer
[Unit]
Description=Daily AIDE check

[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=30m

[Install]
WantedBy=timers.target

Enable it and confirm the next run time:

Bash
sudo systemctl daemon-reload
sudo systemctl enable --now aide-check.timer
systemctl list-timers aide-check.timer

Output goes to the journal, so read it with:

Bash
journalctl -u aide-check.service --since "2 days ago"

Check it works

Create a file in a watched directory and run a check:

Bash
sudo touch /etc/aide-test-file
sudo aide.wrapper --check

The report should list /etc/aide-test-file as an added entry. Remove it, run --update to refresh the database, and confirm the next check comes back clean:

Bash
sudo rm /etc/aide-test-file
sudo aide.wrapper --update
sudo aide.wrapper --check

Troubleshooting

  • "Couldn't open file /var/lib/aide/aide.db for reading" — the baseline was never promoted. Run sudo aideinit -y on Debian/Ubuntu, or move aide.db.new.gz to aide.db.gz on the RHEL family.
  • Hundreds of entries under /var/log, /var/spool or /run — those paths are still in scope. Add ! exclusions to your drop-in config and rebuild the baseline.
  • Permission denied on /root or /etc/shadow — AIDE is not running as root. Run it with sudo or from a root shell.
  • The check takes a long time and saturates disk I/O — narrow the scope to configuration and binaries, and keep Nice and IOSchedulingClass=idle in the service unit so the check yields to real work.
  • The report is full of changes right after a package update — expected. Read the entries, confirm they match the packages you installed, then run --update.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.