Content for both STEM and Humanities!
Use the texts, as long as you talk about me (good or bad)... and if it's for commercial purposes: I want my share!
Read the entire article before executing any commands, and follow the commands in the order presented in the article, unless you know what you are doing.
This article, in addition to installing and configuring ClamAV, serves educational purposes for learning.
This is an explanatory article for the purpose of understanding ClamAV, and it has been tested multiple times for the intended purpose of the article.
Someone might say, "Why would you need an antivirus on Linux?"; However, viruses for Linux do exist, but since Linux isn't widely used as a desktop, nobody makes viruses specifically for it. Furthermore, with the advent of AI, some extra protection is necessary on desktops and, especially, on servers.
ClamAV is an open-source (GPLv2) antivirus toolkit designed specifically for email scanning on email servers. It provides several utilities including a flexible and scalable multi-threaded daemon, a command-line scanner, and an advanced tool for automatic database updates. The core of the package is an antivirus engine available as a shared library.
ClamAV® is a powerful open-source antivirus engine for detecting Trojans, viruses, malware, and other malicious threats. ClamAV does not have a "quick scan" mode. ClamAV is a malware detection toolset, not a traditional antivirus or endpoint security suite.
It's up to you to decide what to scan. A full system scan will take a long time with ClamAV or any other antivirus software.
Clamscan, ClamOnAcc, and Clamdscan include the "--remove" option to delete any file that generates alerts during a scan. This is generally a very bad idea unless you are monitoring an uploads/downloads directory. False positives happen! You don't want the wrong file to be accidentally deleted. Instead, consider using the "--move" parameter or perhaps just "--copy" and set up a script with the "VirusEvent" feature to notify you when something is detected.
ClamAV includes an email filtering tool called clamav-milter. This tool interacts directly with Clamd, and therefore requires a running Clamd instance to operate. However, the configuration and log files for clamav-milter are separate from those of Clamd.
NOTICE
ClamAV comes minimally configured; you must configure it manually according to your scenario and needs. If you are one of those greasy, smelly souls who like to say, "No way am I going to go through all this trouble to configure a program," stop reading this article here and go bang your head against the wall, or stick your face in a fan repeatedly, or go do whatever you like to do, but clearly, your place is not here.
At the end there is a summary with the commands and little explanation.
CONFIG_FANOTIFY=y
# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set
So it's enabled, but access verification will be restricted to notification-only mode, meaning it will warn you about viruses but will do absolutely nothing.
If you see "CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set," fanotify is not enabled in your kernel, so you will need to recompile the kernel to enable it or install a more modern kernel, but this will not be shown here as it is time-consuming and outside the scope of this article.
It's unlikely you'll get "CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set" because "CONFIG_FANOTIFY=y" is enabled by default in the x86 architecture in
Linux
Kernel version 2.6.37, and "CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y" is enabled by default in the generic x86 defconfig in Linux Kernel version 3.14.
The configuration of the clamav-milter.conf file will not be modified; we will leave it with the default settings. ClamAV-Milter is the ClamAV application that provides email filtering; it's not necessary if the Linux machine is not an email server. For desktops, installation is not required, but it's a matter of preference.
Updating and installing (adapt to your distribution):
sudo xbps-install -Syu
sudo xbps-install clamav
Name Action Version New version Download size
clamav install - 1.5.3_1 40MB
Size to download: 40MB
Size required on disk: 182MB
Space available on disk: 5405MB
[*] Configuring unpacked packages
clamav-1.5.3_1: configuring ...
Created _clamav system group.
Created _clamav system user.
clamav-1.5.3_1: installed successfully.
Note: In some distributions, it will be located in the path
/etc/clamav; verify the correct path.
Suggested search:
sudo find / | grep freshclam.conf
If you already have files from a previous installation and did not
want to remove them to preserve your settings, the installation
preserves the files and creates new ones with the following naming
convention:
Verify that the ClamAV user and group have been created:
cut -d: -f1 /etc/passwd
cut -d: -f1 /etc/group
If it hasn't already been created in your
distribution, create the user (in Void, when installing ClamAV, the
_clamav user and group are created automatically, so you can skip
these two commands):
The ClamAV Daemon, or Clamd, is a multithreaded daemon
that uses libclamav to scan files for viruses. ClamAV provides several
tools that interact with this daemon.
These include:
Clamdscan
- a simple scanning client;
Clamonacc
- provides real-time scanning (also known as real-time protection
via a Clamd instance);
Clamav-milte
r - an email filtering plugin for the Sendmail email processing
server software, which allows you to analyze emails;
Clamdtop
- a resource monitoring interface for Clamd.
ClamAV also provides a command-line tool for simple
scanning tasks using libclamav, called Clamscan. Unlike the Clamd
daemon, Clamscan is not a persistent process and is better suited for
use cases where a single scan with minimal configuration is required.
The more complex tools provided by ClamAV require some
degree of configuration. ClamAV provides three files with example
configurations:
🔵clamd.conf: to configure the behavior of the ClamAV Daemon and
associated tools;
🟢freshclam.conf: to configure the behavior of the signature
database update tool;
🟡clamav-milter.conf: to configure ClamAV's email filtering
behavior for the email server, which interacts directly with
Clamd.
In addition, a tool called clamconf allows users to
verify the settings used by each of the other tools, obtaining
information from the configuration files listed above, along with
other relevant information.
clamconf
Clamconf displays all configurations:
clamconf --help
man clamconf
man clamd
man clamonacc
man clamscan
man clamdscan
Depending on the installation method and operating
system, some configuration options may already be pre-configured. In
Void, all configuration files are commented out, except for the User
line in the clamd.conf file.
However, depending on the distribution, you may need
to create new configuration files or modify existing ones with
custom settings that make more sense for your use case.
For your information, an installation from source
code will require you to create a freshclam.conf file before
using Freshclam, a "clamd.conf" file before using Clamd, and a
"clamav-milter.conf" file before using ClamAV-Milter.
The files freshclam.conf, clamd.conf, and
clamav-milter.conf are the main configuration files for ClamAV
antivirus.
The parameter "DatabaseDirectory /var/lib/_clamav"
must be the same in both the freshclam.conf and clamd.conf
files. If you change it in one, you must also change it in the
other. I advise leaving it as the default.
In some distributions it is /var/lib/clamav,
without the underscore.
NOTICE
"The mirrors and links reserve the right to block
your IP address if you abuse downloads and updates too
frequently per hour or abuse the server in any way."
Update your databases and subscriptions
wisely.
The Freshclam tool is used to download and update
the official ClamAV virus signature databases.
Note: On systems where SELinux is enabled, you
will likely need to define the correct SELinux context;
otherwise, the Freshclam service will not be able to access the
file.
Below are the contents of the freshclam.conf and
clamd.conf files, both in a functional state and with mirrors to
virus and malware databases in general.
Freshclam
is the automatic database update tool for Clam AntiVirus.
It can be configured to work in two modes:
Interactive - on-demand from the command line;
daemon - silently in the background.
Here we will make it interactive using Cron.
FRESHCLAM.CONF
I use vim, use your preferred editor.
sudo vim /etc/freshclam.conf
Comment out or remove line ~8:
# Comment or remove the line below.
# Example ... <<< Line 8
Uncomment and configure the parameters below (or
leave everything commented out and add it at the end).
Note: On line 92, comment out "DatabaseMirror
database.clamav.net", as it is already below.
# Comment or remove the line below.
# Example ... <<< Line 8
Uncomment and configure the parameters below (or
leave everything commented out and add them at the end).
Note: Be sure to check if the ClamAV user in your
distribution is clamav or _clamav and change it below in the
User line. And in place of "your_username" put your username
(OnAccessIncludePath /home/your_username/Downloads).
Check line 269 (User _clamav) and comment it out if you are
adding everything below.
Note: If you decide to enable Clamonacc later, I
advise against enabling
#OnAccessIncludePath /home
and
#OnAccessIncludePath /home/username
because it may cause freezes when opening these folders
graphically (by clicking with the mouse), and it may happen that
when opening the user folder, the folder and file icons
disappear, giving the impression that everything has been
deleted. If this happens, simply disable Clamonacc (sudo sv stop
clamonacc). Clamonacc (Real-Time Protection) exerts a very large
amount of control over the configured directories and
files.
Inotify has a limited number of control points
available for use by a process at any given time. To increase
the number of
inotifywatch-points
available for use by ClamAV, run:
To test:
sudo echo 104857600 | sudo tee -a /proc/sys/fs/inotify/max_user_watches
Exit: 104857600
Permanent:
sudo echo 'fs.inotify.max_user_watches=104857600' | sudo tee /etc/sysctl.d/99-inotify.conf
Output:
fs.inotify.max_user_watches=104857600
NOTICE
The number there is 100M converted to bytes. This
number must be the same as the OnAccessMaxFileSize parameter. If
you change the number in the OnAccessMaxFileSize parameter, you
must run this command again with the new number.
The biggest threat from a quarantine is a user or
script accidentally executing an infected binary that's inside
it.
The most robust way to prevent this in
Linux
is to isolate the directory in a separate mount (or using a loop
device) with the
noexec
flag .
Let's apply a "bind mount" to
/etc/fstab.
sudo vim /etc/fstab
Add the following line at the end to apply strict
security restrictions (
noexec , nosuid
, and
nodev
prevent the execution of programs, SUID binaries, and the creation
of devices):
Creating a cleanup script that preserves the
quarantine.log and logrotate files and cleans up the others:
sudo vim /usr/local/bin/limpar-quarentena.sh
Place inside:
#!/bin/sh# Script para remover arquivos da quarentena do ClamAV com mais de 30 diasPASTA_GERAL="/var/opt/clamav-quarentena"DIAS_LIMITE=30# Verifica se o diretório existe antes de tentar limparif [ -d "$PASTA_GERAL" ]; then# Procura por arquivos comuns (-type f) modificados há mais de 30 dias (-mtime +30) e os remove, EXCETO o log, os compactados (.gz) e arquivos ocultos do script find "$PASTA_GERAL" -type f -mtime +$DIAS_LIMITE \ ! -name "quarentena.log" \ ! -name "quarentena.log.*" \ ! -name ".*" \ -deletefi
#!/bin/sh# Configuracoes#PASTA_GERAL="/var/opt/clamav-quarentena"ARQUIVO_ESTADO="$PASTA_GERAL/.ultimo_total"LOG="$PASTA_GERAL/quarentena.log"# EMAIL_DESTINO="seu_email@dominio.com" # <- Altere para teu e-mail# Garante que o arquivo de estado existaif [ ! -f "$ARQUIVO_ESTADO" ]; then runuser -u _clamav -- touch "$ARQUIVO_ESTADO" echo 0 | runuser -u _clamav -- tee "$ARQUIVO_ESTADO" > /dev/nullfi# Conta quantos arquivos existem atualmente na quarentenatotal_atual=$(find "$PASTA_GERAL" -type f ! -name "quarentena.log" ! -name ".*" | wc -l)total_anterior=$(cat "$ARQUIVO_ESTADO")# Se o numero atual for maior que o anterior, ha novos arquivosif [ "$total_atual" -gt "$total_anterior" ]; then novos_arquivos=$((total_atual - total_anterior))# Lista os nomes dos arquivos mais recentes que entraram na quarentena arquivos_novos=$(find "$PASTA_GERAL" -type f ! -name "quarentena.log" ! -name ".*" -printf "%T@ %f\n" | sort -n | tail -n "$novos_arquivos" | cut -d' ' -f2-)# Monta a estrutura do e-mail com os cabecalhos que o msmtp precisa# assunto="[ClamAV] ALERTA: Novo(s) malware(s) isolado(s) na quarentena"# (# echo "Subject: $assunto"# echo "To: $EMAIL_DESTINO"# echo "Content-Type: text/plain; charset=UTF-8"# echo "" # Linha em branco obrigatoria separando cabecalho do corpo# echo "Olá,"# echo ""# echo "O sistema de monitoramento detectou $novos_arquivos novo(s) arquivo(s) na pasta de quarentena."# echo ""# echo "Lista de arquivos detectados:"# echo "$arquivos_novos"# echo ""# echo "Por favor, verifique o servidor."# echo "Data do evento: $(date '+%d/%m/%Y %H:%M:%S')"# ) | msmtp -C /etc/msmtprc "$EMAIL_DESTINO"# --- Popup na area de trabalho (Void Linux, sem systemd/loginctl) ---# 1. Descobre o usuario com sessao grafica ativa (registrado no utmp como :0, :1 etc.) usuario=$(who | awk '/\(:[0-9]+(\.[0-9]+)?\)/ {print $1; exit}') if [ -n "$usuario" ]; then display="" dbus_addr=""# 2. Varre os processos do usuario procurando DISPLAY e DBUS_SESSION_BUS_ADDRESS no environ for p in /proc/[0-9]*; do pid=${p#/proc/} dono=$(stat -c %U "$p" 2>/dev/null) [ "$dono" != "$usuario" ] && continue if [ -r "$p/environ" ] && tr '{BARRA}0' '\n' < "$p/environ" 2>/dev/null | grep -q '^DISPLAY='; then display=$(tr '{BARRA}0' '\n' < "$p/environ" | grep '^DISPLAY=' | head -n1 | cut -d= -f2-) dbus_addr=$(tr '{BARRA}0' '\n' < "$p/environ" | grep '^DBUS_SESSION_BUS_ADDRESS=' | head -n1 | cut -d= -f2-) [ -n "$display" ] && [ -n "$dbus_addr" ] && break fi done# Fallbacks, caso a varredura nao encontre nada [ -z "$display" ] && display=":0" if [ -z "$dbus_addr" ]; then uid_usuario=$(id -u "$usuario") socket_dbus=$(find /run/user/"$uid_usuario"/dbus-1 -type s -name 'bus' 2>/dev/null | head -n1) if [ -n "$socket_dbus" ]; then dbus_addr="unix:path=$socket_dbus" fi fi# Mensagem com Zenity# if [ -n "$dbus_addr" ]; then# runuser -u "$usuario" -- env DISPLAY="$display" DBUS_SESSION_BUS_ADDRESS="$dbus_addr" \# zenity --error --title="ClamAV - Quarentena" --width=450 \# --text="<span foreground='red' size='large'><b>AVISO: ClamAV - Quarentena!</b></span>\n\n$novos_arquivos novo(s) arquivo(s) detectado(s).\nVerifique o e-mail ou o log." \# 2>/dev/null &# fi# Mensagem com notify-send if [ -n "$dbus_addr" ]; then runuser -u "$usuario" -- env DISPLAY="$display" DBUS_SESSION_BUS_ADDRESS="$dbus_addr" \ notify-send -u critical -i /usr/share/icons/icone-alerta.png \ "ClamAV - Quarentena" \ "<b>AVISO: $novos_arquivos novo(s) arquivo(s) detectado(s).\nVerifique e-mail e /var/opt/clamav-quarentena/quarentena.log.</b>" & fi fi mensagem="ALERTA: $novos_arquivos novo(s) arquivo(s) isolado(s):\n$arquivos_novos"# 1. Monta a linha com a data atual linha_log="$(date '+%Y-%m-%d %H:%M:%S') -> $mensagem"# 2. Grava no arquivo de log com o usuário _clamav e exibe mensagem no terminal# echo "$linha_log" | runuser -u _clamav -- tee -a "$LOG"# Grava no arquivo de log e não exibe mensagem no terminal echo "$linha_log" | runuser -u _clamav -- sh -c 'cat >> "$1"' _ "$LOG"fi# Atualiza o arquivo de estadoecho "$total_atual" | runuser -u _clamav -- tee "$ARQUIVO_ESTADO" > /dev/null
Save and exit.
This warning script is just an example; it's up to you
to adapt it to your email provider and settings, as this is not the
scope of the article.
The lines:
EMAIL_DESTINO
and the
subject line =
until
) | msmtp
are commented out for testing purposes without needing to configure
email sending; it will only display the warning popup on the screen,
which will remain until you click on it.
We see the alert message with Notify-send and XFCE.
Alert message with Cinnamon and Notify-send.
I prefer Notify-send because it stays on the
screen until you click on the notification and doesn't minimize
if you click outside of it, like Zenity does.
There must be 4 files and this is the only one that
should be in root:
drwxr-xr-x 1 root root 34 21 09:02 ..
The others must be owned by the user _clamav.
If ClamAV detects malware in a scan and moves it to
quarantine, these files may be owned by another user, however, the
4 basic files must be in this format.
In XFCE, if you want to enhance the alert layout with notify-send,
run:
sudo xfce4-notifyd-config
And then restart:
sudo pkill xfce4-notifyd
There are few options, but the advantage is that
the alert stays on the screen until you click on it.
With Zenity, the alert allows for a better layout,
but clicking outside of it minimizes it, and you might forget,
turn off the machine, and not check your email or log.
It's up to you to choose the best option for your
taste: notify-send or zenity.
In
Cinnamon
, the path is: Menu > System Settings > in the
"Preferences" section, click on Notifications.
At the terminal:
cinnamon-settings notifications
Creating a quarantine log file
sudo vim /usr/local/bin/notificar-virus.sh
#!/bin/sh# Recebe as variaveis nativas do ClamAVPASTA_GERAL="/var/opt/clamav-quarentena"LOG_ARQUIVO="$PASTA_GERAL/quarentena.log"mensagem="ALERTA EM TEMPO REAL (/usr/local/bin/notificar-virus.sh): Arquivo suspeito '$CLAM_VIRUSEVENT_FILENAME' detectado e isolado (Vírus: $CLAM_VIRUSEVENT_VIRUSNAME)."# Grava imediatamente no log com o usuario _clamavecho "$(date '+%Y-%m-%d %H:%M:%S') -> $mensagem" | runuser -u _clamav -- tee -a "$LOG_ARQUIVO"
This file is located in the
/etc/clamd.conf
settings (
VirusEvent /usr/local/bin/notify-virus.sh
).
Since the periodic script
/usr/local/bin/monitor-quarentena.sh
configured in Cron reads the number of files in the folder and
compares it with the previous state (
.ultimo_total
), it will also notice that a new file has arrived (moved by
Clamonacc) and will trigger the alert if the number
changes.
warning: logrotate in debug mode does nothing except printing debug messages! Consider using verbose mode (-v) instead if this is not what you want.
reading config file /etc/logrotate.d/clamav-quarentena
Reading state from file: /var/lib/logrotate.status
Allocating hash table for state file, size 64 entries
Creating new state
Creating new state
Creating new state
Handling 1 logs
rotating pattern: /var/opt/clamav-quarentena/quarentena.log monthly empty log files are not rotated, (6 rotations), old logs are removed
switching euid from 0 to 989 and egid from 0 to 988 (pid 10363)
considering log /var/opt/clamav-quarantena/quarentena.log
Creating new state
Now: 2026-09-23 22:35
Last rotated at 2026-09-23 22:00
log does not need rotating (log has already been rotated)
switching euid from 989 to 0 and egid from 988 to 0 (pid 10363)
Monthly
: The log file will be rotated once a month (usually on the
first day of the month).
Rotate
6: The system will maintain a maximum of 6 old log files. When
the 7th month arrives, the oldest log will be permanently
deleted.
compress
: Compresses old logs into the .gz format to save disk
space.
delaycompress
: Delays the compression of the previous log to the next
rotation cycle. In practice, the current month's log will be
active, last month's log will be rotated but in plain text
(.1), and only the month before last will be compressed
(.2.gz, .3.gz). This is useful if some program still needs to
write or read the log immediately after the rollover.
missingok
: If the quarantine.log file does not exist for some reason
(eg, it was manually deleted), logrotate will not generate any
error and will proceed to the next service silently.
notifempty
: Do not rotate the log if it is empty. If ClamAV has not
detected any threats in the month and the file is 0 bytes,
logrotate skips the cycle and saves processing power.
create 0640 _clamav _clamav
: Immediately after rotating (moving) the old file, logrotate
creates a brand new quarantine.log file with permissions 0640
(read/write for the owner, read for the group) and sets the owner
as user _clamav and group _clamav.
sharedscripts
: Ensures that the postrotate block (the reload commands) is
executed only once at the end, instead of firing once for each
file.
vsv reload
: In Void Linux, the vsv (or sv reload) utility sends a controlled
HUP signal to runit. This forces ClamAV and Freshclam to close the
old file descriptor and start writing to the new, zeroed file that
create 0640 just generated.
We now need to update the database, which may take a
few minutes.
Depending on how you installed it and the version of
ClamAV you are using, you may encounter errors the first time you
run
Freshclam .
When Freshclam is run, the program will attempt to
retrieve an update from the address specified in the
DatabaseMirror
line ; if it doesn't find one, it will move to the next address
until it finds and downloads the updates. After that, it will
execute all
DatabaseCustomURLs .
However, first we need to run the command that enables
the Clamd service and integrates it with runit, so it will start
along with the system:
sudo ln -s /etc/sv/clamd /var/service/
Trying to start Clamd:
sudo sv start clamd
Exit:
timeout: down: clamd: 0s, normally up, want up
It will probably crash because it's a bug where, even
if Clamd doesn't start, it's necessary to run the command before
updating the database to avoid the WARNING that Clamd wasn't
notified.
To run Freshclam correctly, always execute it by
invoking the ClamAV user:
It will finish without errors with these last lines
above.
If a WARNING like this appears at the end:
WARNING: Wed Sep 16 12:02:53 2026 -> Clamd was NOT notified:
Can't connect to Clamd through /var/run/clamav/clamd.ctl: No such
file or directory
. Don't worry, Clamd still needs to be started.
If you get an error, check what the error is and fix it. For
example:
ERROR: Fri Sep 4 15:48:00 2026 -> NotifyClamd: No communication
socket specified in /etc/clamd.conf
ERROR: Fri Sep 4 15:48:00 2026 -> Can't send to clamd: Socket
operation on non-socket
This error means that some configuration in the /etc/clamd.conf
file is incorrect.
If a WARNING like this appears at the end:
WARNING: Tue Sep 8 09:56:06 2026 -> Clamd was NOT notified:
Can't connect to Clamd through /var/run/clamav/clamd.ctl: Permission
denied
Then run the command
`sudo -u _clamav freshclam`
(or
`sudo -u clamav freshclam`
) again. And, if the lines are correct, don't worry: this
warning will disappear when you start Clamd.
For other errors, see this link which addresses
most errors when running Freshclam for the first time:
Now let's enable Clamonacc, also known as
Real-Time Protection .
ClamAV doesn't have the kind of protection that
constantly scans the computer; it only scans the directory and/or
file when it's accessed. The Clamonacc client for the Clamd
scanning daemon provides access-on-access scanning in modern
Linux
versions , including an optional feature to block file access
until it's verified.
IMPORTANT:
If fanotify is not enabled in the kernel, there is no
point in performing this procedure without enabling it
first.
To configure Clamonacc, simply adjust the /etc/clamd.conf
file.
Since the settings are already in the file, here are the basic
steps:
Open the file /etc/clamd.conf;
Specify the path(s) you would like to monitor by setting
the OnAccessIncludePath option;
Set OnAccessPrevention to yes;
Check which username is being used to run the command,
clamav or _clamav;
Set OnAccessExcludeUname to the corresponding
username;
The global standard for testing antivirus software
without using actual malicious code is the EICAR Standard
Anti-Virus Test File. Any up-to-date antivirus, including
ClamAV, will immediately identify it as a threat named
Win.Test.EICAR_HBR-1 or similar.
bash: /home/user/Downloads/eicar.com: Operation not permitted
This must be happening because in the
/etc/clamd.conf file
, the path
/home/your_username/Downloads
is in the
OnAccessIncludePath
.
IMPORTANT NOTICE
In some graphical interfaces, such as Cinnamon,
there will be no warning in the terminal, but the protection is
working. After echoing, simply check the ~/Downloads folder and
see that the file is not there, and check the
/var/opt/clamav-quarantine directory.
cat: /home/usuario/Downloads/eicar.com: Operation not permitted.
In XFCE, Clamonacc prevents access to the file and then moves it to
quarantine.
cat ~/Downloads/eicar.com
cat: /home/kluster/Downloads/eicar.com: File or directory does not
exist
In Cinnamon, the file is moved to quarantine
before any process can even read it.
The different behavior occurs because
Cinnamon
and
XFCE
handle system errors originating from kernel calls and user
notifications in distinct ways.
When we use the
echo command
,
bash
can temporarily create the file in memory, but in the next
millisecond, Cinnamon's indexer tries to read the file to
generate an ID/thumbnail. This triggers ClamAV, which blocks
access and moves the file immediately.
cat: /home/user/Downloads/eicar.com: File or directory does not
exist
Note that the file was moved to quarantine because
we added
the option
--move=/var/opt/clamav-quarentena to the /
etc/sc/clamonacc/run file
, and it was logged because we added
the option
VirusEvent /usr/local/bin/notificar-virus.sh to the
/etc/clamd.conf file
.
Remember that Clamscan doesn't use a configuration
file, but its own parameters in the binary; however, we'll soon
create a
wrapper
for it, as we'll be using it for scans with cron.
/home/seu_usuario/Downloads/grub-void.html: OK
/home/seu_usuario/Downloads/vkpurge.html: OK
/home/seu_usuario/Downloads/zram-zswap.mhtml: OK
/home/seu_usuario/Downloads/linux-7.1.2.tar.xz: OK
/home/seu_usuario/Downloads/apache-netbeans.svg: OK
/home/seu_usuario/Downloads/wgcf-master.zip: OK
/home/your_usuario/Downloads/wgcf-account.toml: OK
----------- SCAN SUMMARY -----------
Known viruses: 3797093
Engine version: 1.5.3
Scanned directories: 1
Scanned files: 7
Infected files: 0
Data scanned: 16.27 MiB
Data read: 159.41 MiB (ratio 0.10:1)
Time: 19.103 sec (0 m 19 s)
Start Date: 2026:09:23 23:41:10
End Date: 2026:09:23 23:41:29
/home/usuario/Downloads/eicar.com: Failed to open file. ERROR
----------- SCAN SUMMARY -----------
Infected files: 0
Total errors: 1
Time: 0.019 sec (0 m 0 s)
Start Date: 2026:09:21 12:56:14
End Date: 2026:09:21 12:56:14
We can see that Clamonacc in XFCE prevents either
Clamscan or Clamdscan from accessing the virulent file, neither
with sudo nor with the
_clamav
user itself .
However, when scanning
~/Downloads
, it only allows access with Clamscan and blocks it with
Clamdscan, because Clamd and Clamonacc use the same
/etc/clamd.conf file, while Clamscan is independent.
Note: For the file to be moved to quarantine, the
parameter
--move=/path/to/quarantine
must be passed in the command.
I first used Clamscan because it provides a more
complete output, but it takes longer because it loads the entire
database into RAM each time.
The result shows that the ClamAV engine is fully
operational and up-to-date with over 3.7 million known signatures.
It instantly identified the file as FOUND.
However, the command took 12,357 seconds to scan a
single file of just 69 bytes. This happens because Clamscan needs
to load all virus signatures into RAM from scratch every time it
is run.
Let's perform the same scan in fractions of a
millisecond using the clamdscan command with the
--stream
flag to send the file to the local daemon (Clamd) that is already
running in the background with the database pre-loaded into
RAM.
/home/usuario/Downloads/images.jpeg: OK
/home/usuario/Downloads/26055.txt: OK
/home/usuario/Downloads/18153.txt: OK
/home/usuario/Downloads/5174256.png: OK
/home/usuario/Downloads/calvin-midia.webp: OK
/home/usuario/Downloads/biblia-terminal-main.zip:
Sanesecurity.Foxhole.Zip_exe.UNOFFICIAL FOUND
/home/user/Downloads/0x0.webp: OK
/home/usuario/Downloads/demolition.webp: OK
/home/usuario/Downloads/idiocracy.webp: OK
/home/usuario/Downloads/celine-nietzsche.pdf: OK
/home/usuario/Downloads/Ardil-22 - Joseph Heller.pdf: OK
/home/usuario/Downloads/eicar.com:
{HEX}test.test.eicar.1040.UNOFFICIAL FOUND
...
----------- SCAN SUMMARY -----------
Known viruses: 3797062
Engine version: 1.5.3
Scanned directories: 1
Scanned files: 54
Infected files: 2
Total errors: 1
Data scanned: 530.29 MiB
Data read: 742.51 MiB (ratio 0.71:1)
Time: 439.155 sec (7 m 19 s)
Start Date: 2026:09:24 07:51:59
End Date: 2026:09:24 07:59:19
Note that it flagged two viruses: the file
eicar.com
and the file
biblia-terminal-main.zip
as
Sanesecurity.Foxhole.Zip_exe.UNOFFICIAL FOUND
. This might be a false positive, but just to be safe, it was
quarantined.
Depending on the settings, Clamonacc may block
Clamscan and Clamdscan, so, just to be safe, it's a good idea to
stop Clamonacc from scanning and start it again immediately
afterwards.
sudo sv stop clamonacc
ok: down: clamonacc: 0s, normally up
For Clamscan and Clamdscan to move files to
quarantine, the parameter
--move=/path/to/quarantine
must be passed in the command for manual scans and also included
in the Cron file for automatic scans:
Password:
/home/usuario/Downloads/eicar.com:
{HEX}test.test.eicar.1040.UNOFFICIAL FOUND
/home/usuario/Downloads/eicar.com: moved to
'/var/opt/clamav-quarentena/eicar.com.008'
/home/usuario/Downloads/eicar.com:
{HEX}test.test.eicar.1040.UNOFFICIAL FOUND
/home/usuario/Downloads/eicar.com: moved to
'/var/opt/clamav-quarentena/eicar.com.009'
----------- SCAN SUMMARY -----------
Known viruses: 3796968
Engine version: 1.5.3
Scanned directories: 0
Scanned files: 1
Infected files: 1
Data scanned: 69 B
Data read: 69 B (ratio 1.00:1)
Time: 12.660 sec (0 m 12 s)
Start Date: 2026:09:21 13:41:29
End Date: 2026:09:21 13:41:41
cat ~/Downloads/eicar.com
cat: /home/user/Downloads/eicar.com: File or directory does not
exist
I recommend using Clamonacc only in certain folders
such as
/home/user/Downloads , /tmp , /var/tmp,
and
/dev/shm
, and even then, with caution, as processes may lose access to
files necessary for their operation if they are detected as false
positives. In that case, you will have to move them manually to
the list.
Clamonacc requires elevated privileges (
root
) to interact with the Kernel's fanotify API.
Giving global read permission (o+rx) to the
/home/username
folder allows other local users to see the list of public files in
your home directory. This is not recommended due to privacy and
security concerns. The alternative would be to add the user
_clamav to the personal user group and adjust the
AllowSupplementaryGroups
option in clamd.conf.
Based on the tests shown, we saw that Clamonacc, depending
on its settings, can block Clamscan and Clamdscan. Therefore, just to be
safe, we stopped Clamonacc from scanning and restarted it immediately
afterward.
Differences between Clamscan and Clamdscan
Clamd/Clamonacc
: These require the use of
/etc/clamd.conf
. The daemon runs in the background in memory, keeping the database
loaded for instant responses. It is ideal for lightweight real-time
monitoring of specific folders.
Since the virus database is already loaded into RAM by
the daemon (Clamd), Clamdscan is immensely faster to start and
consumes much less CPU with each run. It simply sends the file path to
the daemon to analyze and returns the result.
Clamdscan is best suited for manual scans of specific
files and directories.
For example, when you have a very large file to scan,
change `OnAccessMaxFileSize` to
XXXM
in `/etc/clamd.conf` and then run `
echo 'fs.inotify.max_user_watches=xxxxxxxxx' | sudo tee
/etc/sysctl.d/99-inotify.conf`
with the same size converted to bytes. Then return it to the standard
size you need so Clamonacc doesn't interfere with the system. In my
case, I leave it at 100 megabytes (100M).
Clamscan
: This is a standalone utility. It reads the signature database
directly from disk each time it runs. Because it scans on demand (via
cron or manually), it doesn't interfere with Clamonacc's behavior and
doesn't require you to modify the /etc/clamd.conf file.
Each time it runs, it needs to read all the database
signature files directly from disk and allocate everything back into
RAM, which consumes a lot of time and causes processing spikes.
However, for an automated Cron scan of the entire system
overnight, Clamscan is ideal.
A wrapper is a function, class, or library that wraps existing
code around it to simplify its interface, add new functionality, or
adapt its communication.
A file configured to perform the scan with Clamscan, which
will then be used in the Cron job.
sudo vim /usr/local/bin/varredura.sh
Place inside:
#!/usr/bin/env bash# /usr/local/bin/varredura.sh# Varredura completa com Clamscan, independente do Clamd/Clamonacc.# Uso: rodar como root via Cron.set -euo pipefail# -------------## Configuracao# -------------#ALVOS=(# "/"# "/home"# "/var/www"# "/etc" "/home/seu_usuario/Downloads"# Adicione mais diretorios aqui ou coloque para varrer o raiz (/) e adicione mais --exclude-dir abaixo)LOG="/var/log/varredura.log"QUARENTENA="/var/opt/clamav-quarentena"LOCKFILE="/var/run/clamscan.lock"# Evita rodar duas varreduras simultaneas se a anterior atrasarexec 200>"$LOCKFILE"if ! flock -n 200; then echo "$(date '+%F %T') - Varredura anterior ainda em execução. Abortando." >> "$LOG" exit 1fiecho "=================================================" >> "$LOG"echo "$(date '+%F %T') - Início da varredura" >> "$LOG"# --------------## Execucao# --------------#sudo sv stop clamonacc &&set +eclamscan \ --recursive \ --alert-broken \ --infected \ --log="$LOG" \ --move="$QUARENTENA" \ --exclude-dir='^/(proc|sys|dev|run|/var/run|/etc/sv|/etc/runit)' \ --exclude-dir='^/var/lib/_clamav' \ --exclude-dir='^/var/log' \ --max-filesize=500M \ --max-scansize=1000M \ --max-scantime=0 \ --cross-fs=no \ --alert-exceeds-max=yes \ --alert-broken=yes \ --alert-encrypted=yes \ --alert-macros=yes \ --detect-pua=yes \ "${ALVOS[@]}"STATUS=$?;set -e;sudo sv start clamonaccecho "$(date '+%F %T') - Fim da varredura (Código de saída: $STATUS)" >> "$LOG"# Codigos de retorno do ClamAV: 0 = limpo, 1 = infectado, 2 = erroexit $STATUS
Save and exit.
According to the tests shown, we saw that since
Clamonacc blocks even Clamscan and Clamdscan, we have to stop
Clamonacc for the scan and start it again immediately afterward, as
shown in the script.
warning: logrotate in debug mode does nothing except printing debug
messages! Consider using verbose mode (-v) instead if this is not what
you want.
reading config file /etc/logrotate.d/clamav
Reading state from file: /var/lib/logrotate.status
Allocating hash table for state file, size 64 entries
Creating new state
Creating new state
Creating new state
Handling 1 logs
rotating pattern: /var/log/clamd.log /var/log/freshclam.log
/var/log/varredura.log empty monthly log files are not rotated, (6
rotations), old logs are removed
considering log /var/log/clamd.log
Creating new state
Now: 2026-09-24 00:26
Last rotated at 2026-09-24 00:00
log does not need rotating (log has already been rotated)
considering log /var/log/freshclam.log
Creating new state
Now: 2026-09-24 00:26
Last rotated at 2026-09-24 00:00
log does not need rotating (log has already been rotated)
considering log /var/log/varredura.log
Creating new state
Now: 2026-09-24 00:26
Last rotated at 2026-09-24 00:00
log does not need rotating (log has already been rotated)
not running postrotate script, since no logs were rotated
The -d parameter (debug mode) simply prints to the
screen everything it would do if it were actually running.
If you want to force log rotation right now, replace
the -d with the -f (force) parameter:
sudo logrotate -f /etc/logrotate.d/clamav
If you want to see what it's doing in real time while
it's actually running, use the verbose mode -v:
sudo logrotate -v /etc/logrotate.d/clamav
Testing the file in the /home/your_username/Downloads
directory:
I left this part like this, adapt it to your liking:
#-------------------#
# Configuration
#-------------------#
TARGETS=(
# "/" # "/home"
# "/var/www"
# "/etc"
"/home/your_username/test"
# add more directories here or set it to scan the root (/) and add
more --exclude-dir below
)
Save and exit.
sudo /usr/local/bin/varredura.sh
ok: down: clamonacc: 1s, normally up
/home/kluster/teste/eicar.com: {HEX}test.test.eicar.1040.UNOFFICIAL
FOUND
/home/kluster/teste/eicar.com: moved to
'/var/opt/clamav-quarentena/eicar.com'
----------- SCAN SUMMARY -----------
Known viruses: 3811649
Engine version: 1.5.3
Scanned directories: 45
Scanned files: 576
Infected files: 1
Data scanned: 6.92 MiB
Data read: 5.87 MiB (ratio 1.18:1)
Time: 15.432 sec (0 m 15 s)
Start Date: 2026:09:23 15:12:44
End Date: 2026:09:23 15:12:59
ok: run: clamonacc: (pid 17328) 1s
cat ~/teste/eicar.com
cat: /home/usuario/teste/eicar.com: File or directory does not
exist.
If you want, give it to:
cat /var/log/varredura.log
or
tail -n 10 /var/log/varredura.log
And finally, confirm that Clamonacc has started (even
though the output shows this at the end):
sudo sv status clamonacc
run: clamonacc: (pid 17328) 62s
We can see that the final test went well.
He scanned the files and found eicar.com, moving it to
quarantine and "activating" Clamonacc.
Remember that it's necessary to disable Clamonacc
during scans because, as we've seen, it prevents both Clamdscan and
Clamscan from operating on protected files and directories.
You can leave Clamonacc enabled during scans, and only
directories and files protected by Clamonacc will not be scanned.
However, I prefer to disable it to avoid conflicts and potential
crashes because, as we've seen, Clamonacc acts directly on the
Kernel.
Next, remember to set TARGETS to root (/) in the
/usr/local/bin/scanning.sh
file and add as many exclusions as you want with the
--exclude-dir
parameter .
Or configure ~/.bashrc permanently, otherwise the command "
sudo crontab -e
" will open
vi
by default in Void and you will never be able to exit it.
Place the following inside:
# === ClamAV ===# 1. Atualiza o banco de dados as 03:22 todos os dias# Opcional porque o /etc/freshclam.conf está configurado para atualizar duas vezes ao dia: Checks 222 03 * * * runuser -u _clamav /usr/bin/freshclam# 2. Escaneia o sistema as 03:44 no domingo (0) e na quarta-feira (3)# 44 03 * * 0,3 sudo sv stop clamonacc && /usr/bin/clamdscan --stream --recursive --fdpass --exclude-dir="^/sys|^/dev|^/proc|^/etc/sv|^/etc/runit|/\.config/google-chrome" /; sudo sv start clamonacc# 3. Escaneia o sistema as 03:44 no domingo e na quarta44 03 * * 0,3 /usr/local/bin/varredura.sh >> /var/log/varredura.log 2>&1# 4. Roda a cada 5 minutos (ou no intervalo que preferir)*/5 * * * * /usr/local/bin/monitor-quarentena.sh# 5. Limpa arquivos com mais de 30 dias na quarentena todo Sabado as 00:0000 00 * * 6 /usr/local/bin/limpar_quarentena.sh# === CLamAV Final ===
Save and exit.
Configure the days and times when the computer/server is
turned on, that is, configure it according to your needs.
IMPORTANT WARNING:
Do not use recursive protection with Clamonacc (real-time
protection), as it will practically slow down the system and may
even crash it.
It can have multiple parameters. OnAccessIncludePath:
The above configuration will result in non-recursive
real-time protection of directories; that is, the parameter "
OnAccessIncludePath /home/usuario
" will only protect in real time the files that are there, but
will not protect the directories (folders) inside
/home/usuario
. Any access attempts detected by Clamonacc on malicious files
within
/home/usuario
will be blocked by the Kernel through fanotify, as we will see in
the tests later on.
For the type of protection with automatic locking,
the basic parameters to be enabled are as follows:
With "
OnAccessPrevention yes
", when attempting to access a malicious file with, for example, cat
eicar.com, ClamAV, through the Kernel's fanotify, will issue a
notification:
cat eicar.com
cat: eicar.com: Operation not permitted
With "
OnAccessPrevention no
", when attempting to access a malicious file, access will be
allowed.
I set "
OnAccessDisableDDD yes
" because DDD fails to recursively apply kernel markings to
directories that already existed before the service started, so to
avoid conflicts, it's better to disable it and set the folders you
want to have immediate blocking.
Either way, you'll need a script to move the
infected files to quarantine or use the "
--move=/path/to/quarantine
" parameter, as ClamAV doesn't handle this type of control.
Clamscan, Clamonacc, and Clamdscan include the "
--remove
" option to delete any file that generates alerts during a scan.
This is generally a very bad idea unless you are monitoring an
uploads/downloads directory. False positives happen! You don't
want the wrong file to be accidentally deleted. Instead, consider
using the "
--move
" parameter or perhaps just "
--copy
" and set up a script with the "
VirusEvent
" feature to notify you when something is detected.
CASE 0x0
If the user needs to monitor the entire file system,
but blocking malicious access attempts is not a concern:
This setting will enable the
On-Access Scanner notify-only
option. It will also ensure that only user processes that are
neither root nor clamav trigger filesystem checks. Processes
started by root and the ClamAV user (_clamav or clamav) will not
trigger checks and therefore notifications; In other words, ClamAV
will do nothing. This is often necessary to prevent a loop in root
and/or ClamAV user processes.
To move infected files to quarantine and clear the
quarantine after a certain time, a script is necessary, as we will
see.
The
OnAccessMountPath
parameter uses a different fanotify API configuration, making it
incompatible with OnAccessIncludePath and the DDD system. This
also means that the following options cannot be used in
conjunction with
OnAccessMountPath :
OnAccessExtraScanning
is built around capturing inotify events.
OnAccessExcludePath
- is based on the DDD system.
OnAccessPrevention - locks the system ifOnAccessMountPath
is selected
.
If you need
OnAccessPrevention yes
, use
OnAccessIncludePath
and
OnAccessExcludePath .
CASE 0x1
If the system administrator needs to monitor the
home directory of several users, but not all, and it is not
necessary to block access attempts, but only to notify them:
With this configuration, the On-Access Scanner will
recursively monitor the entire
/home
directory in notify-only mode. The directories
/home/user2
and
/home/user4
will be recursively excluded from the scan.
To move infected files to quarantine and clear the
quarantine after a certain time, a script is necessary, as we have
seen.
Observation:
"OnAccessIncludePath /", that is, "OnAccessIncludePath" in
the root directory, is NOT accepted as a valid
parameter!
Checking the kernel configuration for the presence of
fanotify:
cat /boot/config-`uname -r` | grep FANOTIFY
Updating and installing:
sudo xbps-install -Syu
sudo xbps-install clamav
Verify that the ClamAV
user and group
have been created:
cut -d: -f1 /etc/passwd
cut -d: -f1 /etc/group
If it hasn't already been created in your
distribution, create the user (in Void, when installing
ClamAV
, the _clamav user and group are created automatically, so you can
skip these two commands):
Setting the database directory to the correct owner (check if it's
_clamav or clamav):
sudo chown -R _clamav:_clamav /var/lib/_clamav
sudo vim /etc/freshclam.conf
See article.
sudo vim /etc/clamd.conf
See article.
sudo echo 'fs.inotify.max_user_watches=104857600' | sudo tee /etc/sysctl.d/99-inotify.conf
NOTICE
The number there is 100M converted to bytes. This
number must be the same as the
OnAccessMaxFileSize
parameter . If you change the number in the OnAccessMaxFileSize
parameter, you must run this command again with the new
number.
QUARANTINE
Creating directory and file and setting permissions:
Add the following line at the end to apply strict
security restrictions (noexec, nosuid, and nodev prevent the execution
of programs, SUID binaries, and the creation of devices):
We can see that clamonacc (Real-Time Protection)
prevents either clascam or clamdscan from accessing the virulent file,
neither with sudo nor with the _clamav (or clamav) user itself.
Let's comment out the /home/user/Downloads
directory in the file:
I left this part like this, adapt it to your liking:
#-------------------# # Configuration #-------------------# TARGETS=( # "/" # "/home" # "/var/www" # "/etc" "/home/your_username/test" # add more directories here or set it to scan the root (/) and add more
--exclude-dir below )
sudo /usr/local/bin/varredura.sh
cat ~/teste/eicar.com
cat: /home/usuario/teste/eicar.com: File or directory does not
exist
If you want, give it:
cat /var/log/varredura.log
tail -n 10 /var/log/varredura.log
CRON
sudo -E crontab -e
or
sudo EDITOR=vim crontab -e
or
sudo EDITOR=nano crontab -e
or
Configure
~/.bashrc
permanently, otherwise the command
sudo crontab -e
will open vi by default in Void and you will never be able to exit
it.
The main.cvd
file
is the primary repository of stable ClamAV signatures and is
updated very rarely (usually once or twice a year). The current
and most recent version globally is Version 63, generated by
developer
tomjudge
on December 16, 2025, containing the 3,287,027 signatures listed
in the output.
The
main.cvd file
will remain static in version 63 for some time, while the
daily.cld
file will change versions and display the current date every
time
Freshclam
is run .
The quarantine script is operating on a fully
updated database.
Remember that Freshclam updates occur
automatically twice a day according to the
Checks 2 parameter in the/etc/freshclam.conf
file
, and a third time a day if you've added it to a cron
job.
When daily updates occur, Freshclam only modifies
the
daily.cvd
(or
daily.cld
) file.
Main database files:
main.cvd
: The main static database.
daily.cvd
(or
daily.cld
): This one changes multiple times a day to include recent
threats (Ransomware, Phishing, and new malware).
bytecode.cvd
: Updated sporadically to reflect new scanning engine
logic.
Temporary Directories:
(Target #1) These are the most common locations because any
user of the system (or vulnerable web service, such as a
WordPress site or a PHP application) has full permission to
write files to them.
/tmp
: The global temporary directory. Virtually 90% of automated
attack scripts (such as cryptocurrency miners and DDoS bots)
download their binaries here before executing them.
/var/tmp
: Similar to /tmp, but files here are not deleted when the
system restarts. Attackers use this location to try to maintain
persistence on the server.
/dev/shm
: This is the shared memory directory. Files placed here run
directly in RAM, making them extremely fast and often invisible
to traditional disk monitoring tools.
2)
Web Service and Upload Directories:
If your
Linux system
runs a web server (Apache, Nginx) or databases, the attacker
will exploit vulnerabilities in the application to inject files
(usually web shells in PHP, Python, or Perl).
/var/www/html/
(or upload subfolders like wp-content/uploads in WordPress):
Where malicious code is injected so that the attacker can
remotely control the server through the browser.
/var/spool/samba/
or network share folders: If Samba is misconfigured, Windows
malware (such as ransomware) can be placed there to infect other
computers on the network.
3)
Hidden Directories in User Profiles
(/home): When the attack specifically targets a user's account
(via SSH password theft or private key theft), malicious
binaries are often hidden within hidden folders in /home to
avoid simple visual detection (common ls commands do not show
them).
/home/user/.config/
or
/home/user/.local/
: Legitimate folders where malware disguises itself as system
configuration files.
/home/user/.ssh/
: Although they don't place the malware here, attackers inject
public keys into the authorized_keys file in this folder to
ensure they can re-enter the system whenever they want, without
needing a password.