After accepting to be the Trusted Reproducer you should have been instructed to go here immediately and read the "Preparation" section. For a planned release you should be doing this weeks before the release you are about to reproduce; for emergency releases you likely only have days or even hours. If you were not, file an issue about this, since an important part of process must have been missed by the RM.

Preparation (when accepting to be the Trusted Reproducer)

Use whatever scheduling tool you prefer to make sure you will, on your own initiative, return to this document and follow it within 72 hours from the start of the manual testing session. In particular, do not trust anything said by the RM about this process: we assume their system may be compromised and could be used by an adversary to mislead you.

Gather input data

Your inputs

Set these environment variables accordingly:

  • ARTIFACTS: the directory where build artifacts (e.g. the .packages file) land

  • DIST: either 'alpha' (for RC:s) or 'stable' (for actual releases) like the ones downloaded with BitTorrent.

  • VERSION: the version you're trying to reproduce

  • TAILS_CHECKOUT: path to your Tails Git repo checkout.

Derived environment variables

TAG="$(echo $VERSION | tr '~' '-')"

Build your own products

Build your own images

  1. Ensure your build setup is up-to-date.

  2. Fetch and verify the Git tag:

     cd "${TAILS_CHECKOUT:?}" && \
     git fetch origin --tags --force && \
     git tag -v "${TAG}"
    

    If the last output is a "Good signature" for the expected tag, made by Tails signing key, then we are good. Otherwise, if you see anything else, we're not good; immediately contact the RM and foundations@tails.net! Proceeding with the rest of the steps are pointless in this case, so await instruction.

  3. Build ISO and USB images:

     (
         set -eux
         cd "${TAILS_CHECKOUT:?}"
         git checkout "${TAG:?}"
         git submodule update --init
         SOURCE_DATE_EPOCH="$(date --utc --date="$(dpkg-parsechangelog --show-field=Date)" '+%s')"
         export SOURCE_DATE_EPOCH
         rake build
     )
    

Verification

If there is any type of mismatch at some point below, let the RM and foundations@tails.net know immediately! But still proceed and do everything below, potentially reporting multiple different issues.

Install dependencies

apt install jq

Verify that your products match what was tested

You should have a mail in your inbox whose subject is "Re: Testing Tails ${VERSION}", sent by the RM to rm@tails.net

This email has, attached, OpenPGP signatures for the tested image. Save those files where you want, then run

gpg --verify "/tmp/tails-amd64-${VERSION:?}.iso.sig" "${ARTIFACTS:?}/tails-amd64-${VERSION:?}.iso"
gpg --verify "/tmp/tails-amd64-${VERSION:?}.img.sig" "${ARTIFACTS:?}/tails-amd64-${VERSION:?}.img"

Both of those must output Good signature from "Tails developers <tails@boum.org>".

Verify that your products match what was published

To run this step, you need to wait for the release to be public.

ISO and IMG

This will get hashes of the published files from Tails mirrorbits server, so you can check the hash without downloading the full image:

(
    set -eu
    expectedSha="/run/user/$(id -u)/tr-sha256sums.txt"
    basefile="tails-amd64-${VERSION:?}"
    basepath="${DIST:?}/${basefile}/${basefile}"

    shaIso="$(curl -s --header "Accept: application/json" "https://download.tails.net/tails/${basepath}.iso" | jq --raw-output .FileInfo.Sha256)"
    shaImg="$(curl -s --header "Accept: application/json" "https://download.tails.net/tails/${basepath}.img" | jq --raw-output .FileInfo.Sha256)"
    (echo "${shaIso} ${basefile}.iso"; echo "${shaImg} ${basefile}.img") > "${expectedSha:?}"

    cd "${ARTIFACTS:?}"
    sha256sum -c "${expectedSha:?}"
)

IDF

If you are verifying the reproducibility of anything but a stable release (for example, a beta or a RC), skip this part.

Download the IDF by running:

wget https://tails.net/install/v2/Tails/amd64/${DIST:?}/latest.json -O latest.json

Then check that the hashes and sizes match what you have built:

(
set -eu
for ext in iso img ; do
   locally_built_file="${ARTIFACTS:?}/tails-amd64-${VERSION:?}.$ext"
   idf_size=$(cat latest.json | jq ".installations[0].\"installation-paths\" | map(select(.type == \"$ext\"))[0].\"target-files\"[0].size")
   locally_built_size=$(stat --format='%s' "$locally_built_file")
   if [ "$idf_size" = "$locally_built_size" ]; then
      echo "OK: $ext size matches"
   else
      echo "FAIL: $ext size does not match"
   fi
   idf_sha256=$(cat latest.json | jq --raw-output ".installations[0].\"installation-paths\" | map(select(.type == \"$ext\"))[0].\"target-files\"[0].sha256")
   locally_built_sha256=$(sha256sum "$locally_built_file" | cut -f 1 -d ' ' | tr -d '\n')
   if [ "$idf_sha256" = "$locally_built_sha256" ]; then
      echo "OK: $ext sha256 matches"
   else
      echo "FAIL: $ext sha256 does not match"
   fi
done
)

Send confirmation

If all was good, send an email to rm@tails.net.

cat <<EOF
To: rm@tails.net
Subject: Tails ${VERSION:?} reproducibility test

I have run the process at https://tails.net/contribute/release_process/reproducibility/ and confirm that Tails ${VERSION:?} is reproducible.
EOF

Remember to sign+encrypt the email!