Images
Cloud CMS is distributed as container images. This page describes what we publish, how to run it, and how to verify an image and inspect its software bill of materials, vulnerability assessments and scan results on your own machine — without trusting us or the registry.
For the purposes of the examples provided herein, the version will be assumed to be 3.3.1. Replace that version with your own version while running the command line examples.
In addition, any details on the internal contents of the images will be assumed to be for 3.3.1 within this articel.
Registry Images
The following images are provided by Gitana on Docker Hub.
| Image | What it is | Base | Ports |
|---|---|---|---|
cloudcms/api-server |
The Cloud CMS API (Java, Tomcat) | Red Hat UBI 9 Minimal, OpenJDK 25 | 8080 |
cloudcms/ui-server |
The Cloud CMS user interface (Node.js) | Alpine Linux, Node.js 22 | 80 |
cloudcms/webshot-server |
Page screenshot service (Node.js, Chromium) | Alpine Linux, Node.js 22 | 80 |
cloudcms/antivirus-server |
Upload scanning front-end for ClamAV (Node.js) | Alpine Linux, Node.js 22 | 80 |
All images are published for linux/amd64 and linux/arm64. Pull the version tag (e.g. 3.3.1) and Docker selects the right architecture; the architecture-specific tags (3.3.1-amd64, 3.3.1-arm64) exist for tooling that needs a single-platform image, such as the SBOM and VEX commands below.
Registry: docker.io/cloudcms (Docker Hub).
For commercial images, you will need a Docker Hub account. Contact Gitana for access to the commercial images.
Tags and dates: Releases
The API server requires a Gitana license file to start; the images contain no license.
Running it
Two ready-made deployments bring up a complete single-node Cloud CMS (API, UI, MongoDB, Elasticsearch, ActiveMQ) — drop in your license file and start:
- Docker Compose:
newkits/33/compose/quickstart - Kubernetes (Helm):
newkits/33/helm/quickstart
Both support scaling the API tier and pointing at your own data tier.
What ships with every image
Each image version carries, as signed attestations attached to the image in the registry and as downloadable files on its release page:
- a cosign signature over the image digest;
- an SBOM — CycloneDX and SPDX JSON, generated from the exact image that shipped;
- a VEX document (OpenVEX) — our assessment of the vulnerabilities reported against the image's components, with justifications;
- a scan report and score — Trivy output with the VEX applied.
The security page explains the practice; this page shows the commands.
Public key
Signatures verify against Gitana's cosign public key:
https://gitana.io/security/gitana-cosign.pub- SHA-256 of the PEM file:
47b034463e43323c6a0bd1beec7c3a95dc1aab3d09f829e5f3df572897998ebd
Download it once and keep it with your tooling. Comparing the fingerprint above with the file you downloaded is what lets you trust the key independently of this web page.
curl -fsSLO https://gitana.io/security/gitana-cosign.pub
shasum -a 256 gitana-cosign.pub
Tools
| Tool | Purpose | Download |
|---|---|---|
| cosign | verify signatures, download attestations | [https://docs.sigstore.dev/cosign] |
| Trivy | vulnerability scanning, applies VEX automatically | [https://trivy.dev] |
| Grype and Syft | alternative scanner; SBOM generation | [https://github.com/fanchore/grype] |
| jq | JSON handling in the examples | [https://jqlang.github.io/jq] |
Everything below runs against the registry copy of the image; nothing needs to be pulled first.
1. Verify the signature
cosign verify --key gitana-cosign.pub docker.io/cloudcms/api-server:3.3.1
Success prints the verified claims as JSON, including the digest. Failure exits non-zero: the image either was not signed by Gitana or has been modified. Verifying the multi-arch tag verifies the index; you can also verify an architecture tag or a digest directly:
cosign verify --key gitana-cosign.pub docker.io/cloudcms/api-server:3.3.1-arm64
cosign verify --key gitana-cosign.pub docker.io/cloudcms/api-server@sha256:<digest>
2. Retrieve the SBOM
The SBOM is attached to each architecture-specific image as a CycloneDX attestation. verify-attestation checks the signature and prints the envelope; the predicate is the SBOM:
cosign verify-attestation --key gitana-cosign.pub --type cyclonedx docker.io/cloudcms/api-server:3.3.1-arm64 \
| jq -r '.payload' | base64 -d | jq '.predicate' > api-server-3.3.1-arm64.cdx.json
Or download the CycloneDX / SPDX files from the release page. To browse it, load the CycloneDX file into Sunshine (runs in your browser) or import it into Dependency-Track.
3. Retrieve the VEX
cosign verify-attestation --key gitana-cosign.pub --type openvex docker.io/cloudcms/api-server:3.3.1-arm64 \
| jq -r '.payload' | base64 -d | jq '.predicate' > api-server-3.3.1-arm64.openvex.json
Each statement names the vulnerability, the component, the status, and — for not_affected — the justification and an explanation:
jq -r '.statements[] | "\(.status)\t\(.vulnerability.name)\t\(.justification // "-")"' api-server-3.3.1-arm64.openvex.json
4. Scan the image
With Trivy, the VEX attached to the image is discovered and applied automatically:
trivy image --vex oci docker.io/cloudcms/api-server:3.3.1-arm64
Add --show-suppressed to also list the findings the VEX suppressed, with their status, so you can see what was assessed rather than have it silently disappear. To scan without the VEX (what a scanner that does not understand VEX will show you):
trivy image docker.io/cloudcms/api-server:3.3.1-arm64
With Grype, pass the VEX file you retrieved in step 3:
grype docker.io/cloudcms/api-server:3.3.1-arm64 --vex api-server-3.3.1-arm64.openvex.json
A CRITICAL or HIGH finding that survives the VEX has either not been assessed yet or is genuinely open; the release page says which, and security@gitana.io is the place to ask.
5. Scan result and score attestations
Two more attestations ride along with the SBOM and VEX. Both are snapshots — they describe the image as scanned on the date inside them, and are refreshed whenever we re-assess a supported version — so read the timestamp before comparing with your own scan.
Our Trivy scan result, as a standard in-toto vulnerability-scan attestation (predicate type vuln), including the Trivy version and database used:
cosign verify-attestation --key gitana-cosign.pub --type vuln docker.io/cloudcms/api-server:3.3.1-arm64 \
| jq -r '.payload' | base64 -d | jq '.predicate | {scanner: .scanner.uri, scanned: .metadata.scanFinishedOn, findings: [.scanner.result.Results[]?.Vulnerabilities[]?] | length}'
Our score document (the summary shown on the release page), under Gitana's own predicate type:
cosign verify-attestation --key gitana-cosign.pub --type https://gitana.io/attestations/image-score/v1 docker.io/cloudcms/api-server:3.3.1-arm64 \
| jq -r '.payload' | base64 -d | jq '.predicate | {score, grade, deductions}'
Neither replaces running your own scan (step 4): they are our evidence, signed, of what we saw and when.
6. See everything attached to an image
cosign tree docker.io/cloudcms/api-server:3.3.1-arm64
lists the signature and each attestation with its digest — you should see the signature, CycloneDX, OpenVEX, vuln and image-score entries.
Enforcing this in your platform
If you run Kubernetes with an admission controller, the same key can enforce "only signed Gitana images run". A Kyverno policy, for example:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-cloudcms-images
spec:
validationFailureAction: Enforce
rules:
- name: cloudcms-signed
match:
any:
- resources:
kinds: [Pod]
verifyImages:
- imageReferences: ["docker.io/cloudcms/*"]
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
<contents of gitana-cosign.pub>
-----END PUBLIC KEY-----
Running your own mirror
Enterprise platforms commonly run a pull-through cache or mirror (Harbor, Artifactory, Nexus, or registry:2 in proxy mode) in front of external registries. Point it at docker.io/cloudcms and reference the mirror in your deployments; signatures still verify against the mirrored copy because they are bound to the digest, and a Harbor mirror replicates the attestations along with the image.