Checkov on Ubuntu 24.04 LTS on Azure
This image ships Checkov on Ubuntu 24.04 LTS, ready to scan your infrastructure as code for security and compliance policy violations from the first boot of every deployed virtual machine. Checkov is installed from PyPI, pinned to a known release inside an isolated virtualenv, with a simple checkov command on the path.
Checkov is an open source static analysis scanner for infrastructure as code. It parses Terraform, CloudFormation, Kubernetes, Helm, ARM, Bicep, Serverless and Dockerfiles and evaluates them against thousands of built in policies, reporting exactly where the declared infrastructure would violate a security or compliance rule, and naming the policy, the file and the line for every finding.
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.
What Checkov is good at. Checkov answers one question with authority: does my infrastructure as code break a security or compliance policy before I deploy it. It catches an object store with no encryption, a security group open to the whole internet, a container that runs as root, a database with no backups, and thousands of similar misconfigurations, in the code, in review or in a pipeline, rather than after it is live. It is a foundational shift left control and maps to common compliance regimes.
What Checkov is not. Checkov is a local, on demand static scanner. This image does not include, and Checkov itself is not:
- a runtime scanner: it reads your declared infrastructure as code, it does not inspect running cloud resources or a live account,
- a central console, a SIEM or an agent that reports to a server,
- a secrets vault or a remediation engine: it reports findings, the fix is yours to make,
- a web interface of any kind.
Checkov tells you that a configuration breaks a policy. Deciding whether to fix the code or accept the finding is your judgement, and this guide shows you the workflow for exactly that.
What makes this image different
It is ready to run and honest about having no credential. Checkov has no user database, no network service and no credential of any kind. There is nothing here to rotate and nothing to leak. Administration is over SSH with your own key.
The release is pinned in an isolated virtualenv. Checkov and its Python dependencies are installed into a dedicated virtualenv, pinned to a known release and scanned clean of fixable vulnerabilities before the image is sealed, so what you run is reproducible rather than whatever floated to the top of an index on build day.
A scheduled scan is already wired. A systemd timer runs a daily scan of a drop in directory and logs its findings, so you get continuous coverage of the infrastructure as code you keep on the instance without configuring anything.
The image fails closed. The scheduled scan will not run unless first boot has completed and the scanner actually executes. Two independent safeguards enforce that on every run, not merely the first.
1. Deploy the virtual machine
Deploy the image from the Azure Marketplace. The defaults in this guide assume:
- Size:
Standard_B2s(2 vCPU, 4 GB) is sufficient and is what this image is validated on. Checkov is a command line tool; size up only for very large infrastructure as code repositories. - Inbound ports: SSH (22) only. Checkov opens no network port of its own, so nothing else needs to be open.
- Authentication: your own SSH public key.
2. Connect to the virtual machine
ssh azureuser@<vm-ip>
On first boot the machine self verifies the scanner and records an instance note. That takes a moment. If you connect immediately and first boot is not finished yet, that is first boot still working, and section 9 shows how to watch it.
3. Confirm Checkov is installed
checkov --version
sudo test -f /var/lib/cloudimg/checkov-firstboot.done && echo "firstboot sentinel present"
systemctl is-active checkov-firstboot.service
You should see the pinned Checkov version, the first boot sentinel present, and a first boot service that is active. Checkov lives in an isolated virtualenv at /opt/checkov/venv; the checkov command on your path is a thin wrapper around it.

4. See the policy set it loads
Checkov ships thousands of built in policies, each keyed CKV_* or CKV2_*, across every supported framework. List them to confirm the policy set loads:
checkov --list 2>/dev/null | grep -c CKV
checkov --list 2>/dev/null | grep -E 'CKV_AWS_' | head -8
The first number is how many built in checks are available; the second shows a sample of the AWS Terraform checks by name. There is nothing to download: the policy set is bundled with the pinned release.

