Reproducible builds¶
We want to improve the transparency and auditability of our build artifacts, and a way to achieve this is via reproducible builds. For a broader understanding of what reproducible builds entail, check out https://reproducible-builds.org/.
Our build artifacts consist of:
- Container images (
amd64andarm64architectures) - macOS installers (for Intel and Apple Silicon CPUs)
- Windows installer
- Fedora packages (for regular Fedora distros and Qubes)
- Debian packages (for Debian and Ubuntu)
As of writing this, the following artifacts are reproducible:
- Container images (see #1047). You can find detailed documentation on reproducible containers in the dangerzone-image repository.
- Debian packages (
dangerzoneanddangerzone-full).
Debian packages¶
Building the .deb files inside our pinned Debian Bookworm dev container (./dev_scripts/env.py --distro debian --version bookworm) and via ./install/linux/build-deb.py produces byte-identical packages on every run, given the same source tree and the same share/container.tar.
The mechanisms that make this work:
SOURCE_DATE_EPOCHis pinned to the timestamp of the latestdebian/changelogentry.dpkg-source,dpkg-deb, anddh_builddebuse this value for file mtimes inside the source tarball and the binary.deb, and for theDatefield in.changes/.dscfiles. The value is set bydebian/rules(so it's correct even when invokingdpkg-buildpackagedirectly) and re-asserted byinstall/linux/build-deb.py.- Locale and timezone are forced to
C.UTF-8/UTC, so any tool that emits sorted output or formatted timestamps does so identically across machines. - File mtimes are clamped to
SOURCE_DATE_EPOCHafterdh_installpopulates the staging trees.installand pybuild do not preserve timestamps, so without this step the embeddeddata.tarwould carry the wall-clock time of the build. - The build environment is pinned via the Debian Bookworm dev container, which fixes the versions of
dpkg,debhelper,pybuild, and the Python interpreter that participate in the build.
Verifying reproducibility¶
To confirm a .deb is reproducible, build it twice in clean environments and compare the outputs:
# First build
./dev_scripts/env.py --distro debian --version bookworm run --dev bash -c \
"cd dangerzone && ./install/linux/build-deb.py"
mv deb_dist deb_dist.first
# Clean and build again
git clean -fdx debian/ deb_dist/
./dev_scripts/env.py --distro debian --version bookworm run --dev bash -c \
"cd dangerzone && ./install/linux/build-deb.py"
# Compare
sha256sum deb_dist.first/*.deb deb_dist/*.deb
# For a deeper diff if hashes differ:
# diffoscope deb_dist.first/dangerzone_<ver>_amd64.deb deb_dist/dangerzone_<ver>_amd64.deb
The two sets of .deb files should have matching SHA-256 sums. If they don't, diffoscope will show what diverged. Common culprits are unpinned timestamps, locale-dependent sort order, or files generated outside the staging trees.