How to Install and Configure ClamAV on Ubuntu Server: Automated Database Updates and Scheduled Malware Scans

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

At 2:00 AM, PagerDuty alerts go off non-stop. The WordPress web server’s CPU spikes to 100%, and outbound traffic hits 250 Mbps. An attacker just dropped a webshell into the wp-content/uploads directory to download and run a hidden Monero miner. In this scenario, ClamAV is the most practical open-source solution: available directly from the Ubuntu repository, completely free, and capable of detecting infected files immediately.

Quick Start: Installation and Scanning in 5 Minutes

If your server is experiencing unusual lag and you need to inspect suspicious files right away, open your terminal and run the following commands:

# 1. Update repositories and install ClamAV packages
sudo apt update
sudo apt install -y clamav clamav-daemon

# 2. Stop the freshclam service to prevent process lock conflicts
sudo systemctl stop clamav-freshclam

# 3. Fetch the latest virus signatures from Cisco Talos
sudo freshclam

# 4. Re-enable and restart the signature auto-update process
sudo systemctl start clamav-freshclam
sudo systemctl enable clamav-freshclam

# 5. Recursively scan the web directory, displaying only infected files
sudo clamscan -r -i /var/www/html

In the command above, the -r (recursive) flag scans deep into all subdirectories. The -i (infected) flag filters out hundreds of thousands of clean file log entries, printing only the files containing backdoors or trojans. For additional defense against hidden trojans and modified system binaries, you can also verify system integrity with debsums.

Understanding ClamAV Core Components

Once the fire is put out, it is important to understand how ClamAV actually works. This helps you avoid server crashes caused by memory exhaustion or disk I/O bottlenecks. Beyond immediate malware cleanup, running a comprehensive security audit with Lynis will help identify system weaknesses and harden your environment.

1. Comparing clamscan vs clamdscan

These two commands serve entirely different use cases:

  • clamscan (Standalone CLI): Each time it runs, it spends roughly 20–30 seconds just loading the entire virus signature database from disk into RAM. Once the scan finishes, the process terminates and frees the memory. This is handy for ad-hoc checks, but heavy on I/O and CPU if executed frequently.
  • clamdscan (Client/Server via Socket): Relies on clamav-daemon, which permanently keeps the database preloaded in RAM. When running clamdscan, the command simply sends the target file path through a local UNIX socket (/run/clamav/clamd.ctl) for the daemon to scan. Scanning speed is 5 to 10 times faster than clamscan.

2. Freshclam: Signature Update Mechanism

ClamAV’s malware signature database is maintained hourly by Cisco Talos. The configuration file is located at /etc/clamav/freshclam.conf. By default, the clamav-freshclam daemon checks for updates 24 times a day (once every hour) over HTTPS.

3. Fixing the Error: “freshclam is locked by another process”

If you run sudo freshclam right after installation, you will almost certainly encounter this error:

ERROR: /var/log/clamav/freshclam.log is locked by another process
ERROR: Problem database update failed.

The reason is simple: immediately after apt completes installation, Ubuntu automatically launches the clamav-freshclam service in the background. This service acquires an exclusive lock on both the log file and the database. To update manually, simply stop the service first:

sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam

Automating Scans and Email Alerts with Cron Jobs

Automatically quarantining infected files is a critical step to prevent malware from spreading before you can intervene. To block malicious activity and exploit attempts before backdoors are ever uploaded, consider deploying CrowdSec as an intrusion prevention system.

1. Creating a Quarantine Directory

Avoid using the --remove flag to delete files immediately, as this can lead to data loss from false positives (clean code mistakenly identified as malicious). Instead, move suspicious files to an isolated directory with strict permissions:

sudo mkdir -p /var/quarantine
sudo chmod 700 /var/quarantine

2. Writing an Automation Bash Script

Create an executable script at /usr/local/bin/clamav-auto-scan.sh:

sudo nano /usr/local/bin/clamav-auto-scan.sh

Add the following script content (requires the server to have mailutils or another mail utility configured):

#!/bin/bash

SCAN_TARGET="/var/www /home /tmp"
LOG_FILE="/var/log/clamav/daily-scan.log"
QUARANTINE_DIR="/var/quarantine"
DATE=$(date +"%Y-%m-%d %H:%M:%S")

echo "=== ClamAV scan started at: $DATE ===" >> "$LOG_FILE"

# Recursively scan, quarantine infected files, and skip virtual filesystems
clamscan -r -i \
    --move="$QUARANTINE_DIR" \
    --exclude-dir="^/sys" \
    --exclude-dir="^/proc" \
    --exclude-dir="^/dev" \
    --log="$LOG_FILE" \
    $SCAN_TARGET

INFECTED_COUNT=$(grep "Infected files:" "$LOG_FILE" | tail -n 1 | awk '{print $3}')

if [ "$INFECTED_COUNT" -gt 0 ]; then
    echo "[ALERT] $INFECTED_COUNT infected file(s) detected! Check immediately at $QUARANTINE_DIR" | mail -s "[ALERT] Virus detected on $(hostname)" [email protected]
fi

Grant execute permissions to the newly created script:

sudo chmod +x /usr/local/bin/clamav-auto-scan.sh

3. Scheduling a Nightly Cron Job

Open the root crontab with sudo crontab -e and add the scan schedule to run at 3:00 AM:

0 3 * * * /usr/local/bin/clamav-auto-scan.sh > /dev/null 2>&1

Production Resource Optimization Tips

Running antivirus software on a Linux server requires careful planning to prevent performance degradation on user-facing web services. Utilizing real-time system monitoring with Netdata helps you keep a close eye on CPU and I/O metrics while resource-intensive scans execute.

1. Lower Process Priority with nice and ionice

Scanning compressed .zip archives or directories with millions of small files (such as framework caches) can spike CPU usage to 100% and saturate disk I/O. Reduce the scan process priority to the lowest level:

nice -n 19 ionice -c 3 clamscan -r -i /var/www

This configuration instructs the OS scheduler to prioritize CPU for Nginx/PHP-FPM first. Additionally, disk bandwidth is allocated to ClamAV only when the disk is completely idle (Idle class – -c 3).

2. Managing RAM Overhead for clamav-daemon

ClamAV’s detection database currently contains over 8.5 million virus signatures. When loaded into memory, clamd actively consumes between 1.1 GB and 1.4 GB of RAM. On a VPS with only 1 GB or 2 GB of RAM, the Linux kernel’s OOM Killer will likely terminate MySQL to reclaim memory.

For servers with less than 2 GB of RAM:

  • Completely disable clamav-daemon (sudo systemctl disable --now clamav-daemon).
  • Create a swap file of at least 2 GB to buffer memory spikes.
  • Run only standalone clamscan via cron jobs during off-peak hours (between 2:00 AM and 4:00 AM).

3. Always Exclude Virtual Filesystems

If scanning the entire disk starting from the root directory (/), you must add exclusion flags: --exclude-dir="^/proc", --exclude-dir="^/sys", and --exclude-dir="^/dev". These directories contain virtual files created by the kernel in RAM. Scanning them traps ClamAV in infinite loops, saturates I/O, and can easily freeze your server.

Share: