Guides

ClamAV on Linux: install it, update the signatures and scan safely

ClamAV Linux guide: install on Ubuntu, Debian or Rocky, keep signatures current with freshclam, scan with clamscan or clamd, and know its limits.

Published ~10 min read
On this page

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.

Debian · Ubuntu · the short version
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 files

The 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.

ProgramWhat it doesUse it for
clamscanLoads all signatures, scans, exitsOne-off and nightly scans; needs no daemon
freshclamDownloads signature updatesRuns as a service (clamav-freshclam)
clamdDaemon that keeps the signatures in memoryMany scans a day: uploads, mail, a busy file share
clamdscanClient that hands files to clamdFast scans once clamd is running
clamonaccOn-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).

Debian · Ubuntu
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 there

Until 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

Rocky Linux · 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-freshclam

ClamAV’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:

Rocky Linux · AlmaLinux
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 daemon

Keep 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:

freshclam while the service runs
ERROR: /var/log/clamav/freshclam.log is locked by another process
ERROR: Problem with internal logger (UpdateLogFile = /var/log/clamav/freshclam.log).
Debian · Ubuntu · Rocky · Alma
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam

Do 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?

any Linux
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
Example output · shortened
/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.

  • -i prints only infected files; without it every clean file gets an OK line. -r descends into subdirectories.
  • --exclude-dir and --exclude take 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 3 in 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 clamscan lists 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.

Debian · Ubuntu
sudo systemctl enable --now clamav-daemon
clamdscan --fdpass -m -i /srv/uploads
  • --fdpass: clamd runs as its own unprivileged user (clamav on 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.
  • --move and --remove work 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 RAMSensible setup
2 GBclamscan at night instead of clamd, with a swap file (adding swap)
4 GBclamd fits next to a light stack; set ConcurrentDatabaseReload no
8 GB or moreclamd with the default reload, or on-access scanning
memory check and the reload switch
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 no

With 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

/etc/cron.d/clamscan · Sundays at 03:30
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 /home

Files 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:

/etc/systemd/system/clamscan-weekly.service
[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
/etc/systemd/system/clamscan-weekly.timer
[Unit]
Description=Run the weekly ClamAV scan

[Timer]
OnCalendar=Sun *-*-* 03:30:00
RandomizedDelaySec=30min
Persistent=true

[Install]
WantedBy=timers.target
enable it
sudo systemctl daemon-reload
sudo systemctl enable --now clamscan-weekly.timer
systemctl list-timers clamscan-weekly.timer

On 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:

bash · in an upload handler
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
fi

Treat 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

MessageCauseFix
freshclam.log is locked by another processThe freshclam service is already runningStop clamav-freshclam, run freshclam, start it again
clamav-daemon: start condition not metNo signature databases yetWait for freshclam, then start clamav-daemon
Could not connect to clamd on LocalSocketclamd is stopped, still loading, or was killedStart it; check journalctl -u clamav-daemon and memory
*** The virus database is older than 7 days! ***Updates have been failingRead the freshclam log; check DNS, outbound HTTPS and a 429 cool-down
Error 429 and a cool-down time from freshclamToo many downloads from your addressWait it out; drop extra cron runs; use cvdupdate for many servers
Permission denied from clamdscanThe clamav user cannot read the fileAdd --fdpass
Out of memory: Killed process ... (clamd)Not enough RAM, often during a reloadConcurrentDatabaseReload 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.

Related articles

All guides