Configure ClamAV antivirus scanning with automated threat detection and email alerts

Intermediate 25 min Apr 03, 2026 56 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Set up ClamAV daemon for real-time malware detection with automated scanning schedules, email notifications for threats, and optimized performance settings for production servers.

Prerequisites

  • Root or sudo access
  • Mail server (Postfix) for notifications
  • Minimum 2GB RAM for optimal performance
  • Network connectivity for virus definition updates

What this solves

ClamAV provides enterprise-grade antivirus protection for Linux servers, detecting malware, viruses, and suspicious files through signature-based scanning. This tutorial configures the ClamAV daemon with automated scanning schedules using systemd timers, email notifications for threat detection, and performance optimizations for production environments. You'll establish comprehensive malware protection that runs continuously in the background while maintaining system performance.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest security patches and ClamAV version.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install ClamAV and components

Install ClamAV daemon, command-line scanner, and update utilities for comprehensive antivirus protection.

sudo apt install -y clamav clamav-daemon clamav-freshclam clamav-unofficial-sigs
sudo dnf install -y clamav clamav-update clamav-scanner-systemd epel-release
sudo dnf install -y clamav-unofficial-sigs

Install mail utilities for alerts

Install mail transfer agent and utilities to send email notifications when threats are detected.

sudo apt install -y postfix mailutils
sudo dnf install -y postfix mailx
Note: When prompted, configure Postfix as "Internet Site" and set your server's FQDN as the mail name.

Stop services for initial configuration

Stop ClamAV services to perform initial configuration and virus database updates safely.

sudo systemctl stop clamav-freshclam
sudo systemctl stop clamav-daemon

Update virus definitions

Download the latest virus signatures and malware definitions before starting the daemon.

sudo freshclam
Note: This initial update may take several minutes to download the complete virus database.

Configure ClamAV daemon settings

Optimize ClamAV daemon configuration for performance and security scanning capabilities.

# Logging configuration
LogFile /var/log/clamav/clamav.log
LogTime yes
LogFileMaxSize 100M
LogRotate yes
LogVerbose yes

Network configuration

TCPSocket 3310 TCPAddr 127.0.0.1

Performance settings

MaxThreads 4 MaxQueue 200 IdleTimeout 120

Scanning options

ScanPDF yes ScanSWF yes ScanXMLDOCS yes ScanHWP3 yes ScanOLE2 yes ScanHTML yes ScanArchive yes ArchiveBlockEncrypted no

Size limits

MaxScanSize 150M MaxFileSize 50M MaxRecursion 10 MaxFiles 15000 MaxEmbeddedPE 40M MaxHTMLNormalize 40M MaxHTMLNoTags 8M MaxScriptNormalize 20M MaxZipTypeRcg 1M

Threat detection

DetectPUA yes DetectBrokenExecutables yes HeuristicScanPrecedence yes StructuredDataDetection yes

Exclude common false positives

ExcludePath ^/proc/ ExcludePath ^/sys/ ExcludePath ^/dev/ ExcludePath ^/var/lib/clamav/

User and permissions

User clamav AllowAllMatchScan yes Foreground no PidFile /run/clamav/clamd.pid LocalSocket /run/clamav/clamd.ctl

Configure automatic updates

Set up freshclam to automatically update virus definitions with optimized scheduling.

# Database mirror configuration
DatabaseMirror db.local.clamav.net
DatabaseMirror database.clamav.net

Update frequency (24 checks per day)

Checks 24 UpdateLogFile /var/log/clamav/freshclam.log LogVerbose yes LogTime yes LogFileMaxSize 50M LogRotate yes

Notification settings

OnUpdateExecute /usr/local/bin/clamav-notify-update.sh OnErrorExecute /usr/local/bin/clamav-error-notify.sh

Download settings

MaxAttempts 3 DNSDatabaseInfo current.cvd.clamav.net ConnectTimeout 60 ReceiveTimeout 60

Run as user

DatabaseOwner clamav PidFile /run/clamav/freshclam.pid

Create notification scripts

Set up email notification scripts for virus database updates and scanning alerts.

sudo mkdir -p /usr/local/bin
sudo chmod 755 /usr/local/bin
#!/bin/bash
echo "ClamAV virus database updated successfully at $(date)" | \
    mail -s "[$(hostname)] ClamAV Database Update" admin@example.com
#!/bin/bash
echo "ClamAV database update failed at $(date). Please check /var/log/clamav/freshclam.log" | \
    mail -s "[$(hostname)] ClamAV Update ERROR" admin@example.com
sudo chmod 755 /usr/local/bin/clamav-notify-update.sh
sudo chmod 755 /usr/local/bin/clamav-error-notify.sh

Create scanning script with threat alerts

Develop a comprehensive scanning script that sends detailed email notifications when threats are detected.

#!/bin/bash

Configuration

