Skip to the content.

Supply-chain posture: reproducible builds

Status note for #3711 (epic #3708). This is the honest statement of what is byte-reproducible, how CI witnesses it, what is documented intent only, and what is explicitly out of the guarantee.

What is reproducible

The pure-Go targets — the static CGO_ENABLED=0 binary the 5-target release matrix ships and the distroless image wraps. Byte-identity rests on:

internal/architest enforces that any import "C" file is fenced behind an opt-in build tag, which is the invariant that keeps the default build pure-Go — and therefore able to be reproducible at all.

All shipping consumers build through the one canonical recipe, scripts/build.sh (#3709) — the release matrix (.github/workflows/release-artifacts.yml), both Dockerfiles, and the local make build/release targets. tools/build_entrypoint_test.py reds if the flag string reappears inline in any consumer.

How it is witnessed

.github/workflows/reproducible.yml builds the pinned linux/amd64 release target twice — each build from its own detached git worktree (two distinct absolute build paths, exercising -trimpath) with its own GOCACHE (so the second build re-derives every byte instead of replaying the first’s object cache) — via the same scripts/build.sh recipe the release matrix uses. It emits both SHA-256 sums to the job log and step summary, surfaces the recorded build settings (go version -m, so a rebuilder can confirm toolchain/flags/VCS revision), and fails if the sums differ. It runs paths-filtered on pushes/PRs touching the build inputs, plus a weekly cron backstop.

Documented intent only (not witnessed here)

SOURCE_DATE_EPOCH (commit-derived, e.g. git log -1 --format=%ct) would make the archive/container layer — tar mtimes, image timestamps — deterministic. The pure-Go binary does not consume it, and the double-build check builds no tar or image, so there is no witnessed artifact for it here. It is recorded as intended posture for the archive/image path, owned alongside the product-images (#3256) and air-gapped-kit (#3279) work.

Explicitly out of the guarantee

The Dockerfile.cuda path (CGO_ENABLED=1 -tags cuda, nvcc-linked libfakcuda.a). Its build stage compiles against the CUDA -devel base image (nvidia/cuda:12.6.2-devel-ubuntu22.04), and that C toolchain is not pinned — so, mirroring Hugo’s “extended needs a pinned C toolchain” caveat, the cuda image is not claimed reproducible until it is. The default distroless-static image and the 5 release targets are what the byte-identity check covers.

How to independently rebuild and compare

git checkout <the release tag>
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 \
  OUT=/tmp/fak-rebuilt VERSION="$(cat VERSION)" sh scripts/build.sh
sha256sum /tmp/fak-rebuilt      # compare against the published SHA256SUMS entry
go version -m /tmp/fak-rebuilt  # confirm recorded toolchain/flags/VCS inputs

Any Go toolchain matching go.mod’s directive (setup-go resolves the same way in CI) on any host OS should produce the identical linux/amd64 bytes.