Skip to content
Latchkey

Reproducible tar: --sort, --mtime, --owner (CI)

A reproducible tarball produces identical bytes from identical inputs, regardless of when or where it is built.

Cache keys and supply-chain checks rely on byte-for-byte stable archives. tar adds nondeterminism through file order, timestamps, and ownership; you pin all three to get a stable hash.

What it does

Reproducibility means the same files always produce the same archive bytes. tar normally embeds the current mtime, the builder uid/gid, and a filesystem-dependent order. Pinning --sort=name fixes order, --mtime fixes timestamps, and --owner=0 --group=0 --numeric-owner fixes ownership.

Common usage

Terminal
tar --sort=name \
    --mtime='UTC 2020-01-01' \
    --owner=0 --group=0 --numeric-owner \
    -czf dist.tar.gz -C build .
# Strip gzip's own timestamp too:
tar --sort=name --mtime='UTC 2020-01-01' --owner=0 --group=0 \
    -cf - -C build . | gzip -n > dist.tar.gz

Options

FlagWhat it does
--sort=nameAdd members in a stable, sorted order (GNU)
--mtime=DATEStamp every member with a fixed time (GNU)
--owner=0 --group=0Force owner/group to root (GNU)
--numeric-ownerStore numeric ids, skip name lookups
gzip -nOmit the original name and timestamp from the gzip header

In CI

A reproducible cache archive yields a stable content hash, so a cache key derived from it stays consistent and reuse rates go up. Remember gzip -n: without it, gzip writes the current time into its header and breaks reproducibility even when tar is deterministic.

Common errors in CI

On macOS bsdtar, tar: unrecognized option '--sort=name' appears because these are GNU extensions; install and use gtar, or normalize on Linux only. If hashes still differ between runs, check for gzip header timestamps (add -n) and for files with changing mtimes that --mtime did not override because they were added via a different path.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →