How to Install ClamAV on Linux: A Complete Technical Guide
ClamAV is an open-source, cross-platform antivirus engine maintained by Cisco Talos that detects viruses, trojans, rootkits, malware, and other malicious threats. It operates using a signature-based detection model backed by a continuously updated database (/var/lib/clamav/), and it is the de facto standard antivirus solution for Linux servers, mail gateways, and web hosting environments.
This guide covers the full installation lifecycle: system preparation, package installation across major distributions, virus database management with freshclam, daemon configuration, scanning strategies, quarantine handling, cron automation, and real-time scanning via clamonacc — including production-grade pitfalls that most tutorials omit.
Why ClamAV Matters on Linux Servers
Linux systems are not immune to malware. While Linux-targeting exploits are less common than Windows threats, servers running web applications, mail relays, or file-sharing services are active vectors for malware distribution — even when the Linux host itself is not the primary target. A compromised VPS Hosting environment can silently redistribute infected files to end users, trigger blacklisting by spam databases, or serve as a pivot point in a larger attack chain.
ClamAV addresses this by providing:
- On-demand scanning for scheduled or triggered analysis
- Daemon-mode scanning (
clamd) for high-throughput, low-latency checks - Mail gateway integration via
clamsmtp,amavisd-new, orMilter - Real-time file system monitoring via
clamonacc(Linux kernelfanotify) - Bytecode signatures for heuristic detection beyond static pattern matching
Step 1: Prepare and Update Your System
Before installing any package, synchronize your package index and apply pending security patches. Running outdated system libraries alongside a security tool creates a false sense of protection.
For Debian/Ubuntu:
sudo apt update && sudo apt upgrade -yFor CentOS/RHEL 7:
sudo yum update -yFor Rocky Linux / AlmaLinux / RHEL 8+:
sudo dnf update -yFor Fedora:
sudo dnf update -yConfirm your kernel and glibc versions are current, as clamonacc (real-time scanning) requires kernel 5.1+ for stable fanotify support.
Step 2: Install ClamAV
ClamAV is available in the default repositories of all major distributions. The key distinction is whether you install only the scanner (clamav) or also the background daemon (clamav-daemon / clamd), which is strongly recommended for any production server.
For Debian/Ubuntu:
sudo apt install clamav clamav-daemon -yclamav— installsclamscanandfreshclam
clamav-daemon — installs clamd, the persistent scanning daemon that keeps the virus database loaded in memory, dramatically reducing per-scan overhead
For CentOS/RHEL 7 (requires EPEL):
sudo yum install epel-release -y
sudo yum install clamav clamav-update clamav-scanner-systemd clamd -y
For Rocky Linux / AlmaLinux / RHEL 8+ (requires EPEL):
sudo dnf install epel-release -y
sudo dnf install clamav clamav-update clamd -y
For Fedora:
sudo dnf install clamav clamav-update clamd -y
Post-install binary locations to verify:
Binary
Path
Purpose
clamscan
/usr/bin/clamscan
On-demand CLI scanner
clamd
/usr/sbin/clamd
Background scanning daemon
freshclam
/usr/bin/freshclam
Virus database updater
clamdscan
/usr/bin/clamdscan
Client that delegates to clamd
clamonacc
/usr/sbin/clamonacc
Real-time on-access scanner
Step 3: Update the Virus Signature Database
ClamAV's detection capability is entirely dependent on the currency of its signature database. The database lives in /var/lib/clamav/ and consists of several files: main.cvd, daily.cvd (or .cld), and bytecode.cvd.
Stop the Daemon Before the First Update (Debian/Ubuntu)
On Debian/Ubuntu systems, clamav-freshclam.service runs automatically after installation and locks the database directory. If you attempt to run freshclam manually while this service is active, you will encounter a lock conflict. Stop it first:
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam
On CentOS/RHEL/Rocky/Alma:
sudo freshclam
Expected output on a successful update:
ClamAV update process started at ...
daily.cvd updated (version: 27xxx, sigs: xxxxxxx, ...)
main.cvd is up to date
bytecode.cvd is up to date
Configure Automatic Database Updates
freshclam is controlled by /etc/clamav/freshclam.conf. Key directives to review:
sudo nano /etc/clamav/freshclam.conf
Critical parameters:
Checks 24 — number of update checks per day (default: 12 on some distros)
DatabaseMirror database.clamav.net — official mirror; do not change unless using a private mirror
NotifyClamd /etc/clamav/clamd.conf — instructs freshclam to signal clamd after an update so the daemon reloads signatures without restarting
Step 4: Configure and Start the ClamAV Daemon
The clamd daemon keeps the full virus database resident in RAM (typically 500 MB–1.2 GB depending on database version). This eliminates the multi-second startup cost of clamscan, making it essential for any environment that performs frequent or concurrent scans.
Debian/Ubuntu
sudo systemctl start clamav-daemon
sudo systemctl enable clamav-daemon
sudo systemctl status clamav-daemon
CentOS/RHEL 7
On RHEL 7, the service unit is named clamd@scan, referencing the configuration file /etc/clamd.d/scan.conf:
sudo systemctl start clamd@scan
sudo systemctl enable clamd@scan
Rocky Linux / AlmaLinux / RHEL 8+
sudo systemctl start clamd@scan
sudo systemctl enable clamd@scan
Key clamd.conf Parameters
The daemon configuration lives at /etc/clamav/clamd.conf (Debian/Ubuntu) or /etc/clamd.d/scan.conf (RHEL family). Review these directives:
sudo nano /etc/clamav/clamd.conf
Important settings:
LocalSocket /run/clamav/clamd.ctl — Unix socket path used by clamdscan; ensure this matches your client configuration
MaxFileSize 100M — maximum file size to scan; increase for mail servers handling large attachments
MaxScanSize 400M — maximum data scanned per file after decompression
StreamMaxLength 100M — relevant for milter/stream-based scanning
User clamav — daemon runs as the clamav user; ensure this user has read access to directories you intend to scan
LogFile /var/log/clamav/clamd.log — enable persistent logging for audit trails
Critical pitfall: If clamd runs as user clamav and you scan /home/user/uploads/, the clamav user must have read permissions on that path. Forgetting this results in silent scan failures — clamd will report "Access denied" errors in its log rather than returning a clean/infected verdict.
Step 5: Running Scans with clamscan and clamdscan
On-Demand Scanning with clamscan
clamscan is the standalone scanner. It loads the database from disk on each invocation, making it slower but independent of the daemon.
Scan a specific directory recursively:
clamscan -r /path/to/directory
Scan and display only infected files:
clamscan -r --infected /path/to/directory
Scan with verbose output and log results:
sudo clamscan -r --infected --log=/var/log/clamav/manual_scan.log /var/www/html
Move infected files to a quarantine directory:
sudo clamscan -r --move=/var/quarantine /path/to/directory
Remove infected files automatically (use with caution in production):
sudo clamscan -r --remove /path/to/directory
Scan the entire filesystem (expect significant runtime on large disks):
sudo clamscan -r --infected --exclude-dir="^/sys" --exclude-dir="^/proc" --exclude-dir="^/dev" /
Excluding /sys, /proc, and /dev is mandatory — scanning these pseudo-filesystems produces false errors and can cause hangs.
High-Performance Scanning with clamdscan
When clamd is running, use clamdscan instead of clamscan. It submits scan requests to the already-loaded daemon over the Unix socket, making it orders of magnitude faster for repeated or bulk scans.
clamdscan --fdpass /path/to/directory
The --fdpass flag passes the file descriptor directly to clamd, bypassing permission issues that arise when the daemon's user cannot read the target path directly.
Multi-threaded scanning with clamdscan:
clamdscan --multiscan --fdpass /var/www/html
--multiscan instructs clamd to scan files in parallel using its thread pool, significantly reducing wall-clock time on multi-core systems.
clamscan vs. clamdscan: Performance Comparison
Attribute
`clamscan`
`clamdscan`
Database load per scan
Yes (slow startup)
No (daemon keeps DB in RAM)
Typical startup time
5–30 seconds
Under 1 second
Requires clamd running
No
Yes
Parallel scanning
No
Yes (--multiscan)
Best use case
One-off manual scans
Automated, frequent, or bulk scans
Permission model
Runs as invoking user
Runs as clamav user (use --fdpass)
Step 6: Automate Scanning with Cron
For continuous protection, schedule regular scans using cron. The following example scans the web root daily at 02:00 AM and logs results with a timestamp.
sudo crontab -e
Add the following entry:
0 2 * * * /usr/bin/clamdscan --multiscan --fdpass --log=/var/log/clamav/daily_scan_$(date +%Y%m%d).log /var/www/html
Production-grade cron with email alerting on infection:
0 2 * * * /usr/bin/clamscan -r --infected /var/www/html 2>&1 | grep -v "^$" | mail -s "ClamAV Daily Scan Report - $(hostname)" admin@yourdomain.com
This pipes non-empty output directly to a mail recipient, ensuring you only receive alerts when something is found or an error occurs. Ensure mailutils or postfix is configured on the server.
Rotate scan logs to prevent unbounded disk growth:
sudo nano /etc/logrotate.d/clamav-scan
/var/log/clamav/daily_scan_*.log {
weekly
rotate 4
compress
missingok
notifempty
}
Step 7: Real-Time On-Access Scanning with clamonacc
clamonacc is ClamAV's on-access scanning component, introduced as a stable feature in ClamAV 0.102. It hooks into the Linux kernel's fanotify subsystem to intercept file open and close events, scanning files before they are accessed.
Requirements:
Linux kernel 5.1 or later (for fanotify with FAN_OPEN_EXEC_PERM)
ClamAV 0.102+
clamd must be running
Root privileges
Enable On-Access Scanning in clamd.conf
sudo nano /etc/clamav/clamd.conf
Add or uncomment:
OnAccessIncludePath /home
OnAccessIncludePath /var/www/html
OnAccessPrevention yes
OnAccessExcludeUname clamav
OnAccessPrevention yes — blocks access to infected files in real time (deny mode); set to no for detection-only mode
OnAccessExcludeUname clamav — prevents clamd itself from triggering recursive scan loops
Start clamonacc
sudo clamonacc --log=/var/log/clamav/clamonacc.log --daemonize
To run it as a systemd service, create a unit file:
sudo nano /etc/systemd/system/clamonacc.service
[Unit]
Description=ClamAV On-Access Scanner
Requires=clamav-daemon.service
After=clamav-daemon.service
[Service]
Type=simple
ExecStart=/usr/sbin/clamonacc --log=/var/log/clamav/clamonacc.log --foreground
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now clamonacc
Known pitfall: On high-throughput servers (e.g., busy file upload endpoints), OnAccessPrevention yes can introduce measurable I/O latency. Benchmark your workload before enabling prevention mode in production. Consider scoping OnAccessIncludePath to the narrowest necessary path rather than broad directories like /.
Step 8: Integrating ClamAV with Mail Servers
ClamAV's most widespread production use case is mail gateway scanning. If you are running a mail server on your VPS Hosting or Dedicated Servers infrastructure, integrating ClamAV with your MTA is a critical security layer.
Common integration stacks:
Postfix + amavisd-new + ClamAV — amavisd-new acts as a content filter between Postfix and ClamAV, also handling SpamAssassin
Postfix + clamsmtp — lightweight milter-style proxy
Exim + ClamAV — native Exim av_scanner directive supports clamd directly via socket
Example: Exim clamd integration in /etc/exim4/exim4.conf:
av_scanner = clamd:/run/clamav/clamd.ctl
This single directive routes all message content through the running clamd instance before delivery. Pair this with proper Email Hosting configuration to ensure your mail infrastructure is fully protected.
Troubleshooting Common ClamAV Issues
freshclam Fails with "locked by another process"
sudo systemctl stop clamav-freshclam
sudo rm -f /var/lock/clamav/freshclam.lock
sudo freshclam
sudo systemctl start clamav-freshclam
clamd Fails to Start: "ERROR: Can't open/parse the config file"
Verify the configuration file path and syntax:
sudo clamd --config-file=/etc/clamav/clamd.conf --debug 2>&1 | head -50
High Memory Usage
clamd typically consumes 500 MB–1.2 GB of RAM with the full database loaded. On memory-constrained systems, consider:
Setting MaxThreads 2 in clamd.conf to limit concurrency
Using clamscan without the daemon for infrequent scans
Upgrading to a plan with sufficient RAM — a VPS Hosting plan with at least 2 GB RAM is the practical minimum for running clamd alongside a web stack
Scan Returns "Access denied" for Files
The clamd daemon runs as the clamav user. Grant read access:
sudo setfacl -R -m u:clamav:rX /path/to/scan
Or use clamdscan --fdpass to pass file descriptors from the invoking user's context.
False Positives
ClamAV occasionally flags legitimate files, particularly compressed archives or certain PHP frameworks. To whitelist a known-safe file by hash:
sigtool --md5 /path/to/legitimate/file >> /var/lib/clamav/whitelist.fp
Restart clamd after modifying .fp files.
ClamAV on Shared Hosting vs. VPS vs. Dedicated Server
The deployment model significantly affects how ClamAV should be configured:
Environment
Recommended Mode
Notes
Shared Web Hosting
On-demand clamscan via cron
No root access; daemon mode unavailable
VPS (2–4 GB RAM)
clamd daemon + cron clamdscan
Balance performance with memory constraints
Dedicated Server
clamd + clamonacc + mail integration
Full feature set; no resource compromise
GPU/High-compute node
clamd daemon only
Avoid clamonacc I/O overhead on data pipelines
For environments requiring maximum throughput and full control over security tooling, Dedicated Servers provide the hardware headroom to run clamd, clamonacc, and mail scanning simultaneously without resource contention.
Technical Decision Matrix and Key Takeaways
Before deploying ClamAV, validate each of the following:
Kernel version — run uname -r; confirm 5.1+ if clamonacc is required
Available RAM — clamd needs 1–1.5 GB; plan accordingly before enabling the daemon
freshclam automation — confirm clamav-freshclam.service is enabled and NotifyClamd is set in freshclam.confclamav user can read all scan targets; use --fdpass with clamdscan where ACLs are impractical/proc, /sys, /dev from recursive scanslogrotate for all ClamAV log files before enabling daily cron jobsOnAccessPrevention — test in detection-only mode (no) before switching to blocking mode (yes) on production systemsamavisd-new or native MTA av_scanner directive, not just periodic file scans/var/quarantine with appropriate ownership before using --move; clamscan will not create it automatically.fp whitelist file and review scan logs after each database update for regressionsFrequently Asked Questions
Does ClamAV provide real-time protection on Linux by default?
No. After installation, ClamAV operates in on-demand mode only. Real-time protection requires explicitly enabling clamonacc with OnAccessIncludePath and OnAccessPrevention directives in clamd.conf, plus a kernel that supports fanotify (5.1+).
What is the difference between clamscan and clamdscan?
clamscan is a standalone binary that loads the virus database from disk on every invocation, resulting in a 5–30 second startup delay. clamdscan is a thin client that submits scan jobs to the already-running clamd daemon, which keeps the database in RAM — making it significantly faster for repeated or automated scans.
How much RAM does ClamAV's daemon require?
clamd with the current full database (main + daily + bytecode) typically requires between 700 MB and 1.2 GB of resident memory. On systems with less than 2 GB total RAM, running the daemon alongside a web server or database can cause memory pressure. Use clamscan without the daemon on memory-constrained instances.
Can ClamAV scan compressed archives and email attachments?
Yes. ClamAV natively unpacks and scans ZIP, RAR, 7z, TAR, GZIP, BZIP2, CAB, and many other archive formats, as well as OLE2 documents (Microsoft Office), PDF files, and ELF/PE executables. The MaxScanSize and MaxFileSize directives in clamd.conf control the depth and size limits for archive scanning.
Why does freshclam report "locked by another process" immediately after installation?
On Debian/Ubuntu, the clamav-freshclam systemd service starts automatically after package installation and holds an exclusive lock on the database directory. Running freshclam manually while this service is active causes a lock conflict. Stop the service with sudo systemctl stop clamav-freshclam, run the manual update, then restart the service.
