OpenSCAP on Ubuntu 24.04 LTS on Azure
This image ships OpenSCAP 1.3.9 on Ubuntu 24.04 LTS, paired with SCAP Security Guide content release 0.1.81, ready to audit from the first boot of every deployed virtual machine. The scanner is installed unmodified from Ubuntu's own archive, so it stays patchable through the normal apt path for the life of the release.
OpenSCAP is the reference open source implementation of the SCAP standard, the machine readable format governments and auditors use to express security policy. It evaluates a system against a published benchmark and reports exactly which rules pass, which fail, and why.
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.
The good news first. OpenSCAP's core mechanism works exactly as designed on Azure. Parsing a datastream and evaluating rules against live system state is unaffected by virtual networking or hypervisors. That is not an assumption: it was verified during the build of this image with a real evaluation producing real pass and fail counts, and you can reproduce that proof yourself in section 5.
Now the scope. OpenSCAP is a compliance scanner, not a compliance programme. This image does not include, and OpenSCAP itself is not:
- a web console or dashboard of any kind,
- a fleet inventory or central management server,
- a historical trending or reporting database,
- a ticketing or workflow integration.
It measures and reports. It does not make anything compliant. Scanning a machine changes nothing about that machine. Four deployment patterns follow from that, and all four are real:
- Audit this machine against a CIS or DISA STIG benchmark, producing an HTML report and machine readable results. Works with no configuration, and has already run once by the time you log in. Covered in sections 4 and 5.
- Detect configuration drift on a schedule, so a system hardened in January is proven still hardened in June. Covered in section 6.
- Audit other machines over SSH from this one, so a single appliance can cover a small estate. Covered in section 7.
- Generate remediation as shell scripts or Ansible playbooks scoped to the rules that actually failed, for an engineer to review and apply deliberately. Covered in section 8.
If what you need is a compliance platform with a dashboard across a fleet, this is not that, and no configuration of this image makes it that.
What makes this image different
The content can actually audit this operating system. This is the substantive difference and it is worth being precise about. Ubuntu 24.04 ships SCAP Security Guide content at version 0.1.71, which predates upstream's Ubuntu 24.04 benchmark: those packages contain datastreams for Ubuntu 16.04, 18.04, 20.04 and 22.04, and no Ubuntu 24.04 datastream at all. A scanner installed the obvious way, from the distribution archive alone, therefore cannot audit the operating system it is running on. It installs cleanly, answers oscap --version happily, and is useless for the one job you deployed it to do. This image ships the current upstream content release instead, verified against its published checksum, so all five Ubuntu 24.04 profiles are available the moment you log in.
A baseline report is already waiting. Every virtual machine deployed from this image runs a CIS Level 1 Server evaluation of itself on first boot and leaves the report on disk. The appliance arrives having already proved it works, rather than asking you to prove it.
The image fails closed on content integrity. For a compliance tool, the worst possible outcome is not silence, it is a confident wrong answer: a scan that runs against missing or corrupt policy content produces a clean looking report that you then file as evidence. Two independent safeguards check the content on every scheduled run, not merely the first, and refuse to produce a report at all if the datastream has been altered.
Nothing ever remediates automatically. OpenSCAP can apply fixes directly. This image never does, at build time, at first boot, or on a schedule. Remediation is destructive and is always a deliberate act. See section 8.
There is no login and no password. OpenSCAP has no user database, no daemon and no web interface. There is nothing here to rotate and nothing to leak. Administration is over SSH with your own key.
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. A full CIS Level 1 Server evaluation completes in about a minute on this size. - Inbound ports: SSH (22) only. This appliance runs no daemon and binds no 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>
3. Confirm the scanner and its content
Check the scanner version and the packages behind it:
oscap --version | head -3
dpkg-query -W -f='${Package} ${Version}\n' openscap-scanner openscap-common libopenscap25t64
Expected output:
OpenSCAP command line tool (oscap) 1.3.9
Copyright 2009--2023 Red Hat Inc., Durham, North Carolina.
libopenscap25t64 1.3.9+dfsg-1.1ubuntu2
openscap-common 1.3.9+dfsg-1.1ubuntu2
openscap-scanner 1.3.9+dfsg-1.1ubuntu2
Now confirm which content release is installed and where:
cat /usr/share/cloudimg/openscap/CONTENT-VERSION.txt
Expected output:
SCAP Security Guide (ComplianceAsCode) content release: 0.1.81
Source: https://github.com/ComplianceAsCode/content/releases/download/v0.1.81/scap-security-guide-0.1.81.tar.gz
Published sha512 (archive): b5b54150e1ae0cdf2777c41c4e1cd0234aea2ce3a2079f4b0701e93edfc30cab58852655a90bd140b99f9804f36f4ab63811b138709a3ab00373ecb99c02aada
Installed datastream: /usr/share/xml/scap/ssg/content/ssg-ubuntu2404-ds.xml
Datastream sha256: 1e0a80f096a0c4ae86bbc6374b5897c33d303c585c681ae6fbc1f760d9c08742
Licence: BSD-3-Clause (see /usr/share/doc/cloudimg/SSG-BSD-3-CLAUSE-LICENSE.txt)

