ClamAV Scanning On Loopback, Signatures Kept Current

ClamAV from EPEL: clamd on a local socket and loopback TCP, signatures fetched before it starts and freshclam enabled after, since every ClamAV unit ships disabled. The README measures where a size limit fails open. The live test decodes the EICAR test file on the target, so no role file holds it, and finds the signature by name on three client paths. Original role, live-tested on Rocky Linux 10.

ansibleSecurity & Secrets

Verification

Live-tested

Really deployed to a container sandbox, proven idempotent (a second run changes nothing), verified against the role’s assertions, then torn down.

Conformance

  • Static validation (yamllint · ansible-lint)

Provenance

  • SHA-256 checksum
  • Signature (pending)

Functional

  • Live-tested - applied, verified, destroyed

Last verified 2026-10-02 · podman 4.9.3 · ansible 2.21.4 · how we verify

Cite it in your README

badge · attribution

Paste this beside the module in the repository that uses it. The badge is rendered from this artifact's verification record, so it reads live-tested because the record says so, and the link lands on this page.

README.md, GitLab, Gitea
[![IaC Bazaar: live-tested](https://www.iac-bazaar.com/api/artifacts/ansible-clamav/badge)](https://www.iac-bazaar.com/catalog/ansible-clamav?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)

Ansible role 1.0.0, live-tested on IaC Bazaar: [ClamAV Scanning On Loopback, Signatures Kept Current](https://www.iac-bazaar.com/catalog/ansible-clamav?utm_source=syndication&utm_medium=readme&utm_campaign=artifact)

```yaml
# ClamAV Scanning On Loopback, Signatures Kept Current: https://www.iac-bazaar.com/catalog/ansible-clamav (download from your IaC Bazaar account)
```

Preview:IaC Bazaar: live-tested

Documentation

clamav

ClamAV from EPEL: the clamd scanning daemon on a local socket and loopback TCP, with freshclam keeping the signatures current, for clamdscan on the host and for any client that speaks INSTREAM. Original role for EL 10, live-tested with podman on Rocky Linux 10.

No download, and no version to pin. EL 10 packages clamd in EPEL, so the role installs it by name and takes what the distribution ships: a security update arrives through dnf, not through a new release of this role. What the role owns is the configuration and the proof that the service works.

The distribution's unit, our configuration. The role installs clamav, clamd, writes the configuration the package leaves open, and enables the unit the package ships: systemctl cat clamd@scan shows the distribution's own unit, not one this role invented. The listener is 127.0.0.1:3310 by default, for a proxy that authenticates or a client on the same host; the live test reads the listening sockets and expects loopback only.

Every ClamAV unit ships disabled, freshclam's included, and clamd refuses to start without signatures. The role fetches the first set before enabling the daemon (113 MB, 25-40 s in the lane) and then enables clamav-freshclam, so a host never runs a scanner that cannot be updated. Plan for memory: with the full signature set clamd held about 1 GB RSS.

A size limit fails open on two of three paths. clamd does not scan past MaxFileSize. Measured with clamav_max_file_size at 10 bytes, the EICAR test file came back OK, exit 0, through clamdscan --fdpass and through clamdscan --stream; only a client that sent the whole file over INSTREAM got an error (INSTREAM size limit exceeded). So clamdscan sends no more than StreamMaxLength - the role sets both limits from one variable - and clamd never sees a limit crossed. clamav_alert_exceeds_max: true (AlertExceedsMax) reports a skipped file as Heuristics.Limits.Exceeded.MaxFileSize on the --fdpass path and changes nothing on the --stream path, also measured. It is off by default, as upstream, because it flags every legitimate file over the limit as well. Keep the limit above the largest file you need scanned.

Proven on EICAR, without carrying it. The live test decodes the standard EICAR test file on the target - no file in this role contains the string, so neither your antivirus nor ours flags the role - and asserts the signature BY NAME through clamdscan --fdpass, clamdscan --stream and a raw INSTREAM over TCP, with a clean file reported OK both ways. A bare FOUND would not do: a skipped file prints it too, as a heuristic.

License

Commercial - IaC Bazaar EULA. (c) IaC Bazaar.

Usage code & full reference need an account

The complete copy-paste usage, the full input/output reference, and operational notes are free with an account - shown here and bundled in the download. Sign in and this section fills in.

  • Variables
  • Test

Related modules

Live-tested

ansible-aide

AIDE from AppStream on EL 10: a watched tree, a baseline database built once, and the oneshot unit and timer the package does not ship. The live test passes on an unchanged host, FAILS when a file appears inside a watched path and names it, ignores one inside an excluded path, and passes again once the change is gone. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-389-ds

389 Directory Server from AppStream. A fresh instance listens on every interface and lets anonymous clients read the tree; this role binds both listeners to loopback and limits anonymous clients to the rootDSE. The live test adds a user who binds, sees a wrong password and an anonymous search refused, and reads the LDAPS certificate. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-authelia

Authelia from the upstream release (sha256-verified) as a hardened system service on loopback with file users and sqlite; its secrets are generated once on the host and reach the service as AUTHELIA_*_FILE variables. The live test hashes a password with Authelia's hasher, logs in, sees a wrong password refused and an anonymous visitor sent to the portal. Original role, live-tested on Rocky 10.

View module
Live-tested

ansible-bandit

bandit on EL 10 from PyPI into a venv of its own with a link in the PATH; the live test runs pip check, then scans a module that passes a string to subprocess.call with shell=True (B602, High, exit 1) and a clean module (exit 0). Pinned. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-boundary

boundary on EL 10 from releases.hashicorp.com; SHA256SUMS is signature-checked against HashiCorp's key before get_url trusts it, the live test re-checks both, then runs authenticate against a dead address ('connection refused') and database init with a throwaway config (parsed, root key loaded, then the database refused). Pinned. Original role, live-tested on Rocky Linux 10.

View module
Live-tested

ansible-dockle

dockle on EL 10 from the GitHub release; get_url refuses it unless its SHA-256 is in the vendor's checksums file, and the live test re-checks it, then scans a one-layer image whose config names no user, expecting CIS-DI-0001 in the output, exit code 1 with --exit-level warn, and the warning counted in the JSON form. Pinned. Original role, live-tested on Rocky Linux 10.

View module