ClamAV Antivirus Engine on AWS User Guide
Overview
This image runs ClamAV 1.5.3, the open source, GPL-2.0 licensed antivirus engine, ready to scan from the first boot of every instance you launch. ClamAV provides clamd, a daemon that holds a signature set in memory and returns a verdict on any file handed to it, the clamscan and clamdscan command line scanners, and freshclam, which keeps the signature databases current. It is a long-standing answer to file-scanning and compliance requirements such as PCI-DSS requirement 5.x.
ClamAV is installed unmodified from Ubuntu's own package archive, so the engine stays patchable through the normal package path for the life of the release. This is a headless command-line image: there is no web interface, no service to log into and no credential of any kind. You drive it over SSH with your own key.
The single most important design decision in this image is that no virus signature database is baked into the AMI. A signature set frozen at build time is stale the day you deploy it, and a scanner that reports healthy while missing everything published since then is worse than no scanner at all. Instead, on the first boot of every instance, freshclam fetches the current signature databases directly from the upstream provider, so your scanner starts with fresh signatures rather than a frozen snapshot. The image is fail-closed: clamd physically cannot start without a signature database, so an instance that has not completed first boot cannot present a scanner that silently scans nothing.
What This Appliance Does and Does Not Do
Read this section before you deploy. It is the difference between an appliance that does what you think it does and one that quietly does not.
ClamAV's core mechanism works exactly as designed on EC2. Scanning a file is scanning a file: nothing about a virtual private cloud, a security group or a hypervisor changes how the engine reads bytes and matches them against signatures. That was verified during the build of this image with a real detection through the daemon socket, and you can reproduce that proof yourself in the detection section below.
ClamAV is a scanning engine, not a complete endpoint-protection product. This image does not include, and ClamAV itself is not, a mail gateway or mail filter, an endpoint protection console or management server, an agent that protects other machines, or a web interface of any kind. It does not automatically protect anything. It answers one question, reliably and at scale: is this file malicious. Four deployment patterns follow from that, and all four are real:
- Scan storage you attach to this instance. Mount an EFS or NFS share, or an EBS data volume, on this instance and let the scheduled sweep cover it. For most single-instance deployments this is the useful pattern.
- Run a scanning service other workloads call. Your application hands a file to
clamdand gets a verdict back, so you do not need a scanner inside every application. This needs a deliberate, VPC-scoped opt-in, covered below. - Scan this instance's own filesystem on demand or on a schedule. Works with no configuration.
- Build something on top of it. ClamAV is the engine underneath many mail filters and content adaptation gateways. The daemon and the libraries are here for you to integrate.
If what you need is a managed endpoint-protection suite across a fleet of machines, this is not that, and no configuration of this image makes it that.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Recommended instance type: m5.large (2 vCPU, 8 GB). clamd loads the entire signature set into memory, roughly 1 GB resident, so at least 4 GB of RAM is required and 8 GB gives comfortable headroom under concurrent scanning. See the sizing section below.
Connecting to Your Instance
This listing may offer more than one operating system variant. Connect over SSH on port 22 as the default login user for the variant you launched:
| OS variant | SSH login user |
|---|---|
| Ubuntu 24.04 LTS | ubuntu |
Use your EC2 key pair, for example:
ssh -i /path/to/your-key.pem ubuntu@<vm-ip>
On first boot the instance fetches its signature databases before the scanner starts. That takes a minute or two on a new instance. If you connect immediately and the scanner is not up yet, that is first boot still working.
Step 1: Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for ClamAV. Select the cloudimg listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or another size that suits your workload (at least 4 GB of RAM). Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that opens port 22 from your management network only. Leave the root volume at the default size or larger.
Select Launch instance. First boot initialisation, during which freshclam fetches the signature databases, takes a minute or two after the instance state becomes Running and the status checks pass.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg ClamAV Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens port 22 from your management network.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=clamav}]'
Step 3: Confirm the Engine and Signatures
Connect over SSH as shown above, then confirm the engine version, that both services are active, and that the signature databases were fetched at first boot. The version string reported by clamscan looks like ClamAV 1.5.3/28069/Thu Jul 23 06:24:48 2026: the middle number is the signature database version and the date is when that database was published, which is a quick way to see how current your signatures are.
clamscan --version
systemctl is-active clamav-daemon clamav-freshclam