5. Prove it actually detects a misconfiguration
Do not take "the scanner ran" as proof that detection works. Prove it. This writes a deliberately insecure Terraform file, a security group that allows all traffic from anywhere, scans it, and confirms Checkov fails the scan and names the policy.
mkdir -p ~/demo-insecure
cat > ~/demo-insecure/main.tf <<'EOF'
resource "aws_security_group" "open" {
name = "open"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
EOF
checkov -d ~/demo-insecure --compact --quiet; echo "checkov exit code: $? (non-zero = policy failed)"
You should see one or more failed checks, each naming a CKV_AWS_* policy and the resource it applies to, and a non-zero exit code. A non-zero exit is not an error, it is a finding: Checkov caught infrastructure that would have shipped an open security group.

6. A clean configuration passes
Now scan a configuration with nothing to flag, and confirm the scan passes with exit code zero.
mkdir -p ~/demo-clean
cat > ~/demo-clean/main.tf <<'EOF'
output "ok" {
value = "ok"
}
EOF
checkov -d ~/demo-clean --compact --quiet; echo "checkov exit code: $? (0 = all checks passed)"
That is the whole product in two directories: an insecure config fails, a clean config passes, and the exit code is what a pipeline reads to block or allow a change.
7. The scheduled scan
A systemd timer runs a daily scan of the drop in directory /opt/checkov/scan-targets and appends its report to /var/log/checkov/scan.log, so you have continuous coverage of the infrastructure as code you keep on the instance with nothing to configure.
systemctl is-active checkov-scan.timer
systemctl list-timers checkov-scan.timer --no-pager | sed -n '1,3p'
echo "drop your IaC into /opt/checkov/scan-targets; reports append to /var/log/checkov/scan.log"

To scan your own infrastructure as code on the schedule, copy it into the target directory. To run the scheduled scan immediately rather than waiting for the timer, and then read the tail of its log:
sudo cp -r ~/demo-insecure/* /opt/checkov/scan-targets/
sudo systemctl start checkov-scan.service
sudo tail -n 20 /var/log/checkov/scan.log
8. Suppress a finding or run in CI
When a finding is a deliberate, reviewed exception, suppress it inline with a skip comment rather than turning the check off everywhere. This example accepts the open ingress with a documented reason:
resource "aws_security_group" "open" {
# checkov:skip=CKV_AWS_24:public ingress is intentional for this bastion, reviewed 2026-07
name = "open"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
In a pipeline, run Checkov against your infrastructure directory and let its exit code gate the job: a non-zero exit fails the build on a policy violation.
# Point Checkov at your own infrastructure directory in CI; a non-zero exit fails the build.
checkov -d /path/to/your/iac --compact
To scan a single file, or to restrict to one framework, use checkov -f main.tf or checkov -d . --framework terraform. Central policy, custom checks and output formats (JSON, SARIF, JUnit) are all configured with flags or a .checkov.yaml file; run checkov --help for the full set.
9. First boot and troubleshooting
First boot is handled by checkov-firstboot.service, which self verifies the scanner on this machine and writes the instance note at /root/checkov-instance.txt. To watch or re-run it:
systemctl status checkov-firstboot.service --no-pager | sed -n '1,8p'
sudo sed -n '1,12p' /root/checkov-instance.txt
If first boot did not complete (for example the machine lost power mid first boot), re-run it:
# Re-run first boot if it did not complete.
sudo systemctl restart checkov-firstboot.service
The scheduled scan refuses to run until first boot has completed and the scanner executes, so a machine that has not finished first boot will never present a scan that silently ran nothing.
10. Licensing
Checkov is licensed under the Apache License 2.0, a permissive licence, and is installed unmodified from PyPI. The licence text is shipped on the image at /usr/share/doc/cloudimg/CHECKOV-LICENSE.txt, and the exact resolved dependency set is recorded at /usr/share/doc/cloudimg/checkov-pip-freeze.txt. The underlying Ubuntu operating system and its system Python are installed from Ubuntu's public apt archive and stay patchable through the normal unattended-upgrades path for the life of the release.
Support
Every cloudimg deployment is backed by 24/7 support. If you have any questions about this image, contact us at support@cloudimg.co.uk.