Mailcow ClamAV Virenscanner auslagern
Ich gehe hier darauf ein, wie man Mailcow: dockerized einen "externen" ClamAV als E-Mail Virenscanner geben kann. ClamAV ist sehr hungrig nach RAM, deshalb macht es Sinn auf einem kleinen System nur einen ClamAV als Shared Service laufen zu lassen.

ClamAV Shared Docker Container
Ich baue bei mir den ClamAV Container in meinen Toolstack mit ein. In diesem sind bereits einige Container, u.a.:
- Fail2ban-Dockerized: SSH und andere Dienste absichern per Docker Compose
- Watchtower - Docker Container automatisch aktualisieren
- Portainer Docker Installation
mkdir /opt/tools
cd /opt/tools
legt dort dann das .env und docker-compose.yml an, oder erweitert beides entsprechend:
.env
# Config File for Tools Application
# Docker Compose Project Name
# max length 11 characters
PROJECT_NAME=tools
# ClamAV Exposed Port Configuration
CLAMAV_PORT=3310
# Timezone
TZ=Europe/Berlin
docker-compose.yml
services:
clamav:
image: clamav/clamav-debian:${CLAMAV_VERSION:-stable}
restart: unless-stopped
ports:
- ${CLAMAV_PORT}:3310
volumes:
- clamav_db:/var/lib/clamav
# if you want to use custom clamd.conf, uncomment the following line
- ./data/clamav/conf/clamd.conf:/etc/clamav/clamd.conf:ro
environment:
- TZ=${TZ:-UTC}
labels:
com.centurylinklabs.watchtower.enable: true
healthcheck:
# Checks: clamd answers PONG to PING
test: ["CMD-SHELL", "echo PING | nc -w 5 127.0.0.1 3310 | grep -q PONG"]
interval: 30s
timeout: 10s
retries: 5
networks:
app-nw:
volumes:
clamav_db:
networks:
app-nw:
internal: false
driver: bridge
driver_opts:
com.docker.network.bridge.name: app-${PROJECT_NAME}
Dann legen wir noch die ClamAV Konfigdatei an. Könnt ihr auch einfach vom Mailcow kopieren /opt/mailcow-dockerized/data/conf/clamav/clamd.conf. hier aber eine Beispiel Konfiguration:
/opt/tools/data/clamav/conf/clamd.conf
#Debug true
#LogFile /dev/null
LogTime yes
LogClean yes
ExtendedDetectionInfo yes
PidFile /run/clamav/clamd.pid
OfficialDatabaseOnly no
LocalSocket /run/clamav/clamd.sock
TCPSocket 3310
StreamMaxLength 100M
MaxThreads 10
ReadTimeout 10
CommandReadTimeout 3
SendBufTimeout 200
MaxQueue 80
IdleTimeout 20
SelfCheck 3600
User clamav
Foreground yes
DetectPUA yes
# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md
#ExcludePUA NetTool
#ExcludePUA PWTool
#IncludePUA Spy
#IncludePUA Scanner
#IncludePUA RAT
HeuristicAlerts yes
ScanOLE2 yes
AlertOLE2Macros no
ScanPDF yes
ScanSWF yes
ScanXMLDOCS yes
ScanHWP3 yes
ScanMail yes
PhishingSignatures no
PhishingScanURLs no
HeuristicScanPrecedence yes
ScanHTML yes
ScanArchive yes
MaxScanSize 100M
MaxFileSize 100M
MaxRecursion 5
MaxFiles 200
Bytecode yes
BytecodeSecurity TrustSigned
BytecodeTimeout 1000
ConcurrentDatabaseReload no
und startet am Ende den Stack:
docker compose up -d
Mailcow Konfiguration
Es empfiehlt sich den Mailcow Stack als erstes einmal komplett zu stoppen:
cd /opt/mailcow
docker compose down
nun deaktivieren wir den Mailcow eigenen ClamAV Container:
/opt/mailcow/mailcow.conf
SKIP_CLAMD=y
und konfigurieren unseren Shared ClamAV Container:
/opt/mailcow/data/conf/rspamd/local.d/antivirus.conf
servers = "<FQDN-HOSTNAME>:3310";
Hinweis: Nutz hierfür den Fully Qualified Domain Name eures Docker Host Systems. Nun können wir den Stack wieder hochfahren:
docker compose up -d
Testen
Testen könnt ihr die Konfiguration mittels EICAR Test File . Schickt einfach eine Mail mit einem der Test Dateien an eure E-Mail Adresse. Ihr solltet dann zum Beispiel im Log des ClamAV Containers folgendes sehen:
clamav-1 | Sun Nov 9 12:04:31 2025 -> instream(172.21.0.1@34464): Eicar-Signature FOUND
das Log bekommt ihr so:
cd /opt/tools/
docker compose logs clamav