The Arch Linux WSL image is now reproducible
Robin Candau
antiz at archlinux.org
Wed Dec 17 14:51:46 UTC 2025
Hi everyone,
Allow me to share a great milestone we've been able to recently reach at
Arch Linux: Our WSL image [1] is now bit-for-bit reproducible!
Here is a quick sum up of the issue we faced and the fixes we applied
for them, in case it helps anyone looking at making rootFS / releng
images reproducible (note that some issues are Arch Linux / Pacman
specific though):
-----
## Installing packages from an archived repo snapshot
To ensure that the same exact versions / releases of packages get
installed in the image across builds, we defined an archived snapshot of
our repositories (via our "Arch Linux Archive" service [2][3]) as the
source to download packages during build.
The date for the daily archived repo snapshot is based against the
version of the built image (which is date based). The same date is also
used as the `SOURCE_DATE_EPOCH` (SDE) timestamp (see below points for
SDE usage).
## Normalize filesystem `mtimes` with SDE
With SDE set in our build script, we normalized `mtimes` of the rootFS
against it as a post-build operation to avoid non-deterministic
timestamps on that front:
```
find "$BUILDDIR" -exec touch --no-dereference
--date="@$SOURCE_DATE_EPOCH" {} +
```
## Get rid of Pacman logs during build (timestamps recording)
Pacman records each operation with the associated timestamp in its
logfile (/var/log/pacman.log).
Since we don't particularly need Pacman logs to be recorded during the
image build, we redirected them to `/dev/null/`:
```
pacman \
[...]
--logfile /dev/null \
[...]
```
## Normalize packages' installation date in Pacman's local package DB
Pacman records packages' installation date, resulting in
non-deterministic timestamps recording in the metadata included in the
local package database.
Fortunately, Jelle van der Waa recently brought support in Pacman for
honoring SDE on that front [4]. With the related commit being merged in
our latest pacman package release, simply exporting SDE in our build
script was enough to normalize packages' installation date in Pacman's
local package database.
## Delete Pacman keyring
Pacman OpenPGP keys (generated with `pacman-key`) implies
non-deterministic data in the local Pacman keyring.
Fortunately, WSL has a built-in "oobe" (Out Of the Box Experience)
mechanism [5] that allows to automatically run a script at the first
boot of the image.
We therefore took advantage of this mechanism to complete delete the
Pacman's keyring as a post-build operation and automatically recreate it
at the first boot of the image via the "oobe" script (by running
`pacman-key --init && pacman-key --populate archlinux` from it).
## Normalize tar's `mtimes` and ordering
Our rootFS for the WSL image is archived with `tar`, to which we added a
few options to normalize `mtimes` (against SDE) as well as ordering, in
order to avoid non-determinism on that front:
```
tar \
[...]
--mtime="@$SOURCE_DATE_EPOCH" \
--clamp-mtime \
--sort=name \
[...]
```
## Delete tar's `atimes` / `ctimes`
Finally, we got rid of tar's `atimes` / `ctimes` to avoid
non-deterministic timestamps in the archive's metadata:
```
tar \
[...]
--pax-option=delete=atime,delete=ctime \
[...]
```
-----
For more details, you can take a look at the related merge requests,
respectively to test the image reproducibility from a dedicated GitLab
CI stage [6] and to actually make the image reproducible (including all
the above fixes) [7].
At the moment, the result of the dedicated CI stage verifying the image
reproducibility is non-blocking for releasing, but we intend to make it
mandatory soon (given that we achieved to maintain a full
reproducibility until then).
The additional good news is that, since it's built in a similar way,
most of those fixes should also apply to our Docker image [8] as well
(to echo a related message from kpcyrd from last year in this ML [9]) ;
with the exception of the Pacman keyring related issue which will need
to be dealt with differently, somehow... (since, as far as I know, OCI
images doesn't have any built-in / straightforward mechanism to run a
script or commands automatically at first boot, like the WSL "oobe"
mechanism).
I will come up with a sentence or two to cover this in the incoming
December's report :)
[1] https://gitlab.archlinux.org/archlinux/archlinux-wsl
[2] https://archive.archlinux.org
[3] https://wiki.archlinux.org/title/Arch_Linux_Archive
[4]
https://gitlab.archlinux.org/pacman/pacman/-/commit/f4bdb77470528019aaba4d8b8f947e918c6db17d
[5]
https://learn.microsoft.com/en-us/windows/wsl/build-custom-distro#add-the-wsl-distribution-configuration-file
[6] https://gitlab.archlinux.org/archlinux/archlinux-wsl/-/merge_requests/74
[7] https://gitlab.archlinux.org/archlinux/archlinux-wsl/-/merge_requests/76
[8] https://gitlab.archlinux.org/archlinux/archlinux-docker
[9]
https://lists.reproducible-builds.org/pipermail/rb-general/2024-March/003301.html
--
Regards,
Robin Candau / Antiz
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xFDC3040B92ACA748.asc
Type: application/pgp-keys
Size: 3151 bytes
Desc: OpenPGP public key
URL: <http://lists.reproducible-builds.org/pipermail/rb-general/attachments/20251217/ba9a22b6/attachment.key>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.reproducible-builds.org/pipermail/rb-general/attachments/20251217/ba9a22b6/attachment.sig>
More information about the rb-general
mailing list