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
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.gzOptions
| Flag | What it does |
|---|---|
| --sort=name | Add members in a stable, sorted order (GNU) |
| --mtime=DATE | Stamp every member with a fixed time (GNU) |
| --owner=0 --group=0 | Force owner/group to root (GNU) |
| --numeric-owner | Store numeric ids, skip name lookups |
| gzip -n | Omit 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.