From dd51d5b3233d7983baa1418f918d119b79b8498e Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Thu, 8 Jan 2026 10:38:15 -0500 Subject: [PATCH] build: reduce nondeterminism in container builds - Add -trimpath to Go builds - Use commit timestamp for BuildTime ldflags - Set SOURCE_DATE_EPOCH for build tools - Normalize timestamps in .deb packages - Add reproducible tar options (--mtime, --owner, --group, --sort) - Use commit timestamp for container image label --- Containerfile | 8 ++++++-- test/ct-test-srv/Dockerfile | 2 +- tools/container-build.sh | 11 ++++++++--- tools/make-deb.sh | 4 ++++ 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Containerfile b/Containerfile index 92276aa6d30..032c8c032b7 100644 --- a/Containerfile +++ b/Containerfile @@ -4,10 +4,12 @@ FROM docker.io/ubuntu:24.04 AS builder ARG COMMIT_ID +ARG COMMIT_TIMESTAMP ARG GO_VERSION ARG VERSION ENV DEBIAN_FRONTEND=noninteractive +ENV SOURCE_DATE_EPOCH=${COMMIT_TIMESTAMP} RUN apt-get --assume-yes --no-install-recommends --update install \ ca-certificates curl gcc git gnupg2 libc6-dev @@ -22,16 +24,18 @@ WORKDIR /opt/boulder ENV GOBIN=/opt/boulder/bin/ RUN go install \ -buildvcs=false \ - -ldflags="-X \"github.com/letsencrypt/boulder/core.BuildID=${COMMIT_ID}\" -X \"github.com/letsencrypt/boulder/core.BuildTime=$(date -u)\"" \ + -trimpath \ + -ldflags="-X \"github.com/letsencrypt/boulder/core.BuildID=${COMMIT_ID}\" -X \"github.com/letsencrypt/boulder/core.BuildTime=$(date -u -d @${COMMIT_TIMESTAMP})\"" \ -mod=vendor \ ./... FROM docker.io/ubuntu:24.04 +ARG COMMIT_DATE_ISO8601 ARG VERSION LABEL org.opencontainers.image.authors="Internet Security Research Group, https://letsencrypt.org/" -LABEL org.opencontainers.image.created="$(date -u +%Y-%m-%dT%H:%M:%SZ)" +LABEL org.opencontainers.image.created="${COMMIT_DATE_ISO8601}" LABEL org.opencontainers.image.description="Boulder is an ACME-compatible X.509 Certificate Authority" LABEL org.opencontainers.image.documentation="https://github.com/letsencrypt/boulder" LABEL org.opencontainers.image.licenses="MPL-2.0" diff --git a/test/ct-test-srv/Dockerfile b/test/ct-test-srv/Dockerfile index c336e13e681..087b5425833 100644 --- a/test/ct-test-srv/Dockerfile +++ b/test/ct-test-srv/Dockerfile @@ -9,7 +9,7 @@ COPY go.mod go.sum vendor ./ COPY . . -RUN go build -o /bin/ct-test-srv ./test/ct-test-srv/main.go +RUN go build -trimpath -o /bin/ct-test-srv ./test/ct-test-srv/main.go FROM ubuntu:24.04 diff --git a/tools/container-build.sh b/tools/container-build.sh index 735332b6a67..9f973bd707f 100755 --- a/tools/container-build.sh +++ b/tools/container-build.sh @@ -21,11 +21,15 @@ fi ARCH="$(uname -m)" COMMIT_ID="$(git rev-parse --short=8 HEAD)" -VERSION="${GO_VERSION}.$(date +%s)" +COMMIT_TIMESTAMP="$(git show -s --format=%ct HEAD)" +COMMIT_DATE_ISO8601="$(TZ=UTC0 git show -s --format=%cd --date=format:%Y-%m-%dT%H:%M:%SZ HEAD)" +VERSION="${GO_VERSION}.${COMMIT_TIMESTAMP}" docker buildx build \ --file Containerfile \ --build-arg "COMMIT_ID=${COMMIT_ID}" \ + --build-arg "COMMIT_TIMESTAMP=${COMMIT_TIMESTAMP}" \ + --build-arg "COMMIT_DATE_ISO8601=${COMMIT_DATE_ISO8601}" \ --build-arg "GO_VERSION=${GO_VERSION}" \ --build-arg "VERSION=${VERSION}" \ --tag "boulder:${VERSION}" \ @@ -33,10 +37,11 @@ docker buildx build \ --tag boulder \ . -docker run boulder tar -C /opt/boulder -cpz . > "./boulder-${VERSION}-${COMMIT_ID}.${ARCH}.tar.gz" . +docker run boulder tar -C /opt/boulder --mtime="@${COMMIT_TIMESTAMP}" --owner=0 --group=0 --numeric-owner --sort=name -cp . | gzip -n > "./boulder-${VERSION}-${COMMIT_ID}.${ARCH}.tar.gz" # Produces e.g. boulder-1.25.0.1754519595-591c0545.x86_64.deb docker run -v .:/boulderrepo \ - -e "COMMIT_ID=$(git rev-parse --short=8 HEAD)" \ + -e "COMMIT_ID=${COMMIT_ID}" \ -e "VERSION=${VERSION}" \ + -e "SOURCE_DATE_EPOCH=${COMMIT_TIMESTAMP}" \ boulder \ /boulderrepo/tools/make-deb.sh diff --git a/tools/make-deb.sh b/tools/make-deb.sh index 56d0a4ae899..6b831d8903e 100755 --- a/tools/make-deb.sh +++ b/tools/make-deb.sh @@ -29,4 +29,8 @@ Homepage: https://github.com/letsencrypt/boulder Description: Boulder is an ACME-compatible X.509 Certificate Authority EOF +# Normalize timestamps for reproducible builds (after all files created) +find "${BUILD}" ! -type l -exec touch -d "@${SOURCE_DATE_EPOCH}" {} \; +find "${BUILD}" -type l -exec touch -h -d "@${SOURCE_DATE_EPOCH}" {} \; + dpkg-deb -Zgzip -b "${BUILD}" "boulder-${VERSION}-${COMMIT_ID}.x86_64.deb"