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:

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:

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.