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.
Verification
Live-testedReally 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 · attributionPaste 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.
[](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:
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
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.
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.
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.
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.
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.
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.