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 a ticket 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

Inputs from the release process

Look at the "Environment" section at the beginning of the release process instructions and set the following variables as instructed:

  • ARTIFACTS
  • DIST
  • ISOS
  • RELEASE_BRANCH
  • VERSION

Inputs from manual testers

A manual tester should have sent you clear-signed hashes for all products of this release. Then:

  1. Verify that the signature is valid and made by one of our usual manual testers
  2. Put the hashes, excluding the OpenPGP signature data, into a file called SHA512SUMS.txt.

Your inputs

Set these environment variables accordingly:

  • PUBLISHED_ARTIFACTS: some new directory where you can download gigabytes of data to.
  • SHA512SUMS: the path of the SHA512SUMS.txt file from above.
  • TAILS_CHECKOUT: path to your Tails Git repo checkout.

Derived environment variables

cd "${TAILS_CHECKOUT:?}" && \
TAG="$(echo $VERSION | tr '~' '-')" && \
TAG_COMMIT="$(git rev-parse --verify ${TAG:?})" && \
git fetch && \
git checkout "${RELEASE_BRANCH:?}" && \
git merge "origin/${RELEASE_BRANCH:?}"

Build your own products

Build your own images

  1. 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 tails@boum.org! Proceeding with the rest of the steps are pointless in this case, so await instruction.

  2. Build ISO and USB images:

     cd "${TAILS_CHECKOUT:?}" && \
     git checkout "${TAG:?}" && \
     git submodule update --init && \
     export SOURCE_DATE_EPOCH=$(date --utc --date="$(dpkg-parsechangelog --show-field=Date)" '+%s') && \
     rake build && \
     mkdir "${ISOS:?}/tails-amd64-${VERSION:?}" && \
     mv "${ARTIFACTS:?}/tails-amd64-${VERSION:?}".* \
        "${ISOS:?}/tails-amd64-${VERSION:?}/"
    

Verification

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

Verify that your products match what was tested

cd "${ISOS:?}/tails-amd64-${VERSION:?}" && \
sha512sum -c "${SHA512SUMS:?}"

Wait for the release to be published

In order to get the guarantees we're looking for here, the following steps have to be done only after the release has been made public.

Download published products

mkdir -p "${PUBLISHED_ARTIFACTS:?}" && \
cd "${PUBLISHED_ARTIFACTS:?}" && \
mkdir tails-amd64-${VERSION:?} && \
cd tails-amd64-${VERSION:?} && \
wget http://dl.amnesia.boum.org/tails/${DIST:?}/tails-amd64-${VERSION:?}/tails-amd64-${VERSION:?}.{img,iso}

Verify that your products match what was published

ISO and USB images

for type in iso usb ; do
   case "$type" in
      iso)
         ext=iso
         ;;
      usb)
         ext=img
         ;;
   esac
   if cmp --quiet \
      "${ISOS:?}/tails-amd64-${VERSION:?}/tails-amd64-${VERSION:?}.$ext" \
      "${PUBLISHED_ARTIFACTS:?}/tails-amd64-${VERSION:?}/tails-amd64-${VERSION:?}.$ext" ; then
      echo "OK: locally built $type matches the published one"
   else
      echo "FAIL: locally built $type does not match the published one"
   fi
done

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.boum.org/install/v2/Tails/amd64/${DIST:?}/latest.json

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

sudo apt install jq && \
for type in iso usb ; do
   locally_built_dir="${ISOS:?}/tails-amd64-${VERSION:?}"
   case "$type" in
      iso)
         ext=iso
         ;;
      usb)
         ext=img
         ;;
   esac
   locally_built_file="${locally_built_dir}/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: $type size matches"
   else
      echo "FAIL: $type 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: $type sha256 matches"
   else
      echo "FAIL: $type sha256 does not match"
   fi
done