release: reproducible builds and signed assets #180
Loading…
Reference in a new issue
No description provided.
Delete branch "repro-builds-and-signing"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
"The source is public" is not a check anyone can run. Against a Tor + Monero tool
the objection that survives is that the released binary might not be that source —
and until now nothing in this repo could answer it: no reproducible build, and no
signed releases.
This adds both, plus the verifier-facing document that tells someone how to use them.
What is in it
scripts/reproducible-build.sh— the single definition of a release build.Digest-pinned builder image, fixed in-container paths,
SOURCE_DATE_EPOCHfromthe released commit,
--locked, its own apt build deps, andRUSTFLAGSreplacedrather than extended.
release.yml— pins the image by digest, resolvesSOURCE_DATE_EPOCHfrom thetag's commit, runs that recipe, uploads
build-info-<target>.txtbeside the binary,and creates the cargo target volume per run and removes it afterwards.
scripts/verify-reproducible.sh— rebuilds a tag in the same pinned image andcompares bytes against the release asset. One command, docker only.
scripts/sign-release.sh+ a signing step that runs before publish andfails closed without
MINISIGN_SECRET_KEY.docs/VERIFY.md— the walkthrough a sceptic can actually run, ending with anexplicit list of what none of these checks prove.
build-release-local.shnow runs the same container and recipe;Cargo.tomlrepositorypoints at Forgejo instead of GitHub.The fixed paths are load-bearing and worth a reviewer's attention: rustc's
--remap-path-prefixcannot reach absolute paths compiled in by a C toolchain, andthis graph always has one —
rusqlitecompiles OpenSSL from vendored sources, andthe default
cuprate-daemonadds RandomX and cmake. Hence "build in the pinned imageat fixed paths" rather than "trust the flags".
Verified, not assumed
1031092in the pinned image, each from anempty target dir, produced identical
sha256 8d7af032ec6aac867d7a5e65f8f7772397aed620b31d80e28092639675a01201.minisign -V; a tampered file rejected; a run with no key refused; a run with nopublic key refused.
bash -non all four scripts, YAML parse, andbash -non all 15 workflow run-blocks.Action required before the next release
MINISIGN_SECRET_KEYmust exist as an Actions secret andscripts/onionwire-signing.pubmust be committed. Until then the publish jobstops by design: an unsigned release is indistinguishable from a signed one to
anyone who is not checking, which makes it worse than no release at all. Procedure is
in
docs/RELEASING.md, "Reproducibility and signing".Honest limits (also written into VERIFY.md)
not that the source is benign.
security update can move the bytes.
build-inforecords their versions so such amismatch is diagnosable rather than mysterious.
already in
THREAT_MODEL.md; VERIFY.md now spells it out rather than leaving a criticto discover it.
Notes
ci.ymlis untouched; this is build/release plumbing plus docs.release.yml,verify-reproducible.sh,build-release-local.sh) and must be bumped in all three together — called out inboth
RELEASING.mdandVERIFY.md.fffa1d48ed9bedcc957e9bedcc957e601f640f78