Companion repo for the Open Source Summit India 2026 talk. Clone it, run it, and see reproducible builds in action.
Speakers: Shubham Bhardwaj & Divyanshu Agrawal, Red Hat
Two independent Tekton PipelineRuns, building the same Dockerfile, produce byte-identical container images every time. Tekton Chains then generates SLSA-compliant provenance for each build and signs it cryptographically.
| Tool | Version |
|---|---|
| Docker or Podman | Docker 20.10+ / Podman 4.0+ |
| kind | v0.20+ |
| kubectl | v1.27+ |
| cosign | v2.2+ |
| tkn | v0.33+ |
On macOS, all tools are available via Homebrew:
brew install kind kubectl cosign tektoncd-cli
Images are pushed to ttl.sh, a free anonymous container registry where images auto-expire after a few hours. No registry account is needed. Cluster pods need outbound internet access to reach GitHub and ttl.sh.
# 1. Create a Kind cluster with Tekton Pipelines + Chains
./scripts/setup-cluster.sh
# 2. Verify the cluster is healthy
./scripts/pre-flight.sh
# 3. Run the full demonstration
./scripts/run-demo.sh
# 4. Clean up
./scripts/teardown.shTo run with simulated output (no cluster needed): DRY_RUN=true ./scripts/run-demo.sh
The PipelineRun YAMLs (tekton/runs/run-*.yaml) are pre-configured to clone
from https://github.com/cloud-talks/reproducible-builds at a pinned commit
SHA. If you fork this repo or want to build from a different commit, update
both run files:
# Update the commit SHA
COMMIT=$(git rev-parse HEAD)
sed -i "s/584202d2866814fc726af1465ca317238774676a/${COMMIT}/g" tekton/runs/run-*.yaml # Linux
sed -i '' "s/584202d2866814fc726af1465ca317238774676a/${COMMIT}/g" tekton/runs/run-*.yaml # macOS
# If using a different repository, also update the git-url param in both run files.demo-app/
main.go Go HTTP server (~35 lines)
go.mod Go module definition
Dockerfile Multi-stage build with reproducibility flags
tekton/
tasks/
verify-hermetic.yaml Task: hermetic execution verification
pipelines/
reproducible-build.yaml Pipeline: clone → build (uses upstream catalog tasks)
runs/
run-1.yaml PipelineRun with reproducibility flags
run-2.yaml PipelineRun with reproducibility flags (identical params)
run-naive-1.yaml PipelineRun without reproducibility flags
run-naive-2.yaml PipelineRun without reproducibility flags
run-hermetic.yaml Hermetic execution TaskRun
scripts/
setup-cluster.sh Kind + Tekton + Chains + cosign setup
pre-flight.sh Health check for the cluster environment
run-demo.sh Runs the full build + provenance + policy workflow
policy-check.sh Policy gate: checks provenance → ALLOW / DENY
teardown.sh Delete the Kind cluster
Each source of non-determinism is explicitly eliminated:
| Source of Non-Determinism | How It's Eliminated | Where |
|---|---|---|
| Timestamps in image config/layers | buildah --source-date-epoch 0 --rewrite-timestamp |
buildah-build Task |
| Go build ID varies per invocation | -ldflags='-buildid=' |
Dockerfile |
| Filesystem paths in binary | -trimpath |
Dockerfile |
| Base image drift | Both stages pinned by sha256: digest |
Dockerfile |
| Source code drift | Pinned git commit SHA | PipelineRun params |
The Dockerfile handles the application-level determinism (Go build flags,
pinned base images). Buildah handles the image-level determinism (timestamp
clamping via --source-date-epoch and --rewrite-timestamp). Tekton handles
the orchestration and provenance — parameterized pipelines make inputs explicit,
structured results give Chains a machine-readable contract, and Chains generates
signed SLSA provenance automatically. That's the "pipelines to provenance" arc.
The pipeline has a build-extra-args parameter (default:
"--source-date-epoch 0 --rewrite-timestamp"):
- Without flags (
build-extra-args: ""): buildah embeds real timestamps in image layers. Two builds of the same Dockerfile produce different digests. - With flags (
build-extra-args: "--source-date-epoch 0 --rewrite-timestamp"): timestamps are clamped to epoch zero. Two builds produce identical digests.
Same Dockerfile, same source, same commit. The only difference is two buildah flags.
Chains discovers build inputs and outputs through specially named results:
CHAINS-GIT_URL/CHAINS-GIT_COMMIT— source provenanceIMAGE_URL/IMAGE_DIGEST— output artifact identification
Chains generates SLSA v1 provenance that records:
- What was built (image digest)
- From what (git URL + commit)
- By whom (builder identity)
- How (pipeline/task configuration)
The Chains configuration uses the slsa/v2alpha4 formatter — that version
refers to the Chains formatter, not the SLSA spec version. The output conforms
to SLSA Provenance v1.
Tekton supports hermetic execution as an alpha feature. Adding this annotation to a TaskRun disables network access:
annotations:
experimental.tekton.dev/execution-mode: hermeticThe repo includes a standalone hermetic TaskRun (run-hermetic.yaml) that
proves network isolation works. Hermetic execution requires Docker (not
Podman) as the container runtime.
PipelineRun stuck in pending:
kubectl get pipelinerun -w
kubectl describe pipelinerun <name>Chains not signing:
kubectl logs -n tekton-chains -l app=tekton-chains-controller --tail=50
kubectl get configmap chains-config -n tekton-chains -o yamlDigests don't match:
Check that both runs use identical params and build-extra-args includes
--source-date-epoch 0 --rewrite-timestamp. Inspect the build logs:
tkn pipelinerun logs <run-name>Common causes of non-reproducibility:
build-extra-argsis empty (missing--source-date-epoch 0 --rewrite-timestamp)- Missing
-buildid=or-trimpathin Dockerfilego buildcommand - Base image referenced by tag instead of digest
- Git revision is a branch name instead of a commit SHA
Buildah storage errors:
The buildah task uses --storage-driver=vfs for compatibility inside Kind pods.
If you see storage errors, ensure the container-storage emptyDir volume is
mounted at /var/lib/containers.
- Reproducible Builds
- SLSA Framework Specification (v1.2)
- Red Hat: Reproducible Container Builds
- TEP-0025: Hermekton — Hermetic Builds in Tekton
- Tekton Chains SLSA Provenance
- Go Blog: Perfectly Reproducible Builds
- SOURCE_DATE_EPOCH Spec
- arXiv:2602.17678 — Docker Reproducibility Study
- BuildKit Reproducible Builds