TrueNAS Scale ClamAV

Last Edit: 2024.12.01

Overview

Setup ClamAV on TrueNAS Scale.

Assumptions

Install ClamAV

Navigate to the Applications page in the TrueNAS Scale dashboard, Apps on the main navigation.

Switch to the Available Applications tab in the Applications page.

Using the search tool, find the clamav application. Verify ClamAV is from the TrueNAS catalog and is on the Community train.

Select Install to begin configuration and installation of the application. Configuration options not mentioned in this section can be left as default.

Application Name

SettingValueDescription
Application NameclamavName for the application.
Version Number#.#.#Version to use, latest by default.

ClamAV Configuration

SettingValueDescription
Disable ClamdfalseDisables ClamAV daemon, preventing file scans.
Disable FreshclamdfalseDisables automatic updates of ClamAV signature database.
Disable MilterdtrueDisables ClamAV mail filter daemon.
Clamd Startup Timeout1800Seconds to wait before timeout of ClamAV daemon, 30 minutes.
Freshclamd Check1Number of times to update signature database in a day. 1 is daily, 24 is hourly.
Additional Environment VariablesNone required.

Network Configuration

SettingValueDescription
Clamd Port30005ClamAV daemon port.
Milterd Port30006ClamAV mail daemon port.
Host NetworkfalseLeave disabled in most cases.

Storage Configuration

SettingValueDescription
ClamAV Signature Database Storage
TypeixVolumeUse ixVolume for signature storage.
Enable ACLfalseEnabled to configure Access Control List.
ClamAV Scan Directory Storage
TypeixVolumeUse ixVolume for scan storage.
Enable ACLfalseEnabled to configure Access Control List.

Resources Configuration

SettingValueDescription
CPU Limit2Configure a CPU thread limit for the application.
Memory Limit4096Memery limit in megabytes.

Install

Verify you have checked the TrueNAS documentation for ClamAV and Install. The application will complete installation and deploy. Navigate to the Applications tab to monitor the status.

Log Storage

ClamAV will send scan reports via email if TrueNAS Scale has been configured to send emails. Consider creating a dataset to store scan reports, especially on systems without email configured.

Add Dataset

Create a new dataset for log storage, tank01/logs in this example.

Add logs dataset under tank01.

Edit the logs dataset permissions. Configure the User as root with Read, Write, Execute permissions. Configure the Group as wheel with Read, Execute permissions. Configure Other permissions as None. Apply the permissions recursively and Save.

Configure logs dataset permissions (750).

Mount Dataset

Add the logs dataset as Additional Storage for ClamAV.

From the ClamAV application Storage Configuration, Add an Additional Storage path to the logs dataset.

SettingValueDescription
Additional Storage
TypeHost PathDefine a path on the system.
Read OnlyfalseClamAV requires write access to write the logs.
Mount Path/mnt/logsWhere the host path will be mounted in the application container.
Enable ACLfalseEnabled to configure Access Control List.
Host Path/mnt/tank01/logsPath to the logs dataset.

Access Logs

Generated logs can be accessed however system data is currently accessed. Adjust the file permissions as needed.

Consider deploying a File Browser application instance, pointed at the logs dataset. Change the logs dataset Group to apps to allow other applications to read the logs. Change the User to apps to allow other applications to modify logs.

Scan Storage

A storage scan target could have been specified during initial setup using the ClamAV Scan Directory. This example has avoided this because of its editability limitations, and inability to define multiple seperate paths. Instead, multiple Additional Storage directories will be mounted to the application.

Mount Datasets

Mount the datasets that will be scanned. Repeat the process for each dataset.

From the ClamAV application Storage Configuration, Add an Additional Storage path for the dataset to scan.

SettingValueDescription
Additional Storage
TypeHost PathDefine a path on the system.
Read OnlytrueDisable write permission, unless ClamAV will be configured to take action on files.
Mount Path/mnt/scan/tank01-example-datasetWhere the host path will be mounted in the application container.
Enable ACLfalseEnabled to configure Access Control List.
Host Path/mnt/tank01/example-datasetPath of the dataset to scan.

Schedule Scan

ClamAV will not scan anything by default. Create a cron job to run the scan at scheduled intervals.

Scan Command

The following command will scan /mnt/scan recursively and store the log output in the previously mounted logs dataset. Remove log flag and value when only using email.

