Skip to content

Latest commit

 

History

History
640 lines (476 loc) · 17.9 KB

File metadata and controls

640 lines (476 loc) · 17.9 KB

Ansible Role: ClamAV

CI Ansible Galaxy Repository License

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
clamav_freshclam_custom_databases [] List of custom unofficial database URLs

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

Use Case 4: Custom Third-Party Signature Databases

Extend ClamAV's detection capabilities with unofficial signature databases from trusted sources like Malware.Expert and Linux Malware Detect.

---
- name: Configure ClamAV with custom signature databases
  hosts: webservers
  become: true
  vars:
    clamav_mode: "scheduled"

    clamav_scan_directories:
      - "/var/www"

    # Add third-party signature databases for enhanced detection
    clamav_freshclam_custom_databases:
      # Malware.Expert signatures
      - "https://cdn.malware.expert/malware.expert.ndb"
      - "https://cdn.malware.expert/malware.expert.hdb"
      - "https://cdn.malware.expert/malware.expert.ldb"
      - "https://cdn.malware.expert/malware.expert.fp"
      # Linux Malware Detect (rfxn) signatures
      - "https://cdn.rfxn.com/downloads/rfxn.ndb"
      - "https://cdn.rfxn.com/downloads/rfxn.hdb"
      - "https://cdn.rfxn.com/downloads/rfxn.yara"

    # More frequent updates for additional databases
    clamav_freshclam_checks_per_day: 24

  roles:
    - role: oxess.clamav

Note: Third-party databases may have different licensing terms. Verify the terms of use before deploying in production environments.

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.