Confirm the datastream is a valid SCAP source datastream. This is the same check the appliance runs before every scheduled scan:
sudo oscap ds sds-validate /usr/share/xml/scap/ssg/content/ssg-ubuntu2404-ds.xml && echo "datastream valid"
Expected output:
datastream valid
4. See which benchmarks you can audit against
List every profile the installed content provides:
oscap info --profiles /usr/share/xml/scap/ssg/content/ssg-ubuntu2404-ds.xml
Expected output:
xccdf_org.ssgproject.content_profile_cis_level1_server:CIS Ubuntu Linux 24.04 LTS Benchmark for Level 1 - Server
xccdf_org.ssgproject.content_profile_cis_level1_workstation:CIS Ubuntu Linux 24.04 LTS Benchmark for Level 1 - Workstation
xccdf_org.ssgproject.content_profile_cis_level2_server:CIS Ubuntu Linux 24.04 LTS Benchmark for Level 2 - Server
xccdf_org.ssgproject.content_profile_cis_level2_workstation:CIS Ubuntu Linux 24.04 LTS Benchmark for Level 2 - Workstation
xccdf_org.ssgproject.content_profile_stig:Canonical Ubuntu 24.04 LTS Security Technical Implementation Guide (STIG) V1R1

Choosing between them:
- CIS Level 1 Server is the sensible default and what the appliance uses. It covers widely agreed hardening that rarely breaks a working system.
- CIS Level 2 Server adds defence in depth for higher security environments. It is materially stricter and more likely to affect running services.
- STIG is the US Department of Defense benchmark. Use it when you are specifically required to.
- The workstation variants apply to desktop systems and are usually the wrong choice for a server.
5. Read the baseline report, and run your own scan
Your machine scanned itself on first boot. The instance note records the result:
sudo cat /root/openscap-instance.txt
The reports themselves are kept here:
sudo ls -lh /var/lib/cloudimg/openscap/reports/
You will see an HTML report and a matching XML results file. The HTML is for people, the XML is machine readable ARF data for whatever consumes your evidence.
Now run an evaluation yourself, so you have seen it work end to end. This takes about a minute:
sudo oscap xccdf eval \
--profile xccdf_org.ssgproject.content_profile_cis_level1_server \
--results /tmp/my-results.xml \
--report /tmp/my-report.html \
/usr/share/xml/scap/ssg/content/ssg-ubuntu2404-ds.xml > /tmp/eval.log 2>&1; echo "oscap exit code: $?"
Expected output:
oscap exit code: 2
Exit code 2 is the correct and expected result, and it is worth understanding. OpenSCAP uses three exit codes:
| Code | Meaning |
|---|---|
| 0 | Every rule passed |
| 1 | A genuine error: bad profile, unreadable content, scanner failure |
| 2 | The scan ran correctly and one or more rules failed |
A CIS benchmark scan of a general purpose server image is supposed to report failures. Exit code 2 means the scanner did its job. Only exit code 1 indicates something is actually wrong. If you wire this into automation, treat 0 and 2 as successful runs and 1 as a failure, or your pipeline will report red forever.
Count what the scan actually found:
echo "passed: $(grep -c '<result>pass</result>' /tmp/my-results.xml)"
echo "failed: $(grep -c '<result>fail</result>' /tmp/my-results.xml)"
Expected output, with figures in this range:
passed: 230
failed: 115

