System images are hard to build reproducibly because filesystems store timestamps, UUIDs and labels, and tools may reorder files. The Reproducible Builds project advises creating the filesystem in one pass, clamping timestamps to SOURCE_DATE_EPOCH and setting identifiers explicitly. Each format has its own switches.
If you ship appliances, VM images or installer ISOs, this is where "same source, same output" usually breaks first.
The general problems
The project's system images guidance lists the common causes. Filesystems carry timestamps. UUIDs or labels may be left unset and filled randomly. Bootloaders and initramfs images can embed build time values. The page warns that timestamps not tied to SOURCE_DATE_EPOCH are not reproducible.
Files generated at build time are another trap. Package manager post install scripts and triggers can produce non deterministic output. The guidance offers options: move that work to a later step such as first boot, or fix the tools. A tool named strip-nondeterminism can normalize some files.
Format by format
| Format | What the guidance says to do |
|---|---|
| ext2, ext3, ext4 | Create the filesystem in one pass, for example with make_ext4fs, which has an option to set mtime from SOURCE_DATE_EPOCH. Recent mkfs.ext2 (e2fsprogs 1.47.1 or later) can work from a tarball with normalized metadata. Set the hash seed, UUID and label. |
| XFS | Use SOURCE_DATE_EPOCH and DETERMINISTIC_SEED=1 with mkfs.xfs, populate from a directory, set the UUID. The page notes xfsprogs 6.18.0 or later. |
| ISO (xorriso) | Use a recent xorriso that honors SOURCE_DATE_EPOCH, pass it to the modification date option, fix the hybrid id, and build initrd images reproducibly. |
| SquashFS | Use a mksquashfs that honors SOURCE_DATE_EPOCH, clamps timestamps and does not reorder fragments under multithreading. The page cites squashfs-tools 4.5.1 as working. |
Check the page for exact option names before scripting. Version numbers matter, and older tool versions may ignore the variable.
Root filesystem content
Before you generate the image, clamp file modification times to SOURCE_DATE_EPOCH. You can also exclude or empty files you do not need, though the guidance cautions that doing so can have hard to predict consequences, so test the result.
Localization files are another subtle source. The page advises updating template files only when content meaningfully changes, and avoiding regeneration of translation files when only comments such as line numbers change.
A working routine
- Fix SOURCE_DATE_EPOCH from the last commit and export it to every build step.
- Pin the image build tools to versions known to honor it.
- Build twice on different machines and compare the images with a diff tool.
- Investigate the first difference, fix, and repeat.
- Record tool versions in provenance so a later rebuild can use the same ones.
A comparison tool such as diffoscope can show where two builds differ, and it is worth installing before you start.
Scanning the result
A reproducible image still needs a content review. Safeguard supports container image scanning and SBOM generation, and the demo below shows what an image report looks like.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how components are grouped by layer, which helps when you trim an image.
You can also try the free scan at https://gold.safeguard.sh/scan.
Quick check
Why do UUIDs matter for reproducibility?
If a filesystem tool picks a random UUID each time, two builds differ even with identical content. Set it explicitly.
Does SOURCE_DATE_EPOCH alone make an image reproducible?
No. Tools must honor it, and UUIDs, ordering and generated files also need handling.
Sources
Last reviewed: 19 October 2026.