Malware scanning with ClamAV

Starting in version 5.0.0, the ActivityInfo Self-managed Server can scan files that users upload to attachment fields for viruses and other malware using ClamAV, a widely-used open-source anti-virus engine. This article explains how scanning works and how to install and configure ClamAV alongside ActivityInfo.

How scanning works

ActivityInfo does not bundle ClamAV. Instead, it connects to a ClamAV daemon (clamd) that you install separately — either on the same machine or on another host reachable over the network. ActivityInfo talks to clamd over its local Unix domain socket (the default) or over a TCP connection.

When a user uploads a file, ActivityInfo stores it and then scans it in the background. Each attachment has one of the following statuses:

Status Meaning Served to users?
Pending Not yet scanned, or queued for a re-scan. Yes
Clean Scanned with no threat found. Yes
Infected ClamAV matched a known malware signature. No
Error ClamAV refused to process the file (for example, a malformed or corrupt file). No

Because scanning happens just after the upload completes, there is a brief window in which a freshly-uploaded file is **Pending ** and still downloadable. If the scanner is temporarily unreachable when a file is uploaded, the file stays Pending; a periodic background sweep automatically re-scans pending attachments once the scanner becomes available again, so no files are lost and you do not need to re-upload them.

Malware scanning is enabled by default. If you do not install ClamAV, uploads still succeed and are served, but they remain Pending (unscanned) until a scanner becomes reachable. To turn scanning off entirely, set Enabled = False in the [Malware] section of config.ini.

Installing ClamAV on Debian / Ubuntu

Install the ClamAV daemon from the distribution's package repository:

apt install -y clamav-daemon

Then start both services:

systemctl enable --now clamav-freshclam
systemctl enable --now clamav-daemon

On Debian and Ubuntu the daemon listens on the local Unix socket /var/run/clamav/clamd.ctl, which is exactly ActivityInfo's default. No [Malware] configuration is required — once the daemon is running, restart ActivityInfo and scanning is active.

Installing ClamAV on Red Hat / RHEL

ClamAV ships in the EPEL repository on RHEL 9 and its derivatives (AlmaLinux, Rocky Linux). Install EPEL and the ClamAV packages:

yum -y install epel-release
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9
yum -y install clamav clamd clamav-update

Both /etc/freshclam.conf and /etc/clamd.d/scan.conf ship with an Example sentinel line that prevents the services from starting until it is removed (or commented out).

In addition, ActivityInfo needs to reach clamd over a local TCP socket. Edit /etc/clamd.d/scan.conf so that the Example line is gone and the two TCP directives are uncommented and set as follows:

# /etc/clamd.d/scan.conf

# Remove (or comment out) the "Example" line that ships with the package.

# Listen on a local TCP socket so that ActivityInfo can connect.
TCPSocket 3310
TCPAddr 127.0.0.1

Then download the signature database and start both services:

freshclam
systemctl enable --now clamav-freshclam
systemctl enable --now clamd@scan

Then point ActivityInfo at the TCP socket by adding a [Malware] section to /opt/activityinfo/config.ini and restarting the activityinfo service:

[Malware]
Host=127.0.0.1
Port=3310

Running ClamAV as a Docker sidecar

If you run ActivityInfo as a Docker container, the simplest approach is to run the official clamav/clamav image as a sidecar service on the same Docker network and point ActivityInfo at it by service name. See the Traefik Configuration guide for a complete Docker Compose example that runs ActivityInfo and ClamAV together. The relevant environment variables are:

ACTIVITYINFO_MALWARE_ENABLED=true
ACTIVITYINFO_MALWARE_HOST=clamav
ACTIVITYINFO_MALWARE_PORT=3310

The clamav/clamav image runs freshclam on first start, which downloads the signature database and can take a few minutes. While it is downloading, the scanner reports as unreachable and ActivityInfo keeps newly-uploaded attachments **Pending **; the background sweep scans them once ClamAV is ready, so no health-gated startup ordering is required.

Configuration options

Scanning is configured in the [Malware] section of config.ini, and each option can also be supplied as an environment variable. See the [Malware] section of the Configuration file reference for the full list of options and their defaults.

Verifying that scanning is active

ActivityInfo exposes an unauthenticated health endpoint that reports whether the scanner is reachable. The response carries no information about specific files or users — only whether the scanner is running:

curl https://activityinfo.example.gov/resources/malware/status

The endpoint returns one of three states:

State Meaning
AVAILABLE The scanner is reachable and responded to a ping.
UNREACHABLE Scanning is enabled but the scanner did not respond. Check that clamd is running and that the configured socket or host and port are correct.
DISABLED Scanning is turned off in the configuration ([Malware] Enabled = False).

To confirm that detection works end-to-end, you can upload the harmless EICAR test file to an attachment field. ClamAV recognises it as malware, so within moments the attachment should be marked as Infected and become undownloadable.

Disabling scanning

To disable malware scanning entirely, set the following in config.ini and restart ActivityInfo:

[Malware]
Enabled=False

With scanning disabled, attachments are accepted and served without being scanned.

Next item
Explanation