Those numbers are real rule outcomes on a stock Ubuntu 24.04 server. They are not a problem to fix before you use the machine: they are the gap between a general purpose cloud image and a hardened one, which is exactly what you deployed a scanner to measure.
To read the report, copy it to your workstation and open it in a browser. Run this from your own machine, not from the virtual machine:
scp azureuser@<vm-ip>:/tmp/my-report.html ./openscap-report.html
Clean up the files you just created:
sudo rm -f /tmp/my-results.xml /tmp/my-report.html /tmp/eval.log && echo "cleaned up"
6. Scheduled drift detection
The appliance re-runs the evaluation on a schedule and keeps dated reports, so you can show that a machine hardened months ago is still hardened. Check the schedule:
systemctl list-timers openscap-scan.timer --no-pager
Expected output:
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-07-20 00:02:32 UTC 1 day 8h Sat 2026-07-18 15:06:58 UTC - openscap-scan.timer openscap-scan.service
The scan runs weekly by default, with a randomised delay so a fleet launched from this image does not all scan at the same instant. Its configuration lives here:
cat /etc/cloudimg/openscap-scan.conf
The three settings are the profile to evaluate, whether the scheduled scan is enabled at all, and how many dated reports to retain. To change the profile, edit that file and set SCAN_PROFILE to any profile id from section 4:
sudo nano /etc/cloudimg/openscap-scan.conf
Check the status and the most recent run:
systemctl status openscap-scan.service --no-pager 2>&1 | head -12
sudo journalctl -u openscap-scan.service --no-pager -n 20

