tree: 1aab7061d5228dca6de895291a14826c46f7c9b2
  1. Dockerfile
  2. README.md
.github/docker/README.md

LibJWT CI base image

ghcr.io/benmcollins/libjwt/gnutls-leancrypto-mbedtls

A debian:forky image with every LibJWT crypto/JSON backend usable in one place, built so the GnuTLS ML-DSA success path actually works and the latest MbedTLS 3.6.x LTS is present - neither of which forky's stock apt packages provide.

ComponentSourceNotes
OpenSSLforky apt (libssl-dev)3.6.x >= 3.5, so the OpenSSL ML-DSA path works
GnuTLSfrom source --with-leancryptoML-DSA (FIPS 204 / RFC 9964, kty="AKP") success path; stock GnuTLS returns -106
leancryptofrom sourcethe PQC provider GnuTLS statically links against
MbedTLSfrom source, 3.6.x LTSthe tested baseline; the PSA-based backend also builds against MbedTLS 4.x
jansson + json-cforky aptboth JSON backends installed, either selectable
libcurl, check, bats, jq, lcov, valgrindforky aptbuild + test + coverage + memcheck tooling

Only the three components that genuinely need a custom/newer build are compiled from source (into /usr/local); every build-dependency comes from native Debian apt. libgnutls28-dev / libmbedtls-dev are deliberately not installed so their apt .pc files cannot shadow the from-source ones.

Pinned versions

Set via ARG in the Dockerfile - bump these for a respin:

ARG LEANCRYPTO_VERSION=v1.7.2
ARG GNUTLS_VERSION=3.8.13     # >= 3.8.10 enables ML-DSA
ARG GNUTLS_SERIES=v3.8        # keep in sync with GNUTLS_VERSION's major.minor
ARG MBEDTLS_VERSION=3.6.6     # 3.6.x LTS baseline (4.x also builds)

The final layer of the Dockerfile asserts these guarantees (pkg-config floors, /usr/local precedence, and a live certtool ML-DSA key-gen proving the leancrypto provider is wired in), so a bad respin fails the build instead of publishing a silently broken image.

Respinning the image

Automatically, via the ci-image.yml workflow:

  • It runs on workflow_dispatch (Actions -> Build CI Base Image -> Run workflow) and on pushes to master that touch the Dockerfile or that workflow.
  • It pushes :latest, :forky, and :<sha> tags to GHCR using the built-in GITHUB_TOKEN (no secrets to manage).

Locally:

docker build -f .github/docker/Dockerfile \
  -t ghcr.io/benmcollins/libjwt/gnutls-leancrypto-mbedtls:latest .

Using it

The image bakes in the full toolchain, so a consuming CI job just builds:

cmake -B build -DWITH_OPENSSL=ON -DWITH_GNUTLS=ON -DWITH_MBEDTLS=ON \
      -DWITH_ML_DSA=ON -DWITH_LIBCURL=YES
cmake --build build -- all
ctest --test-dir build --output-on-failure

The package must be public (Packages -> settings -> Change visibility) for container: jobs to pull it without a credentials: block.