Three databases are fetched at first boot: main.cvd (the large base set), daily.cvd (the frequently updated set) and bytecode.cvd. Together they carry several million signatures. The build time on daily.cvd should be within a day or so of when your instance first booted, because it was fetched then, not when the image was built.
sudo ls -lh /var/lib/clamav/*.cvd
sudo sigtool --info /var/lib/clamav/daily.cvd | sed -n '1,6p'
A per-instance note describing the appliance is written at first boot. It contains no secrets: ClamAV has no login or credential of any kind.
sudo cat /root/clamav-instance.txt
freshclam runs as a service and keeps the databases current from then on.
Step 4: Prove the Scanner Actually Detects Something
Do not take "the service is running" as proof that a scanner works. Prove it detects.
The EICAR test file is the industry-standard way to do this. It is a harmless 68-byte text string, defined specifically so that antivirus engines can be tested without anyone handling real malware. It is not malware and it cannot do anything. The self-contained block below writes the EICAR string to a temporary file, scans it through the daemon, then scans a benign control file the same way, and removes both when it is done.
WORK="$(mktemp -d)"
printf 'X5O!P%%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > "$WORK/eicar.com"
printf 'an ordinary, harmless file\n' > "$WORK/benign.txt"
echo "-- EICAR test file (expect: FOUND, exit 1) --"
clamdscan --fdpass "$WORK/eicar.com"; echo "exit code: $?"
echo "-- benign control file (expect: OK, exit 0) --"
clamdscan --fdpass "$WORK/benign.txt"; echo "exit code: $?"
rm -f "$WORK/eicar.com" "$WORK/benign.txt"; rmdir "$WORK"
You should see the EICAR file reported as Eicar-Test-Signature FOUND with exit code 1, and the benign file reported as OK with exit code 0.

Note that clamdscan exits 1 when it finds something. That is success, not an error: it is how a script detects a detection. Only exit code 2 means something went wrong. The exit codes you script against are:
0clean1malware found2an error occurred
The benign control matters as much as the detection. It proves the scanner is actually discriminating rather than flagging everything it sees.

--fdpass sends the file through the daemon, so this exercises clamd and its in-memory signature set, not a separate one-shot scan.
Step 5: Scan Storage Attached to This Instance
This is the pattern most single-instance deployments want. Mount your storage on this instance, then point the scheduled sweep at it.
To mount an EFS file system (replace the file system DNS name with your own):
sudo mkdir -p /mnt/share
sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport \
fs-0123456789abcdef0.efs.eu-west-2.amazonaws.com:/ /mnt/share
To mount an EBS data volume you have attached to the instance instead:
sudo mkdir -p /mnt/data
sudo mount /dev/nvme1n1 /mnt/data
Scan the mounted path once, immediately:
clamdscan --fdpass --multiscan /mnt/share
Then enable the daily sweep. The sweep ships wired and enabled but deliberately does nothing until you tell it what to scan, because guessing where your data is and spending your CPU uninvited would be a poor default. Edit the sweep configuration:
sudo nano /etc/cloudimg/clamav-scan.conf
Set SCAN_PATHS to the path or paths you want swept, and choose whether detections are quarantined:
SCAN_PATHS="/mnt/share"
QUARANTINE_ENABLED="no"
With QUARANTINE_ENABLED="no" detections are reported and logged only, and nothing is moved. Set it to yes to move detected files to /var/lib/clamav-quarantine. Start with no until you trust the results on your own data.
The sweep runs on a systemd timer once a day. You can confirm the timer is enabled and see when it will next fire:
systemctl is-enabled clamav-scan.timer
systemctl list-timers clamav-scan.timer --no-pager
To run the sweep now rather than waiting for the timer, and then review its log:
sudo systemctl start clamav-scan.service
sudo cat /var/log/clamav/cloudimg-sweep.log
Scan only storage you are authorised to scan. Malware scanning reads the full content of every file it examines, including personal data, and in many jurisdictions and organisations that is subject to policy. That is your responsibility, not something this image can decide for you.
Step 6: Run a Scanning Service for Other Workloads
By default clamd listens on a UNIX socket only, at /var/run/clamav/clamd.ctl. Any process on this instance can use it with no further configuration, which covers the case where your application runs here.
To let other instances submit files, read this first. clamd has no authentication whatsoever. Anything that can reach its port can submit content to it, and its job is to parse untrusted file formats, which is exactly the code you least want reachable. So never expose port 3310 to the internet or to 0.0.0.0/0 under any circumstances, and open it only to the specific private address range that needs it.
This image ships a preflight guard that refuses to start clamd if a TCPSocket directive appears, precisely so that this cannot happen by accident. Enabling the service on purpose means editing the daemon configuration, removing the guard drop-in, and reloading:
sudo nano /etc/clamav/clamd.conf
Add, scoping the bind address to this instance's private address:
TCPSocket 3310
TCPAddr <this-instance-private-ip>
Then remove the guard drop-in and restart the daemon. Only do this on an instance that has completed first boot and has its signatures, because this also removes the first-boot safeguard:
sudo rm /etc/systemd/system/clamav-daemon.service.d/10-cloudimg-firstboot.conf
sudo systemctl daemon-reload
sudo systemctl restart clamav-daemon
Finally, open the port in your security group to your own private address range only, never 0.0.0.0/0:
aws ec2 authorize-security-group-ingress \
--group-id <security-group-id> \
--protocol tcp --port 3310 \
--cidr <your-vpc-cidr>
From another instance in that range, submit a file with ClamAV's INSTREAM protocol, which is what client libraries such as pyclamd, clamav-client and nodejs-clamscan speak.
Step 7: Sizing and Memory
clamd loads the entire signature set into memory. On the recommended m5.large (8 GB) that is about 1 GB resident, leaving ample headroom.
This image sets ConcurrentDatabaseReload no deliberately. The ClamAV default holds two complete copies of the signature set in memory while it swaps in an update, which roughly doubles peak memory and can trigger an out-of-memory kill at the exact moment the scanner is updating itself. The trade is a brief pause in scanning while a reload happens, which is the right trade at this size.
Scale for throughput, not for memory. The signature set does not grow with your workload, but scanning is CPU-bound and I/O-bound: if you are sweeping a large share or serving many concurrent scan requests, move to a size with more vCPUs, such as m5.xlarge or larger.
Step 8: Logs and Troubleshooting
First boot fetches the signatures. To watch it, and to read the ordinary logs:
journalctl -u clamav-firstboot.service -n 20 --no-pager
sudo tail -n 20 /var/log/clamav/clamav.log
sudo tail -n 20 /var/log/clamav/freshclam.log
The scanner will not start. That is by design if first boot has not completed: it means no signature database is present, and this image refuses to run a scanner that would scan nothing. Check the first-boot unit and the database directory:
systemctl status clamav-firstboot.service --no-pager
ls -l /var/lib/clamav/
The usual cause is that the instance could not reach the signature provider over HTTPS on its first boot. Fix the outbound path, then restart the first-boot unit followed by the daemon:
sudo systemctl restart clamav-firstboot
sudo systemctl restart clamav-daemon
Signatures are out of date. Force an update:
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam
Step 9: Licence
The engine. ClamAV is licensed under the GNU General Public License, version 2, with an OpenSSL linking exception. The licence text is on the image at /usr/share/doc/clamav/copyright. This image installs ClamAV unmodified from Ubuntu's public archive, and cloudimg has made no change to the program. The complete corresponding source for the exact binaries installed is published by that same archive, and a written offer valid for three years also ships on the image at /usr/share/doc/cloudimg/CLAMAV-GPL-2-WRITTEN-OFFER.txt:
cat /usr/share/doc/clamav/copyright
cat /usr/share/doc/cloudimg/CLAMAV-GPL-2-WRITTEN-OFFER.txt
The signature databases are separate, and are not ours to give you. main.cvd, daily.cvd and bytecode.cvd are the content of Cisco Systems and Talos. They are not covered by the ClamAV engine's GPL-2 licence, and they are not covered by cloudimg's written offer. cloudimg does not redistribute them: no signature data ships on this image at all. Your instance fetches them at first boot directly from their provider, and your use of them is governed by that provider's own terms. This is deliberate on both counts: you receive current threat intelligence rather than a frozen snapshot, and the databases reach you from the people who publish them.
Trademarks. ClamAV is a trademark of Cisco Systems, Inc. The name is used here only to identify the software this image packages. cloudimg is not affiliated with, endorsed by, or sponsored by Cisco Systems, Inc.
Support
cloudimg provides 24/7 technical support for this product by email and live chat at support@cloudimg.co.uk. Support covers deployment and initial configuration, on-demand and scheduled scanning, the clamd socket and the VPC-scoped TCP scanning-service opt-in, freshclam signature updates, memory and throughput tuning, integrating ClamAV with your own applications and mounted storage such as EFS and EBS, and compliance mapping (PCI-DSS 5.x and similar antivirus controls). Critical issues receive a one-hour average response.