{"id":565,"date":"2026-07-04T10:19:31","date_gmt":"2026-07-04T10:19:31","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=565"},"modified":"2026-10-07T22:03:12","modified_gmt":"2026-10-07T22:03:12","slug":"vps-intrusion-detection-fail2ban-rkhunter-aide","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/","title":{"rendered":"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots"},"content":{"rendered":"<div style=\"padding:20px\">\n\n\n<p class=\"wp-block-paragraph\">A firewall and updated packages stop known attacks; they do nothing about a compromised binary or a modified system file. Intrusion detection on a VPS answers three distinct questions: who is currently attacking, is there a rootkit present, and has anything on disk changed since you last trusted it. Fail2ban, RKHunter and AIDE answer those three questions respectively \u2014 and they only work if their output survives a reboot and reaches a human.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fail2ban: Blocking the Obvious, Logging the Rest<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Fail2ban reads logs and adds firewall rules on repeat offenders. The common mistake is tuning it so aggressively that a mistyped password locks you out of your own box. Use <code>findtime<\/code> and <code>maxretry<\/code> deliberately, and always whitelist your own management path.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo cp \/etc\/fail2ban\/jail.conf \/etc\/fail2ban\/jail.local\nsudo tee \/etc\/fail2ban\/jail.local &lt;&lt;'EOF'\n[DEFAULT]\nbantime  = 3600\nfindtime = 600\nmaxretry = 5\nignoreip = 127.0.0.1\/8 ::1 YOUR.MGMT.IP\/32\n\n[sshd]\nenabled = true\nmode    = aggressive\n\n[nginx-http-auth]\nenabled = true\nEOF\nsudo systemctl enable --now fail2ban<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the jails actually load rather than assuming:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo fail2ban-client status\nsudo fail2ban-client status sshd<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The recidive jail matters on internet-facing hosts. It watches Fail2ban&#8217;s own ban history and issues long bans to IPs that return repeatedly \u2014 a single sshd jail only sees one service.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">RKHunter: Scanning for Rootkits and Suspicious State<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">RKHunter checks for known rootkit signatures, hidden files, and unexpected modifications to system binaries. Its weakness is false positives from legitimate package updates, which is exactly why you baseline it on a clean install.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install rkhunter -y\nsudo rkhunter --propupd          # record known-good properties NOW\nsudo rkhunter --check --sk<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>--propupd<\/code> must be re-run after every legitimate system upgrade. Skip that step and every future scan reports the package manager&#8217;s own changes as warnings, training you to ignore real alerts. Schedule the scan and route the output somewhere durable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tee \/etc\/systemd\/system\/rkhunter.service &lt;&lt;'EOF'\n[Unit]\nDescription=RKHunter scan\n[Service]\nType=oneshot\nExecStart=\/usr\/bin\/rkhunter --cronjob --report-warnings-only --rwo\nEOF\nsudo systemctl enable --now rkhunter.timer<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">AIDE: Detecting Change You Did Not Make<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">AIDE builds a cryptographic database of file hashes, permissions and timestamps, then compares against it. The value is in the baseline: an alert that a file changed is noise unless you know it should not have. Initialize on a freshly hardened system:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install aide -y\nsudo aideinit\nsudo mv \/var\/lib\/aide\/aide.db.new \/var\/lib\/aide\/aide.db\nsudo aide --check<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On a small VPS, a full scan competes for disk I\/O with your workloads. Constrain AIDE to the paths that matter instead of the whole filesystem:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Watch <code>\/etc<\/code>, <code>\/bin<\/code>, <code>\/sbin<\/code>, <code>\/usr\/bin<\/code>, <code>\/usr\/sbin<\/code> \u2014 where persistence lives.<\/li>\n<li>Exclude <code>\/var\/log<\/code>, <code>\/var\/cache<\/code>, and application upload directories that change constantly.<\/li>\n<li>Run nightly with <code>nice<\/code> and <code>ionice<\/code> so the scan never spikes user-facing latency.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Alerting: The Detection That Fails Silently Is Useless<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">All three tools write to logs that nobody reads. Make sure output reaches you, and that the path is tested. A minimal approach is a wrapper that emails or posts to a webhook only when a scan reports findings, keeping noise near zero so real alerts stand out.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Tool<\/th><th>Answers<\/th><th>Cadence<\/th><th>Disk cost<\/th><\/tr><\/thead><tbody><tr><td>Fail2ban<\/td><td>Who is attacking now?<\/td><td>Continuous<\/td><td>Negligible<\/td><\/tr><tr><td>RKHunter<\/td><td>Is a known rootkit present?<\/td><td>Nightly<\/td><td>Low<\/td><\/tr><tr><td>AIDE<\/td><td>Did files change unexpectedly?<\/td><td>Nightly<\/td><td>Moderate<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Correlating the Three Signals<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The real value of running all three detection layers is correlation. A change detected by AIDE in <code>\/usr\/sbin<\/code>, combined with an unexpected process listening on a new port and a burst of outbound connections in the firewall log, is a coherent incident. Any one of those alone is ambiguous; together they tell a story. Keep the timestamps aligned \u2014 journald, AIDE and Fail2ban all log in local time, so a drifting clock makes correlation unreliable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On a compromised host, the attacker&#8217;s first move is often to disable or tamper with these very tools. That is why integrity of the detection stack itself matters. AIDE watches <code>\/usr\/bin<\/code> and <code>\/etc<\/code> where Fail2ban&#8217;s filters live; if someone edits a filter to ignore a specific IP, the next nightly AIDE run should catch the modified file hash. This mutual coverage is the point of stacking tools rather than trusting any single one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Surviving Reboots and Restores<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Detection state is only useful if it persists. Confirm every service is enabled, not just started, and that databases live outside volatile paths:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl is-enabled fail2ban rkhunter.timer aide.timer\nls -l \/var\/lib\/aide\/aide.db \/var\/lib\/rkhunter\/db<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then test the recovery path: reboot, confirm jails are active, and confirm AIDE can still read its baseline. A detection stack that breaks silently after a reboot is worse than none, because you believe you are covered when you are not. If you are auditing a server you have not touched in months, pair this with <a href=\"https:\/\/virtualserversvps.com\/#providers\">a provider-focused security review<\/a> to check the infrastructure layer too, since host-level protections complement \u2014 but do not replace \u2014 what runs on the instance.<\/p>\n\n\n\n<h2>Putting It Together<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Baseline RKHunter with <code>--propupd<\/code> and AIDE with <code>aideinit<\/code> on a clean build.<\/li>\n<li>Configure Fail2ban with a management-IP whitelist and the recidive jail.<\/li>\n<li>Schedule nightly scans with I\/O priority limits.<\/li>\n<li>Route warnings to a channel a human actually monitors.<\/li>\n<li>Re-baseline after every legitimate upgrade and test survivability after reboot.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Run on a schedule and re-baselined honestly, these three tools turn &#8220;I think the server is clean&#8221; into an answer with evidence behind it. Choosing an instance with the disk headroom to run integrity scans without hurting production is part of the design \u2014 see how <a href=\"https:\/\/virtualserversvps.com\/\">these hosts compare<\/a> before scaling the workload.<\/p>\n\n\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>A firewall and updated packages stop known attacks; they do nothing about a compromised binary or a modified system file. Intrusion detection on a VPS answers three distinct questions: who&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":2,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-565","post","type-post","status-publish","format-standard","hentry","category-security-compliance"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots - Virtual Servers VPS Blog<\/title>\n<meta name=\"description\" content=\"A firewall and updated packages stop known attacks; they do nothing about a compromised binary or a modified system file. Intrusion detection on a VPS\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots\" \/>\n<meta property=\"og:description\" content=\"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-04T10:19:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-07T22:03:12+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/\",\"name\":\"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-07-04T10:19:31+00:00\",\"dateModified\":\"2026-10-07T22:03:12+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"description\":\"A firewall and updated packages stop known attacks; they do nothing about a compromised binary or a modified system file. Intrusion detection on a VPS\",\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots - Virtual Servers VPS Blog","description":"A firewall and updated packages stop known attacks; they do nothing about a compromised binary or a modified system file. Intrusion detection on a VPS","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/","og_locale":"en_US","og_type":"article","og_title":"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots","og_description":"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots","og_url":"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-07-04T10:19:31+00:00","article_modified_time":"2026-10-07T22:03:12+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/","url":"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/","name":"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-07-04T10:19:31+00:00","dateModified":"2026-10-07T22:03:12+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"description":"A firewall and updated packages stop known attacks; they do nothing about a compromised binary or a modified system file. Intrusion detection on a VPS","breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/vps-intrusion-detection-fail2ban-rkhunter-aide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Intrusion Detection on a VPS: Fail2ban, AIDE and Rootkit Scans That Survive Reboots"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/565","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=565"}],"version-history":[{"count":2,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/565\/revisions"}],"predecessor-version":[{"id":1329,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/565\/revisions\/1329"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}