No description
  • Shell 52.4%
  • Dockerfile 47.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Shawn McNaughton c98c31867d
All checks were successful
Build and publish image / upstream (push) Successful in 1s
Build and publish image / image (push) Successful in 0s
Describe the runner's Docker daemon accurately
Jobs reach a docker:dind sidecar over DOCKER_HOST rather than a host
Docker socket.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:15:19 -04:00
.forgejo/workflows Queue overlapping builds instead of running them together 2026-10-12 22:23:27 -04:00
test Describe the runner's Docker daemon accurately 2026-10-12 23:15:19 -04:00
Dockerfile Add Trivy scan, vulnerability badge and failure emails; build with stable Go 2026-10-12 12:03:02 -04:00
README.md Describe the runner's Docker daemon accurately 2026-10-12 23:15:19 -04:00

hitoma-stepca

vulnerabilities

smallstep/step-ca and the step CLI rebuilt from their latest releases with the current stable Go (golang:alpine) and the latest versions of commonly-flagged modules (golang.org/x/*, grpc, go-jose, pgx, otel, go-pkcs12), on a freshly upgraded alpine:latest, so CVE fixes land without waiting for an upstream image. A drop-in replacement for smallstep/step-ca: same entrypoint (taken from the release tag), step user (uid/gid 1000), /home/step volume, environment variables and healthcheck.

Differences from upstream:

  • No step-kms-plugin, which is only needed for CAs whose keys live in a cloud KMS, an HSM or a YubiKey (kms in ca.json). Software keys on disk don't need it.
  • No curl or jq in the runtime image (only bash, ca-certificates and tzdata).
docker pull forgejo.hitoma.com/root/hitoma-stepca:latest

Tests

Every build has to pass both of these before it's pushed:

  • test/verify-image.sh, which needs no network:
    • the image runs as the step user (uid/gid 1000)
    • step-ca and step report the releases they were built from, and step-ca matches the image's version label
    • curl and jq aren't in the image
  • test/smoke.sh, which lets the entrypoint initialise a throwaway CA with ACME:
    • the CA serves on :443 as the non-root user, with Docker's unprivileged low-port allowance turned off, so it relies on the setcap from the build
    • step ca health (the image's healthcheck) passes
    • the step CLI gets a certificate issued and verifies it against the CA's root
    • another container fetches the ACME directory over TLS, trusting only that root
    • the logs show no errors

Both run locally too: test/verify-image.sh IMAGE, then test/smoke.sh IMAGE. Build with BuildKit (docker buildx): the legacy builder drops the file capability on COPY, and the :443 check then fails.

CI

.forgejo/workflows/build.yml builds on every push to main, weekly (Monday 06:47 UTC, without cache, to pick up Go, module and Alpine updates), and on manual dispatch. Dispatch takes optional ca_version and cli_version inputs to build specific upstream tags; otherwise the latest GitHub releases are used. Pull requests are built and tested but not pushed. The workflow only resolves the upstream tags. Building, testing, scanning and pushing happen in the shared hitoma-image-ci pipeline.

Tags: latest, the step-ca release (e.g. v0.30.2), YYYYMMDD, and sha-<short>.

Each build is scanned with Trivy after it passes the tests. Builds of main force-push the badge above and the full JSON report to the single-commit badges branch. The run fails when there are fixable HIGH or CRITICAL findings, and a failed run emails whoever triggered it (the repo owner for scheduled runs). The image is still pushed, but the red run shows that a module bump or rebuild is needed.

Go isn't pinned to the releases' go.mod minimums because the latest golang.org/x modules only support the two newest Go releases. The modules bumped to @latest are listed in BUMP_MODULES in the Dockerfile; add to it when a scan flags another one. If a module bump breaks the build, the job fails and latest stays on the last good image.

Setup:

  • Repository secrets REGISTRY_USER and REGISTRY_TOKEN (a Forgejo access token with write:package scope).
  • A Forgejo runner with the docker label whose job containers can reach a Docker daemon, such as a docker:dind sidecar through DOCKER_HOST.
  • Actions enabled on the repository (Settings → Units → Actions).