EMAIL="admin@example.com" LOGFILE="/var/log/clamav/scan.log" SCAN_DIRS=("/home" "/var/www" "/opt" "/srv") QUARANTINE_DIR="/var/quarantine/clamav"

Create quarantine directory

mkdir -p "$QUARANTINE_DIR" chmod 700 "$QUARANTINE_DIR" chown clamav:clamav "$QUARANTINE_DIR"

Start scan log entry

echo "[$(date)] Starting ClamAV system scan" >> "$LOGFILE"

Scan each directory

INFECTED_FILES=() for dir in "${SCAN_DIRS[@]}"; do if [[ -d "$dir" ]]; then echo "[$(date)] Scanning $dir" >> "$LOGFILE" SCAN_OUTPUT=$(clamdscan --multiscan --fdpass "$dir" 2>&1) echo "$SCAN_OUTPUT" >> "$LOGFILE" # Check for infections INFECTED=$(echo "$SCAN_OUTPUT" | grep " FOUND" | awk '{print $1}') if [[ -n "$INFECTED" ]]; then while IFS= read -r file; do INFECTED_FILES+=("$file") done <<< "$INFECTED" fi fi done

Handle infected files

if [[ ${#INFECTED_FILES[@]} -gt 0 ]]; then echo "[$(date)] THREAT DETECTED: ${#INFECTED_FILES[@]} infected files found" >> "$LOGFILE" # Quarantine infected files for file in "${INFECTED_FILES[@]}"; do if [[ -f "$file" ]]; then BASENAME=$(basename "$file") QUARANTINE_FILE="$QUARANTINE_DIR/${BASENAME}.$(date +%Y%m%d-%H%M%S)" mv "$file" "$QUARANTINE_FILE" 2>/dev/null echo "[$(date)] Quarantined: $file -> $QUARANTINE_FILE" >> "$LOGFILE" fi done # Send threat notification email { echo "SECURITY ALERT: ClamAV detected malware on $(hostname)" echo "" echo "Date: $(date)" echo "Infected files found: ${#INFECTED_FILES[@]}" echo "" echo "Infected files (now quarantined):" printf '%s\n' "${INFECTED_FILES[@]}" echo "" echo "Files have been moved to: $QUARANTINE_DIR" echo "" echo "Full scan log: $LOGFILE" echo "" echo "Please investigate immediately and run additional security checks." } | mail -s "[SECURITY] Malware detected on $(hostname)" "$EMAIL" else echo "[$(date)] Scan completed - no threats detected" >> "$LOGFILE" fi
sudo chmod 755 /usr/local/bin/clamav-scan.sh

Set up log rotation

Configure logrotate to manage ClamAV log files and prevent disk space issues.

/var/log/clamav/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    copytruncate
    create 644 clamav clamav
    postrotate
        /bin/kill -HUP cat /run/clamav/clamd.pid 2>/dev/null 2>/dev/null || true
    endscript
}

Create systemd timer for automated scanning

Set up systemd service and timer units for automated daily malware scanning.

[Unit]
Description=ClamAV System Scan
Requires=clamav-daemon.service
After=clamav-daemon.service

[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/clamav-scan.sh
StandardOutput=journal
StandardError=journal
[Unit]
Description=Run ClamAV scan daily at 2 AM
Requires=clamav-scan.service

[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true
RandomizedDelaySec=1800

[Install]
WantedBy=timers.target

Create log directories and set permissions

Ensure proper log directory structure with correct ownership for ClamAV operations.

sudo mkdir -p /var/log/clamav
sudo mkdir -p /var/quarantine/clamav
sudo chown clamav:clamav /var/log/clamav
sudo chown clamav:clamav /var/quarantine/clamav
sudo chmod 755 /var/log/clamav
sudo chmod 700 /var/quarantine/clamav
Never use chmod 777. It gives every user on the system full access to your files. Instead, fix ownership with chown and use minimal permissions like 755 for directories and 644 for files.

Enable and start ClamAV services

Start ClamAV daemon and freshclam services, then enable the automated scanning timer.

sudo systemctl enable --now clamav-freshclam
sudo systemctl enable --now clamav-daemon
sudo systemctl enable --now clamav-scan.timer
sudo systemctl daemon-reload

Configure firewall rules

Set up firewall rules to allow ClamAV daemon access while maintaining security. Similar to network security hardening discussed in our Linux firewall configuration tutorial.

sudo ufw allow from 127.0.0.1 to any port 3310
sudo ufw reload
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="127.0.0.1" port protocol="tcp" port="3310" accept'
sudo firewall-cmd --reload

Performance optimization and exclusions

Configure performance-based exclusions

Add directory exclusions for system paths and high-I/O areas to improve scanning performance.

# Add these exclusions to the existing configuration

Temporary and cache directories

ExcludePath ^/tmp/ ExcludePath ^/var/tmp/ ExcludePath ^/var/cache/

Database directories (if applicable)

ExcludePath ^/var/lib/mysql/ ExcludePath ^/var/lib/postgresql/ ExcludePath ^/var/lib/redis/

Log directories

ExcludePath ^/var/log/

Container runtime directories

ExcludePath ^/var/lib/docker/ ExcludePath ^/var/lib/containerd/

Backup directories (scan separately if needed)

ExcludePath ^/backup/ ExcludePath ^/var/backups/

Optimize memory usage

Configure memory limits and threading for optimal performance on your system resources.

# Check available memory
free -h

Adjust MaxThreads based on CPU cores

nproc
# Memory optimization (adjust based on available RAM)

For systems with 4GB+ RAM

MaxThreads 4 MaxQueue 200

For systems with 2GB RAM

MaxThreads 2

MaxQueue 100

For systems with 8GB+ RAM

MaxThreads 8

MaxQueue 400

Verify your setup

# Check ClamAV daemon status
sudo systemctl status clamav-daemon

Check freshclam update service

sudo systemctl status clamav-freshclam

Verify scanning timer is active

sudo systemctl status clamav-scan.timer sudo systemctl list-timers clamav-scan.timer

Test daemon connectivity

clamdscan --version echo "X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*" > /tmp/eicar.txt clamdscan /tmp/eicar.txt rm -f /tmp/eicar.txt

Check recent logs

sudo tail -f /var/log/clamav/clamav.log sudo tail -f /var/log/clamav/freshclam.log

Verify quarantine directory

ls -la /var/quarantine/clamav/

Monitor scan logs and quarantine management

Set up log monitoring script

Create a monitoring script to track scanning statistics and system health.

#!/bin/bash

echo "=== ClamAV System Status ==="
echo "Date: $(date)"
echo ""

echo "Service Status:"
systemctl is-active clamav-daemon
systemctl is-active clamav-freshclam
systemctl is-active clamav-scan.timer

echo ""
echo "Database Information:"
sigtool --info /var/lib/clamav/main.cvd | head -5
sigtool --info /var/lib/clamav/daily.cvd | head -5

echo ""
echo "Recent Scan Activity (last 10 entries):"
tail -10 /var/log/clamav/scan.log | grep "\[.*\]"

echo ""
echo "Quarantined Files:"
ls -la /var/quarantine/clamav/ | wc -l
echo "files in quarantine"

echo ""
echo "Memory Usage:"
ps aux | grep -E "(clamd|freshclam)" | grep -v grep
sudo chmod 755 /usr/local/bin/clamav-status.sh

Create quarantine management script

Develop a script for safely managing quarantined files and reviewing threats.

#!/bin/bash

QUARANTINE_DIR="/var/quarantine/clamav"
LOG_FILE="/var/log/clamav/quarantine.log"

case "$1" in
    list)
        echo "Quarantined files:"
        ls -la "$QUARANTINE_DIR"
        ;;
    clean)
        echo "Cleaning quarantine older than 30 days..."
        find "$QUARANTINE_DIR" -type f -mtime +30 -exec rm {} \;
        echo "[$(date)] Cleaned old quarantine files" >> "$LOG_FILE"
        ;;
    restore)
        if [[ -z "$2" ]]; then
            echo "Usage: $0 restore "
            exit 1
        fi
        RESTORE_FILE="$QUARANTINE_DIR/$2"
        if [[ -f "$RESTORE_FILE" ]]; then
            echo "Restoring $2 to /tmp/ for analysis"
            cp "$RESTORE_FILE" "/tmp/$2.restored"
            echo "[$(date)] Restored $2 to /tmp/ for analysis" >> "$LOG_FILE"
        else
            echo "File not found in quarantine"
        fi
        ;;
    *)
        echo "Usage: $0 {list|clean|restore }"
        echo "  list    - Show quarantined files"
        echo "  clean   - Remove files older than 30 days"
        echo "  restore - Copy file to /tmp for analysis"
        ;;
esac
sudo chmod 755 /usr/local/bin/clamav-quarantine.sh

Common issues

SymptomCauseFix
Daemon won't startConfiguration syntax errorsudo clamconf -n to check config validity
Database update failsNetwork connectivity or mirror issuesCheck /var/log/clamav/freshclam.log and test ping database.clamav.net
High CPU usage during scanToo many scan threads for systemReduce MaxThreads in /etc/clamav/clamd.conf
Permission denied errorsIncorrect file ownershipsudo chown -R clamav:clamav /var/log/clamav
Email notifications not workingPostfix not configured properlyTest with echo "test" | mail -s "test" admin@example.com
Large files not scannedSize limits too restrictiveIncrease MaxScanSize and MaxFileSize in config
Scan taking too longNo exclusions for system directoriesAdd appropriate ExcludePath entries for system dirs
Socket connection refusedClamAV daemon not runningsudo systemctl restart clamav-daemon

Next steps

Automated install script

Run this to automate the entire setup

#clamav #antivirus #malware-detection #automated-scanning #email-alerts

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer