Skip to content

Ansible role for ClamAV antivirus with scheduled scanning, on-access monitoring, quarantine management, log rotation, and Zabbix integration for Debian/Ubuntu systems.

License

Notifications You must be signed in to change notification settings

oxess/ansible-clamav

Repository files navigation

Ansible Role: ClamAV

An Ansible role for managing ClamAV antivirus on Debian-based systems. This role provides flexible malware protection through scheduled scanning, real-time on-access monitoring, or both.

Features

  • Scheduled Scanning: Automated periodic scans with configurable schedules
  • On-Access Monitoring: Real-time file scanning using clamonacc
  • Quarantine Management: Automatic isolation of infected files
  • Email Notifications: Alert on malware detection
  • Log Rotation: Automatic log management with configurable retention
  • Zabbix Monitoring: Integration with Zabbix agent for monitoring
  • Flexible Exclusions: Define paths and file extensions to skip

Requirements

  • Ansible 2.12 or higher
  • Debian-based operating system:
    • Debian 11 (Bullseye)
    • Debian 12 (Bookworm)
    • Debian 13 (Trixie)
    • Ubuntu 22.04 (Jammy)
    • Ubuntu 24.04 (Noble)

Installation

From Ansible Galaxy

ansible-galaxy install oxess.clamav

From Git Repository

git clone https://github.com/oxess/ansible-clamav.git roles/oxess.clamav

Role Variables

Scanning Mode

Variable Default Description
clamav_mode "scheduled" Scanning mode: scheduled, on-access, or both

Directories Configuration

Variable Default Description
clamav_scan_directories ["/var/www"] List of directories to scan
clamav_exclude_directories ["/var/www/prestashop/var/cache", "/var/www/prestashop/vendor"] Directories to exclude from scanning
clamav_exclude_extensions [".log", ".sql"] File extensions to exclude

Scheduled Scanning (Systemd Timer)

Scheduled scanning uses systemd timers for reliable, modern scheduling with security hardening.

Variable Default Description
clamav_scheduled_enabled true Enable/disable scheduled scanning
clamav_scheduled_hour "3" Hour to run scan (0-23)
clamav_scheduled_minute "0" Minute to run scan (0-59)
clamav_scheduled_weekday "*" Day(s) to run: * (daily), 0-6 (specific day), "0,3" (multiple)
clamav_scheduled_randomized_delay "5min" Random delay to spread load across systems
clamav_scheduled_oncalendar (auto) Override with explicit systemd OnCalendar format
clamav_scheduled_timeout (none) Optional maximum scan duration (e.g., "2h")

Note: The legacy variables (hour, minute, weekday) are automatically converted to systemd's OnCalendar format. You can override this by setting clamav_scheduled_oncalendar directly using systemd.time(7) syntax.

OnCalendar examples:

  • "*-*-* 03:00:00" - Daily at 3 AM
  • "Mon,Wed,Fri 02:30:00" - Mon/Wed/Fri at 2:30 AM
  • "weekly" - Weekly on Monday at midnight

On-Access Scanning

Variable Default Description
clamav_on_access_enabled false Enable/disable on-access scanning
clamav_on_access_mount_path "/var/www" Path to monitor for file access
clamav_on_access_include_pattern "" Pattern for files to include
clamav_on_access_exclude_uid "" UID to exclude (e.g., www-data)

ClamAV Daemon Settings

Variable Default Description
clamav_max_file_size "100M" Maximum file size to scan
clamav_max_scan_size "400M" Maximum scan size for archives
clamav_max_recursion 16 Maximum archive recursion depth
clamav_max_files 10000 Maximum files in archive to scan

Virus Definition Updates

Variable Default Description
clamav_freshclam_checks_per_day 12 Update checks per day (12 = every 2 hours)
clamav_freshclam_database_mirror "database.clamav.net" Mirror for virus definitions

Notifications and Logging

Variable Default Description
clamav_notify_email "" Email for notifications (empty = disabled)
clamav_log_file "/var/log/clamav/scan.log" Path to scan log file

Quarantine

Variable Default Description
clamav_quarantine_enabled true Enable quarantine for infected files
clamav_quarantine_dir "/var/quarantine" Quarantine directory path

Log Rotation

Variable Default Description
clamav_logrotate_enabled true Enable log rotation
clamav_log_retention_days 30 Days to retain logs

Zabbix Monitoring

Variable Default Description
clamav_zabbix_enabled "auto" Zabbix integration: auto, true, or false
clamav_zabbix_agent_conf_dir "/etc/zabbix/zabbix_agentd.conf.d" Zabbix agent config directory
clamav_zabbix_agent_service "zabbix-agent" Zabbix agent service name

Dependencies

None.

Example Playbooks

Use Case 1: Scheduled Scanning for Web Application

Protect a web application by scanning specified directories on a schedule. Useful for detecting malware uploaded through web forms or compromised files.

---
- name: Configure ClamAV for web application
  hosts: webservers
  become: true
  vars:
    # Scheduled scanning mode
    clamav_mode: "scheduled"

    # Directories to scan
    clamav_scan_directories:
      - "/var/www/myapp/uploads"
      - "/var/www/myapp/public"
      - "/home/deploy/shared"

    # Exclude cache and vendor directories (they change frequently)
    clamav_exclude_directories:
      - "/var/www/myapp/var/cache"
      - "/var/www/myapp/vendor"
      - "/var/www/myapp/node_modules"

    # Exclude common safe file types
    clamav_exclude_extensions:
      - ".log"
      - ".sql"
      - ".txt"

    # Run scan daily at 2:30 AM
    clamav_scheduled_hour: "2"
    clamav_scheduled_minute: "30"
    clamav_scheduled_weekday: "*"

    # Enable quarantine
    clamav_quarantine_enabled: true
    clamav_quarantine_dir: "/var/quarantine/clamav"

    # Send alerts to admin
    clamav_notify_email: "admin@example.com"

    # Keep logs for 60 days
    clamav_log_retention_days: 60

  roles:
    - role: oxess.clamav

Weekly scanning example (every Sunday at 4 AM):

---
- name: Weekly ClamAV scan
  hosts: webservers
  become: true
  vars:
    clamav_mode: "scheduled"
    clamav_scan_directories:
      - "/var/www"
    clamav_scheduled_hour: "4"
    clamav_scheduled_minute: "0"
    clamav_scheduled_weekday: "0"  # Sunday
  roles:
    - role: oxess.clamav

Use Case 2: On-Access Protection with Path Exclusions

Real-time protection that scans files as they are accessed. Ideal for high-security environments where immediate detection is critical.

---
- name: Configure ClamAV on-access protection
  hosts: fileservers
  become: true
  vars:
    # Enable on-access monitoring
    clamav_mode: "on-access"
    clamav_on_access_enabled: true

    # Monitor the main application directory
    clamav_on_access_mount_path: "/var/www/myapp"

    # Exclude web server user from scanning (prevents performance issues)
    # Get UID with: id -u www-data
    clamav_on_access_exclude_uid: "33"

    # Exclude directories that change frequently
    clamav_exclude_directories:
      - "/var/www/myapp/cache"
      - "/var/www/myapp/sessions"
      - "/var/www/myapp/tmp"
      - "/var/www/myapp/vendor"
      - "/var/www/myapp/node_modules"

    # Exclude safe file types
    clamav_exclude_extensions:
      - ".log"
      - ".pid"
      - ".sock"
      - ".lock"

    # Quarantine infected files immediately
    clamav_quarantine_enabled: true
    clamav_quarantine_dir: "/var/quarantine"

  roles:
    - role: oxess.clamav

Combined mode (both scheduled and on-access):

---
- name: Maximum protection with both scanning modes
  hosts: critical_servers
  become: true
  vars:
    # Enable both modes
    clamav_mode: "both"

    # On-access settings
    clamav_on_access_enabled: true
    clamav_on_access_mount_path: "/var/www"

    # Scheduled scan settings (nightly full scan)
    clamav_scheduled_enabled: true
    clamav_scheduled_hour: "3"
    clamav_scheduled_minute: "0"

    # Common exclusions
    clamav_exclude_directories:
      - "/var/www/cache"
      - "/var/www/vendor"

  roles:
    - role: oxess.clamav

