Short answer: ClamAV (Clam AntiVirus) is a free, open-source antivirus engine for Linux. Install it with sudo apt install clamav clamav-daemon on Ubuntu or Debian (from EPEL on Rocky Linux and AlmaLinux), let freshclam keep the signatures current, and scan with clamscan -r -i /path. It finds known malware in files; it does not secure a server on its own.
sudo apt update
sudo apt install -y clamav clamav-daemon # also pulls in clamav-freshclam and clamdscan
systemctl status clamav-freshclam --no-pager # signature updates run as a service
clamscan --version # engine version / signature version / date
sudo clamscan -r -i /home /srv # scan two trees, list only infected filesThe commands follow the ClamAV documentation on docs.clamav.net, the clamscan man page and the Debian and EPEL package contents, as of October 2026. The output blocks show the format ClamAV prints; they are examples, not captures from a test run.
What ClamAV is, and its five tools
ClamAV compares files with a database of signatures for known malware, and it looks inside archives, office documents, PDFs and mail files while it does so. Cisco Talos maintains it. Per the end-of-life page on docs.clamav.net (October 2026), 1.4 is the long-term support release, supported until August 2027, and 1.5 is the newest feature release. Versions 0.105 and older are blocked from downloading signature updates, so an old server needs a newer package before it is any use.
| Program | What it does | Use it for |
|---|---|---|
clamscan | Loads all signatures, scans, exits | One-off and nightly scans; needs no daemon |
freshclam | Downloads signature updates | Runs as a service (clamav-freshclam) |
clamd | Daemon that keeps the signatures in memory | Many scans a day: uploads, mail, a busy file share |
clamdscan | Client that hands files to clamd | Fast scans once clamd is running |
clamonacc | On-access scanning through clamd (Linux only) | Watching a directory as files arrive |
How do you install ClamAV on Linux?
Ubuntu and Debian
clamav brings clamscan, clamav-daemon brings clamd, and both pull in clamav-freshclam; clamav-daemon also recommends clamdscan, so apt installs it by default. Configuration lives in /etc/clamav, signatures in /var/lib/clamav. Debian 12 and 13 carry the 1.4 branch and Ubuntu 24.04 gets 1.5 through its updates (packages.debian.org and Launchpad, October 2026).
sudo apt install -y clamav clamav-daemon
systemctl status clamav-freshclam --no-pager # downloading right after the install
ls -lh /var/lib/clamav # main, daily and bytecode databases (.cvd or .cld)
sudo systemctl enable --now clamav-daemon # once the databases are thereUntil the first download has finished, clamav-daemon does not start: its unit checks that the signature files exist, and systemctl status clamav-daemon reports a start condition that was not met. That is not an error. Start it again when /var/lib/clamav holds the databases.
Rocky Linux and AlmaLinux
sudo dnf install -y epel-release
sudo dnf install -y clamav clamd clamav-update
sudo freshclam # first download, before the service runs
sudo systemctl enable --now clamav-freshclamClamAV’s docs name the updater package clamav-update; current EPEL builds call it clamav-freshclam and it still answers to the old name. The daemon is a template unit with its config in /etc/clamd.d/scan.conf. Open that file, remove the # in front of the LocalSocket line (and comment out a line that reads only Example, if your copy has one), then start it:
sudo systemctl enable --now clamd@scan
sudo setsebool -P antivirus_can_scan_system 1 # SELinux: allow ClamAV to read the whole system
clamdscan --config-file=/etc/clamd.d/scan.conf --version # the client talks to that daemonKeep the signatures current with freshclam
The freshclam service checks for new signatures several times a day without your help. clamscan --version shows the engine version, the signature version and its date; a date several days old means updates are failing. To update by hand, stop the service first. A manual run while it is active stops with:
ERROR: /var/log/clamav/freshclam.log is locked by another process
ERROR: Problem with internal logger (UpdateLogFile = /var/log/clamav/freshclam.log).sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclamDo not add freshclam to cron on top of the service, and never run it in a loop. The signature servers rate-limit clients that download too often: freshclam then reports HTTP error 429 and a cool-down time, and it gets nothing until that has passed. With many servers behind one address, the ClamAV FAQ points to cvdupdate, which keeps a local mirror that the other machines update from.
How do you scan with clamscan?
clamscan download.zip # one file
sudo clamscan -r /srv/www # a directory tree
sudo clamscan -r -i /srv/www # only infected files in the output
sudo clamscan -r -i --exclude-dir='^/srv/www/cache' /srv/www
sudo install -d -m 700 /var/lib/clamav-quarantine
sudo clamscan -r -i --move=/var/lib/clamav-quarantine /srv/uploads/srv/uploads/eicar.com.txt: Win.Test.EICAR_HDB-1 FOUND
----------- SCAN SUMMARY -----------
Known viruses: ...
Engine version: 1.4.3
Scanned directories: 3
Scanned files: 412
Infected files: 1
Time: ...Each hit is a line with the path, the signature name and FOUND. To see one without real malware, scan the EICAR test file, a harmless string that every antivirus reports on purpose (download it from the EICAR website). clamscan exits with 0 when it found nothing, 1 when it found something and 2 on errors, which is what scripts should test.
-iprints only infected files; without it every clean file gets anOKline.-rdescends into subdirectories.--exclude-dirand--excludetake regular expressions and can be repeated. For a scan of/, leave out the virtual file systems:--exclude-dir='^/(proc|sys|dev|run)'.- clamscan has no quick-scan mode: it reads every file you point it at. Run it with
nice -n 19 ionice -c 3in front so that the server’s real work wins. - Size limits (
--max-filesize,--max-scansize) decide how much of a large file or archive gets scanned;man clamscanlists the defaults of your version.
clamd and clamdscan: scan faster with the daemon
clamscan loads the whole signature database on every run, which costs time and memory each time. clamd loads it once and keeps it, and clamdscan sends it work, so scanning a single upload no longer waits for the database to load.
sudo systemctl enable --now clamav-daemon
clamdscan --fdpass -m -i /srv/uploads--fdpass: clamd runs as its own unprivileged user (clamavon Debian and Ubuntu) and cannot open files that only you or your web server may read. With this flag clamdscan opens each file and passes the open file descriptor over the local socket, so permissions stop being a problem.-m(--multiscan) spreads a directory over clamd’s worker threads.--moveand--removework here too; clamdscan carries them out, not clamd.- Without a running daemon, clamdscan fails with
Could not connect to clamd on LocalSocket /var/run/clamav/clamd.ctl.
How much RAM does ClamAV need?
Per docs.clamav.net, ClamAV uses upwards of 1.2 GiB of RAM just to load the signatures, and clamd briefly needs twice that when it reloads after an update, because it builds the new engine before it drops the old one. The documentation recommends 3 GiB of RAM or more on a Linux server and 5 GiB of free disk for ClamAV. clamscan needs the same memory while it runs, but only for that time.
| Server RAM | Sensible setup |
|---|---|
| 2 GB | clamscan at night instead of clamd, with a swap file (adding swap) |
| 4 GB | clamd fits next to a light stack; set ConcurrentDatabaseReload no |
| 8 GB or more | clamd with the default reload, or on-access scanning |
ps -o rss=,cmd= -C clamd # resident memory of clamd in KiB
# Debian, Ubuntu: /etc/clamav/clamd.conf Rocky, Alma: /etc/clamd.d/scan.conf
ConcurrentDatabaseReload noWith ConcurrentDatabaseReload no, clamd stops taking new scans while it reloads instead of holding two copies of the database. Restart the daemon after the change. If the kernel kills clamd anyway, the journal shows it (see why Linux kills a process).
Schedule a scan with cron or a systemd timer
30 3 * * 0 root nice -n 19 ionice -c 3 clamscan -r -i --move=/var/lib/clamav-quarantine --log=/var/log/clamscan-weekly.log /srv /homeFiles in /etc/cron.d carry the user as the sixth field; the crontab guide explains the format and why output vanishes unless you log it. A systemd timer does the same and records the result in the journal:
[Unit]
Description=Weekly ClamAV scan of /srv and /home
[Service]
Type=oneshot
Nice=19
IOSchedulingClass=idle
ExecStart=/usr/bin/clamscan -r -i --move=/var/lib/clamav-quarantine --log=/var/log/clamscan-weekly.log /srv /home[Unit]
Description=Run the weekly ClamAV scan
[Timer]
OnCalendar=Sun *-*-* 03:30:00
RandomizedDelaySec=30min
Persistent=true
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl enable --now clamscan-weekly.timer
systemctl list-timers clamscan-weekly.timerOn Debian 12 with systemd 252, systemd-analyze verify raised nothing about the two units except that clamscan was not installed on that machine, and systemd-analyze calendar 'Sun *-*-* 03:30:00' printed the next Sunday at 03:30. Because clamscan exits with 1 when it finds something, the service then shows as failed, and that is useful: systemctl --failed lists it, and an OnFailure= unit can send you a message.
Scanning uploads and mail
The place where ClamAV earns its memory on a Linux server is files that come from outside and are passed on to other people: uploads, attachments, shared folders. Scan an upload before it reaches its public directory, from the upload handler, with clamd already running:
if clamdscan --fdpass --no-summary --quiet "$f"; then
mv "$f" /srv/www/uploads/
else
mv "$f" /var/lib/clamav-quarantine/ # 1 = found, 2 = error: keep it out either way
fiTreat exit code 2 like a hit: a scan that failed did not prove anything. For a mail server, scanning belongs in the delivery path rather than in a nightly job. With Postfix that is clamav-milter (its own package on Debian and Ubuntu), or a content filter such as Amavis or Rspamd, which both hand attachments to clamd.
On-access scanning with clamonacc
clamonacc watches paths through the kernel’s fanotify interface and sends new and changed files to clamd as they appear. It must run as root, it reads its settings from clamd.conf (OnAccessIncludePath for each directory to watch), and clamd must run as a user that is excluded from watching (OnAccessExcludeUname clamav), or its own reads trigger new scans. Debian and Ubuntu ship it as clamav-clamonacc.service. By default it only reports; with OnAccessPrevention yes it blocks access to a file until the scan is done, which the documentation warns “will seriously impact performance if used on commonly accessed directories”. Point it at an upload directory, never at /.
What antivirus on a Linux server can and cannot do
- It can catch known malware in files your server stores or passes on: Windows malware in uploads and attachments, known webshells and miners whose files match a signature, and infected archives on a share used by desktop clients.
- It can give you a second opinion after a suspected break-in, next to the checks in finding a cryptominer.
- It cannot stop an attack. Most Linux servers are broken into through outdated software, exposed services or guessed passwords, and a signature scan sees none of that.
- It cannot reliably detect new or modified malware, and it does not watch what processes do. Anyone who has root can switch it off or hide files from it.
So treat ClamAV as a filter for files, not as protection for the server. The protection is the dull list: updates, key-only logins from securing SSH access, fail2ban against password guessing, a firewall that only opens what you serve, and backups. The initial server setup covers the first hour.
Common ClamAV errors and fixes
| Message | Cause | Fix |
|---|---|---|
freshclam.log is locked by another process | The freshclam service is already running | Stop clamav-freshclam, run freshclam, start it again |
| clamav-daemon: start condition not met | No signature databases yet | Wait for freshclam, then start clamav-daemon |
Could not connect to clamd on LocalSocket | clamd is stopped, still loading, or was killed | Start it; check journalctl -u clamav-daemon and memory |
*** The virus database is older than 7 days! *** | Updates have been failing | Read the freshclam log; check DNS, outbound HTTPS and a 429 cool-down |
| Error 429 and a cool-down time from freshclam | Too many downloads from your address | Wait it out; drop extra cron runs; use cvdupdate for many servers |
Permission denied from clamdscan | The clamav user cannot read the file | Add --fdpass |
| Out of memory: Killed process ... (clamd) | Not enough RAM, often during a reload | ConcurrentDatabaseReload no, swap, or clamscan instead |
ClamAV on a VPS or dedicated server
Plan memory first. On a 2 GB plan such as the smallest Hi-CPU KVM, run clamscan at night and skip the daemon. The Standard KVM line starts at 4 GB, which holds clamd next to a small web stack with concurrent reloads switched off. A dedicated server has memory to spare for clamd and on-access scanning of busy upload directories. If a scan does find something on a VPS, take a snapshot in the panel before you clean up, so that the evidence survives, and then find out how the file got there.
Frequently asked
Does a Linux server need antivirus?
Not as protection against attacks: Linux servers are broken into through outdated software, exposed services and guessed passwords, which a signature scanner does not see. ClamAV is worth running where the server stores or passes on files from other people, such as uploads, mail attachments and file shares, because it catches known malware in those files before someone downloads them.
How much RAM does ClamAV need?
According to the ClamAV documentation, loading the signatures alone takes upwards of 1.2 GiB of RAM, and the clamd daemon briefly needs about twice that while it reloads after an update. The documentation recommends 3 GiB of RAM or more. On a 2 GB server, run clamscan on a schedule instead of the daemon; with 4 GB, set 'ConcurrentDatabaseReload no' for clamd.
How do I update ClamAV virus definitions manually?
Stop the updater service, run freshclam and start the service again: 'sudo systemctl stop clamav-freshclam', then 'sudo freshclam', then 'sudo systemctl start clamav-freshclam'. Running freshclam while the service is active fails with 'freshclam.log is locked by another process'. Normally the service updates several times a day on its own, so a manual run is rarely needed.
What is the difference between clamscan and clamdscan?
clamscan works on its own: it loads the whole signature database, scans and exits, so every run pays the load time and the memory. clamdscan is a client for the clamd daemon, which keeps the signatures loaded, so scans start at once. Use clamscan for occasional scans on small servers, and clamd with clamdscan for frequent scans such as uploads or mail.