--- title: "How to Install and Configure ClamAV on Ubuntu 24.04" description: "Install ClamAV on Ubuntu 24.04, keep signatures updated with freshclam, scan files with clamd, and schedule a daily malware scan with a systemd timer." category: "Server Security" language: en source: https://cubepath.com/docs/server-security/clamav-configuration-antivirus-on-linux updated: 2026-09-25 --- # How to Install and Configure ClamAV on Ubuntu 24.04 ClamAV is an open-source antivirus engine used on Linux servers to detect malware, web shells, phishing kits and infected uploads. On a server it is most useful for scanning content that comes from outside: user uploads, web roots, mail and shared directories. In this tutorial you will install ClamAV on Ubuntu 24.04, keep its signature database current, run on-demand scans with both `clamscan` and the faster `clamd` daemon, and schedule a daily scan with a systemd timer. ## Prerequisites To follow this tutorial you need: - A server running Ubuntu 24.04 LTS, for example a CubePath VPS. - A non-root user with `sudo` privileges. - At least 2 GB of RAM. The `clamd` daemon keeps the full signature database in memory and uses around 1 to 1.5 GB on its own. - Outbound HTTPS access, so `freshclam` can download signature updates. ## Step 1 - Installing ClamAV ClamAV is split into several packages. `clamav` provides the command-line scanner `clamscan` and the updater `freshclam`, and `clamav-daemon` provides `clamd` plus its client `clamdscan`: ```bash sudo apt update sudo apt install clamav clamav-daemon ``` Check the installed version: ```bash clamscan --version ``` ```output ClamAV 1.4.3 ``` Once the signature database has been downloaded, the output also shows the database version and date. The packages install two systemd services: | Service | Purpose | |---------|---------| | `clamav-freshclam` | Downloads signature updates, by default up to 24 times per day | | `clamav-daemon` | Runs `clamd`, which loads the signatures once and scans files on request | ## Step 2 - Downloading the signature database The `clamav-freshclam` service starts right after installation and downloads the database in the background. The first download is about 300 MB, so give it a minute or two, then check its log: ```bash sudo tail -n 20 /var/log/clamav/freshclam.log ``` ```output daily.cvd database is up-to-date (version: 27770, sigs: 2074563, f-level: 90, builder: raynman) main.cvd database is up-to-date (version: 62, sigs: 6647427, f-level: 90, builder: sigmgr) bytecode.cvd database is up-to-date (version: 335, sigs: 86, f-level: 90, builder: raynman) ``` The database files live in `/var/lib/clamav`: ```bash ls -lh /var/lib/clamav ``` ```output -rw-r--r-- 1 clamav clamav 276K Sep 24 10:20 bytecode.cvd -rw-r--r-- 1 clamav clamav 60M Sep 24 10:20 daily.cvd -rw-r--r-- 1 clamav clamav 163M Sep 24 10:21 main.cvd ``` If you want to force an update by hand, stop the service first. `freshclam` refuses to run while the service holds its lock file: ```bash sudo systemctl stop clamav-freshclam sudo freshclam sudo systemctl start clamav-freshclam ``` Make sure the updater stays enabled: ```bash sudo systemctl is-enabled clamav-freshclam ``` ```output enabled ``` ## Step 3 - Starting the ClamAV daemon `clamd` does not start until the database exists. Now that it does, enable and start the daemon: ```bash sudo systemctl enable --now clamav-daemon ``` Loading the signatures takes 20 to 60 seconds depending on the CPU. Check the status: ```bash sudo systemctl status clamav-daemon ``` ```output ● clamav-daemon.service - Clam AntiVirus userspace daemon Loaded: loaded (/usr/lib/systemd/system/clamav-daemon.service; enabled; preset: enabled) Active: active (running) since Thu 2026-09-24 10:24:18 UTC; 45s ago ``` `clamd` listens on the local Unix socket `/var/run/clamav/clamd.ctl`. It does not open any network port, so no firewall change is needed. ## Step 4 - Running on-demand scans There are two ways to scan files, and it helps to know the difference: - `clamscan` is standalone. It loads the whole database every time it runs, which takes time and memory, but it needs no daemon. - `clamdscan` sends the files to the running `clamd`, which already has the database loaded. Scans start instantly. ### Testing detection with the EICAR file The EICAR test file is a harmless string that every antivirus engine detects on purpose. Create it in `/tmp`: ```bash echo 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > /tmp/eicar.txt ``` Scan it with `clamscan`: ```bash clamscan /tmp/eicar.txt ``` ```output /tmp/eicar.txt: Win.Test.EICAR_HDB-1 FOUND ----------- SCAN SUMMARY ----------- Known viruses: 8709823 Engine version: 1.4.3 Scanned directories: 0 Scanned files: 1 Infected files: 1 Time: 14.822 sec (0 m 14 s) ``` Now scan the same file through the daemon: ```bash clamdscan --fdpass /tmp/eicar.txt ``` ```output /tmp/eicar.txt: Win.Test.EICAR_HDB-1 FOUND ----------- SCAN SUMMARY ----------- Infected files: 1 Time: 0.004 sec (0 m 0 s) ``` The daemon answers in milliseconds instead of seconds. The `--fdpass` option passes an open file descriptor to `clamd`, so the daemon, which runs as the unprivileged `clamav` user, can scan files it would not otherwise have permission to read. Remove the test file: ```bash rm /tmp/eicar.txt ``` ### Scanning directories Scan a directory recursively and print only infected files: ```bash sudo clamdscan --fdpass --multiscan --infected /var/www ``` - `--multiscan` scans several files in parallel using the daemon's worker threads. - `--infected` (`-i`) prints only infected files instead of one `OK` line per file. `clamdscan` is recursive by default. With `clamscan`, add `-r`: ```bash sudo clamscan -r -i /home ``` Both commands return exit code `0` when nothing was found, `1` when at least one file is infected and `2` on errors, which makes them easy to use in scripts. > Warning: Avoid `--remove` until you trust the results on your data. A false positive would delete a legitimate file. Review detections first, or use `--move=/path/to/quarantine` to set suspicious files aside. ## Step 5 - Tuning the daemon configuration The daemon's settings live in `/etc/clamav/clamd.conf`. Open it: ```bash sudo nano /etc/clamav/clamd.conf ``` A few settings are worth reviewing on a server. Change the existing lines, or add them if they are missing: ```ini # Never descend into virtual filesystems ExcludePath ^/proc/ ExcludePath ^/sys/ ExcludePath ^/dev/ # Skip very large files that are unlikely to be malware and slow scans down MaxFileSize 100M MaxScanSize 400M # Number of parallel scanning threads MaxThreads 4 ``` `ExcludePath` takes a regular expression and can be repeated. Set `MaxThreads` close to the number of CPU cores you are willing to dedicate to scanning. Restart the daemon to apply the changes: ```bash sudo systemctl restart clamav-daemon ``` If the daemon fails to start, the log tells you which line is wrong: ```bash sudo journalctl -u clamav-daemon -n 30 --no-pager ``` ## Step 6 - Scheduling a daily scan A daily scan of the directories that receive external content catches malware that arrived since the last signature update. A systemd timer is a good fit: it logs to the journal and shows a failed state when something is found. Create a directory for scan reports: ```bash sudo mkdir -p /var/log/clamav/scans ``` Create the service unit: ```bash sudo nano /etc/systemd/system/clamav-scan.service ``` ```ini [Unit] Description=Daily ClamAV scan of web and home directories After=clamav-daemon.service Requires=clamav-daemon.service [Service] Type=oneshot Nice=10 IOSchedulingClass=idle ExecStart=/usr/bin/clamdscan --fdpass --multiscan --infected --log=/var/log/clamav/scans/daily.log /var/www /home ``` Adjust the directories at the end of `ExecStart` to the paths you want to scan. Create the timer unit: ```bash sudo nano /etc/systemd/system/clamav-scan.timer ``` ```ini [Unit] Description=Run the ClamAV scan every night [Timer] OnCalendar=*-*-* 03:30:00 RandomizedDelaySec=30m Persistent=true [Install] WantedBy=timers.target ``` Reload systemd and enable the timer: ```bash sudo systemctl daemon-reload sudo systemctl enable --now clamav-scan.timer ``` Check when it will next run: ```bash systemctl list-timers clamav-scan.timer ``` ```output NEXT LEFT LAST PASSED UNIT ACTIVATES Fri 2026-09-25 03:41:12 UTC 17h left - - clamav-scan.timer clamav-scan.service ``` Run the scan once by hand to test it: ```bash sudo systemctl start clamav-scan.service sudo systemctl status clamav-scan.service ``` If no infected files are found, the unit ends as `inactive (dead)` with `status=0/SUCCESS`. If ClamAV finds something, `clamdscan` exits with code 1 and the unit appears as failed, which you can spot with: ```bash systemctl --failed ``` The detections are listed in the report and in the journal: ```bash sudo journalctl -u clamav-scan.service -n 30 --no-pager ``` ## Troubleshooting **`clamdscan` says it cannot connect to clamd.** The daemon is not running or is still loading the database. Check `sudo systemctl status clamav-daemon`. If it keeps stopping, look for out-of-memory kills with `sudo journalctl -k | grep -i oom`: servers with less than 2 GB of RAM cannot hold the database. **`freshclam` fails with a lock error.** You ran it while the `clamav-freshclam` service was active. Stop the service before running `freshclam` by hand, as shown in Step 2. **`Permission denied` errors in scan results.** Add `--fdpass` to `clamdscan` and run it with `sudo`, so the file descriptors are opened with root privileges. **Scans are slow or overload the server.** Exclude large archives and backup directories with `ExcludePath`, lower `MaxThreads`, and keep scheduled scans limited to directories that receive external content. ## Conclusion ClamAV is now installed with automatic signature updates, a daemon ready for fast scans and a nightly scan of your web and home directories. ClamAV is one layer of defense and works best alongside keeping software patched and limiting who can write to your web root. As next steps, send the scan report to your monitoring or email when the scan unit fails, audit the rest of the system with Lynis, and integrate `clamdscan` into upload handling in your application.