Use Case 3: Zabbix Monitoring Integration

Monitor ClamAV health and scan results through Zabbix. Get alerts when infections are detected or services fail.

---
- name: Configure ClamAV with Zabbix monitoring
  hosts: monitored_servers
  become: true
  vars:
    clamav_mode: "scheduled"

    clamav_scan_directories:
      - "/var/www"
      - "/home"

    # Enable Zabbix integration
    # "auto" - enables if zabbix-agent is detected
    # "true" - always enable
    # "false" - disable
    clamav_zabbix_enabled: "auto"

    # Zabbix agent configuration (adjust if using non-standard paths)
    clamav_zabbix_agent_conf_dir: "/etc/zabbix/zabbix_agentd.conf.d"
    clamav_zabbix_agent_service: "zabbix-agent"

    # Schedule for frequent scans (better monitoring data)
    clamav_scheduled_hour: "*/6"  # Every 6 hours
    clamav_scheduled_minute: "0"

  roles:
    - role: oxess.clamav

Available Zabbix UserParameters

After deployment, these monitoring items become available:

UserParameter Description Values
clamav.scan.infected_count Infected files from last scan Integer (0 = clean)
clamav.scan.last_run Timestamp of last scan Unix epoch
clamav.scan.running Scan currently in progress 1 = running, 0 = idle
clamav.service.clamd ClamAV daemon status 1 = active, 0 = inactive
clamav.service.freshclam Freshclam service status 1 = active, 0 = inactive
clamav.definitions.age Virus definitions age Seconds since last update

Zabbix Template Recommendations

Create triggers for:

# Alert if infected files detected
{host:clamav.scan.infected_count.last()}>0

# Alert if ClamAV daemon is down
{host:clamav.service.clamd.last()}=0

# Alert if freshclam is down
{host:clamav.service.freshclam.last()}=0

# Alert if virus definitions are older than 24 hours
{host:clamav.definitions.age.last()}>86400

# Alert if no scan has run in 48 hours
{host:clamav.scan.last_run.now()}-{host:clamav.scan.last_run.last()}>172800

Complete Example: Production Web Server

A comprehensive example combining all features for a production environment:

---
- name: Production ClamAV configuration
  hosts: production_web
  become: true
  vars:
    # Use scheduled scanning (less performance impact)
    clamav_mode: "scheduled"

    # Scan user content directories
    clamav_scan_directories:
      - "/var/www/app/public/uploads"
      - "/var/www/app/storage"
      - "/home/deploy"

    # Exclude framework and build directories
    clamav_exclude_directories:
      - "/var/www/app/vendor"
      - "/var/www/app/node_modules"
      - "/var/www/app/storage/framework/cache"
      - "/var/www/app/storage/framework/sessions"
      - "/var/www/app/storage/framework/views"

    # Exclude common safe extensions
    clamav_exclude_extensions:
      - ".log"
      - ".sql"
      - ".lock"
      - ".cache"

    # Daily scan at 3 AM
    clamav_scheduled_enabled: true
    clamav_scheduled_hour: "3"
    clamav_scheduled_minute: "0"
    clamav_scheduled_weekday: "*"

    # Quarantine settings
    clamav_quarantine_enabled: true
    clamav_quarantine_dir: "/var/quarantine"

    # Email alerts
    clamav_notify_email: "security@example.com"

    # Logging
    clamav_log_file: "/var/log/clamav/scan.log"
    clamav_logrotate_enabled: true
    clamav_log_retention_days: 90

    # Zabbix monitoring
    clamav_zabbix_enabled: "auto"

    # Performance tuning
    clamav_max_file_size: "50M"
    clamav_max_scan_size: "200M"

    # Update virus definitions every 2 hours
    clamav_freshclam_checks_per_day: 12

  roles:
    - role: oxess.clamav

Tags

The role supports the following tags for selective execution:

