ClamAV is the open-source antivirus engine used on Linux mail servers, file servers and web hosts. On a server it’s mostly used to scan files that come from outside: uploads, email attachments, shared folders, and website files after a suspected hack. Here’s how to install it, keep it updated and run useful scans without overloading a small VPS.
Install
Debian/Ubuntu:
sudo apt update
sudo apt install clamav clamav-daemon
RHEL family (EPEL):
sudo dnf install epel-release
sudo dnf install clamav clamav-update clamd
Update the virus signatures
freshclam downloads the signature databases. On Debian and Ubuntu, the clamav-freshclam service updates them automatically:
sudo systemctl status clamav-freshclam
To update manually, stop the service first, since both can’t run at once:
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam
On RHEL-family systems, enable updates with sudo systemctl enable --now clamav-freshclam, or run freshclam from a timer. Remove the Example line in /etc/freshclam.conf if present.
Scan files: clamscan
clamscan -r --infected /var/www # recursive, show only infected files
clamscan -r -i --exclude-dir='^/var/www/.*/cache' /var/www
clamscan -r -i --log=/var/log/clamav/www-scan.log /var/www
Useful options:
-r— recursive.-i— print only infected files.--move=/root/quarantine— move detections to quarantine. Review before deleting.--max-filesize=50M --max-scansize=200M— skip huge files.
clamscan loads the whole signature database each run, which takes 10–30 seconds and about 1 GB of RAM. On a 2 GB VPS, that’s significant. Scan at quiet times, at low priority:
nice -n 19 ionice -c3 clamscan -r -i /var/www
Faster scans: clamd
The daemon keeps signatures in memory, so scans start instantly. It permanently uses about 1–1.5 GB of RAM, so it’s worthwhile on servers with 4 GB+ that scan often, such as mail servers:
sudo systemctl enable --now clamav-daemon # 'clamd@scan' on RHEL
clamdscan --fdpass -m -i /var/www # multi-threaded scan via the daemon
--fdpass lets the daemon read files your user can access.
Schedule a daily scan
sudo tee /etc/cron.daily/clamscan-www > /dev/null <<'EOF'
#!/bin/sh
LOG=/var/log/clamav/www-$(date +%F).log
nice -n 19 ionice -c3 clamscan -r -i --log="$LOG" /var/www /home > /dev/null 2>&1
if grep -q 'Infected files: [1-9]' "$LOG"; then
mail -s "ClamAV: infected files on $(hostname)" [email protected] < "$LOG"
fi
EOF
sudo chmod +x /etc/cron.daily/clamscan-www
The mail step needs a working MTA. Alternatively, send the alert to a webhook. A systemd timer works just as well. See systemd timers.
Scan uploads as they arrive
For apps that accept uploads, scan each file before storing it. Call clamdscan --fdpass file from the app, or use a library that talks to clamd’s socket (PHP, Python and Node libraries exist). Reject or quarantine the file on detection.
Mail servers integrate ClamAV through amavis, rspamd or clamav-milter, scanning every attachment.
What ClamAV is good, and not so good, at
Good at:
- known malware in uploaded files and attachments (Windows malware, macro documents, known PHP shells);
- keeping infected files from being redistributed to your users.
Limited at:
- new or obfuscated PHP backdoors and injected JavaScript on hacked websites. Signature coverage for web malware is weaker. Third-party signature sets (such as those from Linux Malware Detect, or commercial feeds) improve detection;
- rootkits and system compromise. Use dedicated tools. See rkhunter and chkrootkit;
- real-time protection on servers. On-access scanning (
clamonacc) exists but is resource-heavy.
If ClamAV finds something on your website
- Don’t just delete the file. Find out how it got there: outdated plugins, weak passwords, writable upload directories that execute PHP.
- Compare files with a clean copy (WordPress core:
wp core verify-checksums). See WP-CLI. - Check for other changes: recently modified files (
find /var/www -mtime -7 -name '*.php'), new admin users, cron jobs. - Patch the hole, rotate passwords and keys, and restore from a clean backup if in doubt.
- Harden it: disable PHP execution in upload folders, and keep software updated. See WordPress hardening.
Quick reference
| Task | Command |
|---|---|
| Install | apt install clamav clamav-daemon |
| Update signatures | freshclam (service: clamav-freshclam) |
| Scan directory | clamscan -r -i /path |
| Low priority | nice -n19 ionice -c3 clamscan … |
| Via daemon | clamdscan --fdpass -m -i /path |
| Quarantine | --move=/root/quarantine |
Related: Lynis security audit and Linux server hardening.