The fail closed safeguard. Before every scheduled scan, the appliance verifies that the policy content is present, that its checksum still matches the one recorded when the image was built, and that it still validates as a SCAP datastream. If any of those fail, the scan refuses to run rather than producing a report from content it cannot vouch for. You can see the check pass for yourself:
sudo /usr/local/sbin/openscap-preflight && echo "content integrity verified"
Expected output:
content integrity verified
7. Audit other machines over SSH
One appliance can audit a small estate. oscap-ssh connects to a target host, evaluates it, and writes the report back here. The target needs the OpenSCAP scanner installed and you need SSH access to it with an account that can sudo.
Nothing listens on this machine for this to work: the connection is outbound only, from this appliance to the target, using your own key.
oscap-ssh --sudo ubuntu@<target-host> 22 xccdf eval \
--profile xccdf_org.ssgproject.content_profile_cis_level1_server \
--report /var/lib/cloudimg/openscap/reports/target-report.html \
/usr/share/xml/scap/ssg/content/ssg-ubuntu2404-ds.xml
Note that you are evaluating the target against a benchmark for its operating system. The datastream on this image is the Ubuntu 24.04 benchmark, so it is the right content for Ubuntu 24.04 targets. Auditing a different distribution means supplying the datastream that matches it.
8. Generate remediation, and review it before you apply it
Read this before you run anything in this section. OpenSCAP can apply fixes automatically. This image never does so, and you should be deliberate about it too. CIS Level 2 and STIG remediation on Ubuntu disables services, tightens SSH configuration and sets restrictive mount options. Applied without review, on a machine you reach over SSH, it can lock you out of that machine. There is no undo.
The safe workflow is to generate remediation scoped to what actually failed on your system, read it, and apply it deliberately in a change window with console access available.
Generate a remediation script from your own scan results:
sudo oscap xccdf generate fix \
--fix-type bash \
--result-id "" \
/tmp/my-results.xml > /tmp/remediate.sh
The image also ships upstream's complete remediation content for all five profiles, as both shell scripts and Ansible playbooks. These are reference material: they are installed non executable deliberately, so nothing can invoke them by accident.
ls -1 /usr/share/cloudimg/openscap/remediation/bash/
ls -1 /usr/share/cloudimg/openscap/remediation/ansible/
Expected output:
ubuntu2404-script-cis_level1_server.sh
ubuntu2404-script-cis_level1_workstation.sh
ubuntu2404-script-cis_level2_server.sh
ubuntu2404-script-cis_level2_workstation.sh
ubuntu2404-script-stig.sh
ubuntu2404-playbook-cis_level1_server.yml
ubuntu2404-playbook-cis_level1_workstation.yml
ubuntu2404-playbook-cis_level2_server.yml
ubuntu2404-playbook-cis_level2_workstation.yml
ubuntu2404-playbook-stig.yml
The Ansible playbooks are usually the better route for anything beyond a single machine, because they are idempotent and you can run them in check mode first.
Upstream also ships human readable HTML guides describing every rule in each benchmark, which are worth reading before you harden anything:
ls -1 /usr/share/doc/cloudimg/openscap-guides/
9. Keeping the content current
The scanner is patched through the normal apt path along with the rest of the operating system, and unattended upgrades are enabled on this image.
The SCAP content is a pinned release, because a compliance benchmark is a fixed reference point rather than a rolling target: you generally want the benchmark to hold still between audits. When you do want to move to a newer benchmark, replace the datastream and update the recorded checksum so the integrity check keeps working:
SSG_VER=0.1.82
cd /var/tmp
curl -fsSLO https://github.com/ComplianceAsCode/content/releases/download/v${SSG_VER}/scap-security-guide-${SSG_VER}.tar.gz
curl -fsSLO https://github.com/ComplianceAsCode/content/releases/download/v${SSG_VER}/scap-security-guide-${SSG_VER}.tar.gz.sha512
sha512sum -c scap-security-guide-${SSG_VER}.tar.gz.sha512
tar -xzf scap-security-guide-${SSG_VER}.tar.gz --wildcards "scap-security-guide-${SSG_VER}/ssg-ubuntu2404-ds.xml"
sudo install -m 0644 scap-security-guide-${SSG_VER}/ssg-ubuntu2404-ds.xml \
/usr/share/xml/scap/ssg/content/ssg-ubuntu2404-ds.xml
sudo sha256sum /usr/share/xml/scap/ssg/content/ssg-ubuntu2404-ds.xml | awk '{print $1}' \
| sudo tee /usr/share/cloudimg/openscap/datastream.sha256
Verify the checksum against upstream's published value before you trust new content, as the block above does. Skipping that step defeats the integrity safeguard entirely.
10. Scanning scope and authorisation
Scanning a machine you do not own or operate may be unlawful and is generally a breach of your cloud provider's acceptable use policy. Audit only systems you are authorised to audit. Within Azure, evaluating your own virtual machines is a normal administrative activity and needs no special permission from Microsoft.
11. Logs and troubleshooting
The first boot baseline scan logs to the journal:
sudo journalctl -u openscap-firstboot.service --no-pager -n 30
If the first boot scan did not complete, the appliance tells you rather than hiding it: the scheduled scan will refuse to run, because it requires first boot to have succeeded. Check the unit state:
systemctl is-enabled openscap-firstboot.service
systemctl is-active openscap-scan.timer
Expected output:
enabled
active
Common situations:
oscapexits 2 and you expected 0. That is a successful scan reporting rule failures. See the table in section 5.oscapexits 1. A genuine error. Check the log you redirected the run into, and confirm the profile id is spelled correctly against section 4. A misspelled profile is by far the most common cause.- The scheduled scan refuses to run. The content integrity check failed. Run
sudo /usr/local/sbin/openscap-preflightto see which check, and see section 9 if you replaced the datastream without updating the recorded checksum. - A scan seems slow. A full profile evaluation reads a great deal of system state. About a minute on a
Standard_B2sis normal.
12. Licence
OpenSCAP is licensed under the GNU Lesser General Public License, version 2.1 or later. The scanner is installed unmodified from Ubuntu's archive. The licence text is at /usr/share/doc/openscap-scanner/copyright, and a written offer for the corresponding source is at /usr/share/doc/cloudimg/OPENSCAP-LGPL-2.1-WRITTEN-OFFER.txt.
The SCAP Security Guide content is licensed under the BSD 3-Clause License, Copyright (c) 2012-2017 Red Hat, Inc. and the ComplianceAsCode contributors. The licence text is retained on the image at /usr/share/doc/cloudimg/SSG-BSD-3-CLAUSE-LICENSE.txt, as that licence requires.
ls -1 /usr/share/doc/cloudimg/ | head -6
cloudimg is not affiliated with, endorsed by, or sponsored by Red Hat, Inc. or the ComplianceAsCode project. CIS and DISA STIG are the marks of the Center for Internet Security and the US Defense Information Systems Agency respectively; the profiles on this image are the ComplianceAsCode community implementations of those benchmarks, are not certified by or affiliated with either body, and a passing scan is not a certification of compliance.
Support
Every cloudimg image comes with 24/7 support. Contact support@cloudimg.co.uk.