Tag Description
clamav Run all ClamAV tasks
clamav:install Install ClamAV packages only
clamav:configure Configure ClamAV daemon only
clamav:scheduled Configure scheduled scanning only
clamav:on-access Configure on-access scanning only
clamav:logrotate Configure log rotation only
clamav:zabbix Configure Zabbix monitoring only
antivirus Alias for all ClamAV tasks

Tag Usage Examples

# Install and configure only (skip scheduled/on-access setup)
ansible-playbook site.yml --tags "clamav:install,clamav:configure"

# Update Zabbix monitoring configuration only
ansible-playbook site.yml --tags "clamav:zabbix"

# Configure scheduled scanning without touching other settings
ansible-playbook site.yml --tags "clamav:scheduled"

Testing

The role includes comprehensive Molecule tests.

Prerequisites

pip install -r requirements-test.txt

Running Tests

# Run full test suite on all platforms
molecule test

# Test on a specific platform
molecule test --platform-name debian-bookworm
molecule test --platform-name ubuntu-noble

# Development workflow (faster iteration)
molecule create    # Create test containers
molecule converge  # Apply the role
molecule verify    # Run verification tests
molecule destroy   # Clean up

Available Test Platforms

  • debian-bullseye (Debian 11)
  • debian-bookworm (Debian 12)
  • debian-trixie (Debian 13)
  • ubuntu-jammy (Ubuntu 22.04)
  • ubuntu-noble (Ubuntu 24.04)

Managing the Scheduled Scanner

The scheduled scan uses a systemd timer (clamav-scan.timer) and service (clamav-scan.service).

Check Timer Status

# View timer status and next scheduled run
systemctl status clamav-scan.timer

# List all timers including clamav-scan
systemctl list-timers clamav-scan.timer

# Show detailed timer configuration
systemctl show clamav-scan.timer --property=TimersCalendar

Manual Scan Execution

# Trigger an immediate scan (without waiting for timer)
systemctl start clamav-scan.service

# Watch the scan progress
journalctl -u clamav-scan.service -f

View Scan Logs

# View systemd journal logs
journalctl -u clamav-scan.service

# View the scan log file
tail -f /var/log/clamav/scan.log

Timer Management

# Temporarily disable the timer
systemctl stop clamav-scan.timer

# Re-enable the timer
systemctl start clamav-scan.timer

# Check if timer is enabled at boot
systemctl is-enabled clamav-scan.timer

Troubleshooting

Common Issues

Freshclam fails to update

Check network connectivity and mirror availability:

freshclam -v

Scheduled scan not running

Check the timer status and logs:

systemctl status clamav-scan.timer
systemctl status clamav-scan.service
journalctl -u clamav-scan.service --since "1 hour ago"

On-access scanning not working

Verify the clamonacc service:

systemctl status clamonacc
journalctl -u clamonacc -f

High CPU usage during scans

Reduce scan scope or add exclusions:

clamav_exclude_directories:
  - "/var/cache"
  - "/tmp"
clamav_max_file_size: "25M"

You can also set a timeout to limit scan duration:

clamav_scheduled_timeout: "1h"

Zabbix items not appearing

Restart Zabbix agent after role deployment:

systemctl restart zabbix-agent
zabbix_agentd -t clamav.service.clamd

Security Considerations

  • The quarantine directory (clamav_quarantine_dir) should have restricted permissions
  • Review excluded paths regularly to ensure malware can't hide in excluded locations
  • Email notifications require a properly configured MTA (sendmail/postfix)
  • On-access scanning requires root privileges for the clamonacc service
  • The scheduled scan service runs with systemd security hardening:
    • PrivateTmp=true - Isolated temporary directory
    • ProtectSystem=strict - Read-only system directories
    • ProtectHome=read-only - Read-only home directories
    • NoNewPrivileges=true - Prevents privilege escalation

License

MIT

Author

This Ansible Role was created by Mikołaj Jeziorny in 2025. Contact with me or open an issue if you have any questions or suggestions.

About

Ansible role for ClamAV antivirus with scheduled scanning, on-access monitoring, quarantine management, log rotation, and Zabbix integration for Debian/Ubuntu systems.

Topics

Resources

License

Stars

Watchers

Forks