If the default application name was not used when installing ClamAV, modify the container name ix-clamav-clamav-1. The correct value can be found with the docker ps command.

docker exec ix-clamav-clamav-1 clamscan --recursive /mnt/scan --log /mnt/logs/clamav-scan-$(date +\%Y-\%m-\%d_\%H-\%M).log

Schedule Scan

Schedule the scan using cron. ClamAV scans can take a long time to complete. Consider running scans monthly and adjusting from there.

From the TrueNAS dashboard, navigate to System, Advanced Settings. Find Cron Jobs in the list and Add a new one.

Configure the job as required.

SettingValueDescription
Descriptionclamav-scanJob name.
Commanddocker exec ix-clamav-clamav-1 clamscan --recursive /mnt/scan --log /mnt/logs/clamav-scan-$(date +\%Y-\%m-\%d_\%H-\%M).logScan command.
Run As UserrootRun as root user.
ScheduleMonthlyJob frequency.
Hide Standard OutputfalseDisable to get output reports.
Hide Standard ErrorfalseDisable to get error reports.
EnabledtrueEnable to activate the job.

ClamAV scan cron job.

Scan Summary

The scan summary will be emailed if the TrueNAS server is configured to send emails. Find it in the logs dataset, if configured.

----------- SCAN SUMMARY -----------
Known viruses: #######
Engine version: #.#.#
Scanned directories: ##
Scanned files: ##
Infected files: 0
Data scanned: 0.00 MB
Data read: 0.00 MB (ratio 0.00:1)
Time: 00.000 sec (0 m 0 s)
Start Date: 2024:04:20 12:00:00
End Date:   2024:04:20 12:00:00

Schedule Cleanup

Consider creating another cron job to remove old ClamAV scan logs. The following command will delete all log files mounted to ClamAV under /mnt/logs that start with match clamav-scan-*-.log that are older than 90 days.

docker exec ix-clamav-clamav-1 find /mnt/logs -type f -name "clamav-scan-*-.log" -mtime +90 -exec rm {} \;

Schedule the cleanup command to run a few minutes before the ClamAV job each month.

SettingValueDescription
Descriptionclamav-cleanupJob name.
Commanddocker exec ix-clamav-clamav-1 find /mnt/logs -type f -name "clamav-scan-*-.log" -mtime +90 -exec rm {} \;Scan command.
Run As UserrootRun as root user.
ScheduleMonthlyJob frequency. Optionally adjust to run a few minutes before the scan.
Hide Standard OutputtrueDisable to get output reports.
Hide Standard ErrorfalseDisable to get error reports.
EnabledtrueEnable to activate the job.

ClamAV cleanup cron job.

Errors

137 Exit Status

The cron job may fail with exit code 137. This is most likely a memory issue for the ClamAV container. In some cases, this error will present when the command is run in a cron job, but not when run manually.

Increase the amount of RAM assigned to the ClamAV container and restart the job.

 Error: Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/middlewared/job.py", line 488, in run
    await self.future
  File "/usr/lib/python3/dist-packages/middlewared/job.py", line 535, in __run_body
    rv = await self.middleware.run_in_thread(self.method, *args)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 1364, in run_in_thread
    return await self.run_in_executor(io_thread_pool_executor, method, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/main.py", line 1361, in run_in_executor
    return await loop.run_in_executor(pool, functools.partial(method, *args, **kwargs))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/schema/processor.py", line 183, in nf
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/schema/processor.py", line 55, in nf
    res = f(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/middlewared/plugins/cron.py", line 278, in run
    raise CallError(f'CronTask "{cron_cmd}" exited with {cp.returncode} (non-zero) exit status.')
middlewared.service_exception.CallError: [EFAULT] CronTask "docker exec ix-clamav-clamav-1 clamscan --recursive /mnt/scan --log /mnt/logs/clamav-scan-$(date +\%Y-\%m-\%d_\%H-\%M).log" exited with 137 (non-zero) exit status.

References

1 2 3 4


  1. iXsystems. “TrueNAS Documentation.” 2024. ↩︎

  2. iXsystems. “TrueNAS ClamAV Documentation..” 2024. ↩︎

  3. Cisco. ClamAV Documentation. 2024. ↩︎

  4. ClamAV Team. ClamAV GitHub. 2024. ↩︎