AIDE (Advanced Intrusion Detection Environment) is a host-based intrusion detection tool that builds a cryptographic baseline of your filesystem and alerts you whenever files are added, removed, or modified. On RHEL 8 it is available in the base repositories and integrates cleanly with cron and email for automated daily checks. Unlike network-based intrusion detection, AIDE operates entirely on the local filesystem, making it effective at detecting unauthorized changes to binaries, configuration files, and system libraries even when network traffic is encrypted. This tutorial covers installing AIDE, writing targeted rules for critical directories, initializing the database, scheduling daily checks, and maintaining the baseline after legitimate system updates.
Prerequisites
- RHEL 8 server with root or sudo access
- A working MTA (
postfixorsendmail) configured to deliver local mail, or a relay to an external SMTP server mailxormuttfor sending email from scripts- Sufficient disk space for the AIDE database (typically 50–200 MB depending on filesystem size)
Step 1 — Install AIDE
AIDE is available in the default RHEL 8 AppStream or BaseOS repository. Install it with dnf along with mailx for email notifications.
sudo dnf install -y aide mailx
# Confirm the installed version
aide --version
# Review default configuration location
ls -l /etc/aide.conf
Step 2 — Write a Targeted AIDE Configuration
Replace the default configuration with a targeted ruleset that monitors the directories most likely to be tampered with during an intrusion. Use SHA-512 checksums alongside permissions, inode, owner, group, size, and modification time. Exclude volatile files that change legitimately so the daily report does not produce false positives.
sudo cp /etc/aide.conf /etc/aide.conf.bak
sudo tee /etc/aide.conf > /dev/null <<'EOF'
# AIDE configuration — RHEL 8
# Database paths
database_in=file:/var/lib/aide/aide.db.gz
database_out=file:/var/lib/aide/aide.db.new.gz
database_new=file:/var/lib/aide/aide.db.new.gz
# Log file
report_url=file:/var/log/aide/aide.log
report_url=stdout
# Verbose level (0-255; 20 = show changed/new/removed files)
verbose=20
# SHA-512 + metadata rule
SECURE = p+i+n+u+g+s+m+sha512
# Monitor critical system binaries
/bin SECURE
/sbin SECURE
/usr/bin SECURE
/usr/sbin SECURE
/usr/lib SECURE
/usr/lib64 SECURE
# Monitor critical configuration files
/etc SECURE
!/etc/mtab
!/etc/resolv.conf
!/etc/adjtime
!/etc/hostname.1
!/etc/NetworkManager/system-connections
!/etc/cups/subscriptions.conf
!/etc/cups/subscriptions.conf.O
!/etc/aliases.db
!/etc/postfix/prng_exch
!/etc/lvm/archive
!/etc/lvm/backup
# Monitor boot files
/boot SECURE
# Monitor cron jobs
/var/spool/cron SECURE
EOF
# Create log directory
sudo mkdir -p /var/log/aide /var/lib/aide
sudo chmod 700 /var/log/aide /var/lib/aide
Step 3 — Initialize the AIDE Database
The first run builds the baseline database by hashing every file matched by the configuration. This can take several minutes depending on the size of monitored directories. The database must be initialized on a known-good system state — ideally immediately after a fresh OS installation or patching cycle.
# Initialize the database (this may take 5-15 minutes)
sudo aide --init
# Move the newly created database into the active position
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
# Verify the database exists and has reasonable size
ls -lh /var/lib/aide/aide.db.gz
# Run a first check against the baseline to confirm zero differences
sudo aide --check | tail -20
Step 4 — Create a Check Script with Email Notification
Write a script that runs an AIDE check, filters the report for meaningful changes, and emails the results if any modifications are detected. The script suppresses emails when there are no changes to avoid alert fatigue.
sudo tee /usr/local/bin/aide-check.sh > /dev/null < "$REPORT" 2>&1
EXIT_CODE=$?
# Exit code 0 = no changes, 1 = changes found, 2+ = error
if [[ $EXIT_CODE -eq 0 ]]; then
echo "$(date) - AIDE check passed. No changes detected." >> /var/log/aide/aide-summary.log
exit 0
fi
# Count changed, new, and removed files
CHANGED=$(grep -c "^Changed:" "$REPORT" 2>/dev/null || true)
NEW=$(grep -c "^New:" "$REPORT" 2>/dev/null || true)
REMOVED=$(grep -c "^Removed:" "$REPORT" 2>/dev/null || true)
# Build summary
SUMMARY="Changed: $CHANGED New: $NEW Removed: $REMOVED"
echo "$(date) - AIDE check FAILED. $SUMMARY" >> /var/log/aide/aide-summary.log
# Send email with the full report
{
echo "AIDE detected filesystem changes on $(hostname) at $(date)."
echo ""
echo "Summary: $SUMMARY"
echo ""
echo "--- Full Report ---"
cat "$REPORT"
} | mailx -s "$SUBJECT" "$EMAIL"
exit $EXIT_CODE
EOF
sudo chmod +x /usr/local/bin/aide-check.sh
# Test the script (should show no changes on a clean system)
sudo /usr/local/bin/aide-check.sh
echo "Exit code: $?"
Step 5 — Schedule Daily Checks with Cron
Add a cron job that runs the check script every morning. Running it at a consistent time makes anomalies easier to pinpoint by correlating timestamps with change management records.
# Schedule the AIDE check at 04:00 daily
sudo tee /etc/cron.d/aide-check > /dev/null <<'EOF'
# AIDE daily integrity check
0 4 * * * root /usr/local/bin/aide-check.sh
EOF
# Verify the cron entry
cat /etc/cron.d/aide-check
# Verify mail delivery works (sends a test message to root)
echo "AIDE cron mail test" | mailx -s "AIDE mail test" root
sudo tail -f /var/spool/mail/root
Step 6 — Maintain the Baseline After System Updates
After applying dnf updates or making intentional configuration changes, update the AIDE database to reflect the new known-good state. Failing to do so will cause every subsequent check to flag the updated files as changes.
# After running 'dnf update -y' or making known config changes:
# Step 1 — Review the current report to confirm changes are expected
sudo aide --check 2>&1 | grep -E "^(Changed|New|Removed):" | head -40
# Step 2 — Re-initialize the database to capture the new baseline
sudo aide --update
# Step 3 — Move the updated database into the active position
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
# Step 4 — Confirm the next check shows zero differences
sudo aide --check
echo "Exit code after baseline update: $?"
# Archive a timestamped copy of the baseline for audit purposes
sudo cp /var/lib/aide/aide.db.gz
/var/lib/aide/aide.db.$(date +%Y%m%d).gz
ls -lh /var/lib/aide/aide.db.*.gz
Conclusion
AIDE is now configured on RHEL 8 with SHA-512 checksum monitoring across your critical system directories, a daily cron job that emails a report when changes are detected, and a clear workflow for updating the baseline after legitimate system changes. By excluding volatile files like /etc/mtab and /etc/resolv.conf, the check produces low-noise output focused on genuinely suspicious modifications. Store a copy of the initial aide.db.gz baseline off-server so it cannot be modified by an attacker who gains root access.
Next steps: How to Configure auditd for Security Event Logging on RHEL 8, How to Harden SSH Configuration on RHEL 8, and How to Configure SELinux Policies on RHEL 8.