SYSTEMS OPERATIONAL
VPS

VPS Malware Scanning: ClamAV and rkhunter Setup Guide

Getwebup 6 min read

If your VPS doesn't run cPanel, nothing is watching your files for you. There's no Imunify360 quietly quarantining a webshell someone dropped through an old contact form, and no dashboard that lights up when a coin miner starts eating your CPU at 3 a.m. On a plain Ubuntu or Debian box, malware detection is something you have to install yourself. Here's how to set up ClamAV and rkhunter properly, keep the false positives from burying real alerts, and get both running on a schedule you'll actually check.

Symptom: nothing's watching, until something's wrong

Most unmanaged VPS owners find out they have a problem the hard way: outbound mail suddenly spikes and your IP lands on a blocklist, top shows a process you don't recognize pinned at 100% CPU, or your hosting provider emails you about abuse complaints from your server. By the time you notice, the malicious file has usually been sitting there for weeks.

A few early warning signs worth checking right now:

  • Unfamiliar entries in crontab -l or /etc/cron.d/
  • New files in /tmp, /var/tmp, or your web root with random-looking names
  • SSH authorized_keys entries you didn't add
  • Processes in ps aux you can't account for, especially ones spawned from /tmp

Who actually needs this

If your VPS runs cPanel/WHM, you likely already have Imunify360 or similar scanning built in - that's a different setup with its own quarantine workflow. This guide is for everything else: a bare Ubuntu/Debian/AlmaLinux box running Docker containers, a Node.js app, a mail server, or anything you manage yourself over SSH with no control panel in front of it.

Step 1: Install ClamAV

On Ubuntu or Debian:

sudo apt update
sudo apt install clamav clamav-daemon -y

On AlmaLinux or Rocky Linux, enable EPEL first:

sudo dnf install epel-release -y
sudo dnf install clamav clamav-update -y

The daemon competes with the update service for the same lock file on first install, so stop it before you run freshclam manually:

sudo systemctl stop clamav-freshclam

Step 2: Pull down current virus definitions

sudo freshclam

If this fails with a "Can't connect to database.clamav.net" error, it's almost always outbound DNS or a firewall rule blocking port 443 to the ClamAV mirrors - check your CSF or UFW rules before assuming ClamAV itself is broken. Once it succeeds, restart the update service so definitions stay current automatically:

sudo systemctl enable --now clamav-freshclam

Step 3: Run your first real scan

A full scan of your web root, logging only infected files instead of every clean one:

sudo clamscan -r -i /var/www --log=/var/log/clamav/scan.log

On a large site this can take a while and burns CPU. Exclude directories you know are safe and huge - node_modules, .git, cache folders - to cut scan time significantly:

sudo clamscan -r -i /var/www \
  --exclude-dir="node_modules" \
  --exclude-dir="\.git" \
  --log=/var/log/clamav/scan.log

Don't add --remove on your first run. Use --move=/var/quarantine instead so you can review what it flags before anything gets deleted. Create that directory first with restrictive permissions (chmod 700) so quarantined files aren't executable or web-accessible.

Step 4: Add rkhunter for rootkits ClamAV won't catch

ClamAV is signature-based and mostly built for the kind of malware that ends up in web files - webshells, known trojans, malicious PHP. It's not designed to catch rootkits that hook into the kernel or replace system binaries. That's rkhunter's job:

sudo apt install rkhunter -y
sudo rkhunter --propupd
sudo rkhunter --check --sk

The --propupd command builds a baseline of your current file hashes and permissions right after install - run it once on a server you trust is clean. Every future --check compares against that baseline, so if you skip this step, rkhunter has nothing meaningful to compare against and every scan looks suspicious.

Fixing false positives

Both tools flag things that aren't actually malware, and if you don't tune this, you'll start ignoring every alert - which defeats the point.

ToolCommon false positiveFix
ClamAVBackup scripts or admin panels with base64-encoded stringsWhitelist the specific file path in /etc/clamav/clamd.conf with ExcludePath
rkhunter"Warning: Hidden file found" for legitimate dotfilesAdd the path to ALLOWHIDDENFILE in /etc/rkhunter.conf
rkhunterSSH config warnings after intentional hardening changesRun rkhunter --propupd again after any deliberate config change

After editing rkhunter.conf, always run rkhunter --config-check to make sure you didn't introduce a syntax error that silently breaks future scans.

Automating scans with cron

Manual scans only help if you remember to run them. Set both tools up on a schedule and pipe the output somewhere you'll actually read:

sudo crontab -e
# ClamAV: daily scan at 2:30 AM, log infections only
30 2 * * * clamscan -r -i /var/www --log=/var/log/clamav/daily-scan.log

# rkhunter: weekly check, mailed to root on Sunday at 3 AM
0 3 * * 0 rkhunter --check --sk --cronjob 2>&1 | mail -s "rkhunter weekly report" root

If mail isn't installed, add it with apt install mailutils, or swap the last line for a webhook curl call if you'd rather get alerts in Slack than in a root mailbox nobody checks.

If a scan finds something real

  1. Don't delete it yet - move it to an isolated, non-executable directory and note the exact path and timestamp.
  2. Check crontab -l for every user, not just root, and check /etc/cron.d/ for anything you didn't create.
  3. Check ~/.ssh/authorized_keys for every account for keys you don't recognize.
  4. Look at how the file got there - check web server access logs around the file's creation timestamp for the request that dropped it.
  5. Rotate every credential the compromised account could reach: SSH keys, database passwords, API tokens.
  6. Restore the affected files from a backup taken before the infection date, not just delete the one bad file - webshells rarely travel alone.

Prevention: make the next scan boring

  • Keep the OS patched with unattended security updates so known exploits get closed automatically.
  • Run web apps under a dedicated non-root user, never as root.
  • Lock down SSH to key-only auth and disable root login.
  • Keep a firewall (CSF, UFW, or iptables) blocking everything except the ports you actually use.
  • Take regular off-site backups so "restore from before the infection" is actually an option.

None of this replaces good backups or a firewall - ClamAV and rkhunter are a detection layer, not prevention. Their whole job is to tell you fast when something got past everything else.

Frequently asked questions

Does ClamAV replace a firewall or a WAF?

No. ClamAV scans files already sitting on disk for known malware signatures - it doesn't stop an attacker from getting in or block malicious requests in real time. Pair it with a firewall like CSF or UFW and, ideally, a web application firewall in front of anything public-facing.

Will running a scan slow down my VPS?

A full clamscan of a large web root is CPU and disk intensive while it runs. Schedule it during low-traffic hours (2-4 AM is common), and exclude directories like node_modules or vendor caches that don't need scanning every time - it cuts run time significantly without losing coverage on the files that matter.

My VPS has cPanel with Imunify360 - do I need ClamAV too?

Not usually. Imunify360 already runs ClamAV under the hood along with its own heuristics and automatic quarantine, so a separate manual install is redundant. This setup is for VPS instances without a control panel doing that work for you.

rkhunter flagged a warning - does that mean I'm hacked?

Not necessarily. rkhunter is prone to false positives, especially right after you change SSH config, install new packages, or if you never ran the initial baseline with rkhunter --propupd. Read the specific warning before panicking - most resolve by updating the baseline or whitelisting a known-safe path.

How often should I actually scan?

Daily ClamAV scans and weekly rkhunter checks are a reasonable baseline for most VPS instances. If you're running a high-traffic site with public file uploads or a lot of third-party plugins, consider running ClamAV against the uploads directory more frequently, even hourly, since that's the most common entry point.

#clamav #rkhunter #vps-security #malware-scanning #linux #cron

Keep reading

Chat with Support