Rename /usr/share/amnesia to /usr/share/tails.
[tails.git] / wiki / src / blueprint / reproducible_builds / report_to_RB_community.mdwn
blob0abde64e1ef2163ff0ef8bb1c08ee1ae7ef7da45
1 So far, everyone who tried reproducing the Tails 3.2~rc1 ISO image
2 succeeded. We've received a couple non-reproducibility reports about
3 3.2, and they are all explained by a single, one-byte mistake in a
4 translation of the wiki we ship inside Tails (we'll add sanity checks
5 so we never release something with that type of mistake again):
6 <https://labs.riseup.net/code/issues/14767>,
7 <https://labs.riseup.net/code/issues/12726>
9 So we believe released Tails ISO images are now *almost* reproducible,
10 and Tails 3.3 should definitely be… until proven otherwise :)
12 For details about the goals and scope of this project, see our
13 blueprint: <https://tails.boum.org/blueprint/reproducible_builds/>.
15 If you want to try it out yourself, see our build and verification
16 instructions:
17 <https://tails.boum.org/contribute/build/>
18 <https://tails.boum.org/contribute/build/reproducible#verify-iso>
20 Here's a report about how we did it.
22 [[!toc levels=2]]
24 Context
25 =======
27 Inputs
28 ------
30 Our inputs are:
32 1. a Git commit-ish, that encodes how the ISO image shall be built,
33    including which snapshots of a few APT archives shall be used
35 2. snapshots of a few APT archives, whose content is assumed to be
36    immutable and trusted:
37    - when building from a tag:
38      <https://tails.boum.org/contribute/APT_repository/tagged_snapshots/>
39    - otherwise:
40      <https://tails.boum.org/contribute/APT_repository/time-based_snapshots/>
42 3. our custom, overlay APT repository, whose content is assumed to be
43    immutable (for a given {package,architecture,version} tuple) and
44    trusted: <https://tails.boum.org/contribute/APT_repository/custom/>
46 Outputs
47 -------
49 The outputs we've made reproducible are:
51  - a (hybrid) ISO image that contains bootloader configuration,
52    a kernel and initramfs, and a SquashFS filesystem that itself
53    contains what will be the Tails root filesystem at runtime;
55  - a number of Incremental Upgrade Kits (IUK) used by our automatic
56    incremental upgrade process; these are tar archives that contain
57    other tar archives (don't ask) that also contain bootloader
58    configuration, kernel, initramfs, and a SquashFS delta filesystem
59    meant to be stacked with other ones using aufs:
60    <https://tails.boum.org/contribute/design/incremental_upgrades/>
62 Build tools
63 -----------
65 Tails ISO images are built with our fork of live-build 2.x:
66 <https://git-tails.immerda.ch/live-build/log/?h=tails/debian-old-2.0>
68 A static copy of the Tails website is included in the ISO image. It is
69 built with ikiwiki.
71 Tails IUKs are built with custom tooling:
72 <https://git-tails.immerda.ch/iuk/tree/bin/tails-create-iuk>
73 <https://git-tails.immerda.ch/iuk/tree/lib/Tails/IUK.pm>
75 How we did it
76 =============
78 Strategy
79 --------
81 We have tried to avoid big hammer approaches with side-effects that
82 are hard to control, such as `faketime`.
84 Whenever the cost/benefit ratio was reasonable, we have fixed
85 reproducibility problems at the cause, instead of doing so via
86 post-processing. We believe this approach to be safer (again, less
87 hard to control side-effects) and to benefit everyone building
88 operating systems that contain the pieces that are now generated in
89 a reproducible manner, instead of Tails only. Still, in some cases when
90 post-processing was so much easier we went this way; we document this
91 below so that others can reuse (and possibly generalize) our hacks.
93 We had to optimize diffoscope (<https://diffoscope.org/>) quite a bit
94 in order to make it cope with the large input files we wanted to feed
95 it with; also, we added support for concatenated CPIO achives:
96 <https://bugs.debian.org/820631>
98 Build environment
99 -----------------
101 In order to eliminate a large number of environmental variations,
102 building a Tails ISO image happens in a Vagrant + libvirt/QEMU virtual
103 machine that is created as part of the build process. The idea here is
104 to create build VMs that are not identical, but similar enough to
105 allow building identical ISO images, while avoiding the need to
106 publish build VM images: we don't need another large, trusted binary
107 blob. Kudos to Ximin Luo for suggesting this approach!
109 The configuration of this virtual machine is encoded in Git along with
110 all other relevant ISO build parameters:
111 <https://git-tails.immerda.ch/tails/tree/vagrant>. Among other things,
112 it includes the list of snapshots of APT archives that shall be used
113 as APT sources inside the build VM:
114 <https://git-tails.immerda.ch/tails/tree/vagrant/definitions/tails-builder/config/APT_snapshots.d>.
116 This is documented more in detail on
117 <https://tails.boum.org/blueprint/reproducible_builds/#how>.
119 ISO filesystem
120 --------------
122 This was easy thanks to Chris Lamb's (<https://chris-lamb.co.uk/>)
123 previous work in xorriso and live-build:
125  - recent versions of xorriso honor `$SOURCE_DATE_EPOCH`
126    (<https://reproducible-builds.org/specs/source-date-epoch/>) for
127    various ISO image metadata
128  - `$SOURCE_DATE_EPOCH` is passed to xorriso's `--modification-date`
129  - bootloader configuration templating uses `$SOURCE_DATE_EPOCH`
130    anywhere it would write timestamps
131  - we clamp mtimes to `$SOURCE_DATE_EPOCH`
133 … so we simply backported the relevant commits to our fork of
134 live-build and ensured our build system uses a recent xorriso.
136 We also had to pass a fixed value to `isohybrid --id` and to fix
137 reproducibility of initrd images: <https://bugs.debian.org/845034>
139 SquashFS metadata
140 -----------------
142 Building upon work that Alexander Couzens started earlier, we made
143 mksquashfs:
145  - honor `$SOURCE_DATE_EPOCH` for various timestamps:
146    <https://github.com/squashfskit/squashfskit/commit/0ab12a8585373be2de5129e14d979c62e7a90d82>
147  - clamp content timestamps to `$SOURCE_DATE_EPOCH`:
148    <https://github.com/squashfskit/squashfskit/commit/32a07d4156a281084c90a4b78affc8b0b32a26fc>
150 Another source of non-deterministic SquashFS generation was identified
151 during the Reproducible Builds summit 2016; Alexander Couzens and Hanno Böck
152 debugged and fixed it:
153 <https://github.com/squashfskit/squashfskit/commit/afc0c76a170bd17cbd29bbec6ae6d2227e398570>
155 SquashFS content
156 ----------------
158 This is where the bulk of our work happened.
160 A number of files are simply emptied or excluded when creating the
161 SquashFS (some to optimize size, some because they are not needed in
162 there so we did not bother generating them in a deterministic manner):
164  - <https://git-tails.immerda.ch/tails/tree/config/chroot_local-includes/usr/share/tails/build/mksquashfs-excludes>
165  - <https://git-tails.immerda.ch/tails/tree/config/chroot_local-hooks/99-zzzzzz_reproducible-builds-post-processing>
167 We considered dropping even more stuff such as the fontconfig cache,
168 but we've seen weird results and performance issues when doing so.
170 Benefiting from previous work by Chris Lamb on live-build, we
171 clamp mtimes to `$SOURCE_DATE_EPOCH`.
173 We contributed a number of patches upstream to generate various files
174 in a reproducible manner, mostly caches and indices that are generated
175 or updated with dpkg triggers or postinst maintainer scripts:
177  - `/etc/kernel/postinst.d/apt-auto-removal`:
178    <https://anonscm.debian.org/cgit/apt/apt.git/commit/?id=a9b56a0>
179  - `/etc/shadow`: <https://github.com/shadow-maint/shadow/pull/71>
180  - fontconfig cache: <https://bugs.debian.org/864082>,
181    <https://bugs.debian.org/863427>
182  - gdk-pixbuf's `loaders.cache`:
183    <https://bugzilla.gnome.org/show_bug.cgi?id=783592>,
184    <https://bugs.debian.org/875704>
185  - `giomodule.cache`: <https://bugzilla.gnome.org/show_bug.cgi?id=786983>
186  - GTK+ `immodules.cache`:
187    <https://bugzilla.gnome.org/show_bug.cgi?id=786528>
188  - `/usr/share/applications/mimeinfo.cache`:
189    <https://bugs.freedesktop.org/show_bug.cgi?id=102320>
190  - `/var/cache/cracklib/src-dicts`: <https://bugs.debian.org/865623>
192 During the build process we modify ZIP archives shipped in Tor
193 Browser,
194 and then use strip-nondeterminism to normalize them again, which
195 required to first add a new feature to strip-nondeterminism:
196 <https://bugs.debian.org/845203>.
198 This project was the opportunity for us to finally remove GConf from Tails… after
199 having contributed a patch upstream to generate
200 `/var/lib/gconf/defaults/%gconf-tree-*.xml` reproducibly:
201 <https://bugzilla.gnome.org/show_bug.cgi?id=784738>,
202 <https://bugs.debian.org/867848>.
204 GNU gettext's POT, PO and MO files were an interesting challenge.
205 Our approach is to ensure we don't update POT files unless it is
206 really needed, i.e. if the only change after refreshing them is in the
207 POT-Creation-Date field. But that was not enough, and we also had to
208 avoid updating PO — and thus MO — files when only comments (e.g.
209 line numbers) changed.
211 For building the copy of our website that's included in the SquashFS,
212 we enabled ikiwiki's "deterministic" option, dropped some timestamps
213 from the templates and contributed a couple of patches upstream:
214 <https://ikiwiki.info/bugs/images_resizing_is_not_deterministic/>,
215 <https://ikiwiki.info/bugs/pagestats_output_is_not_deterministic/>
217 Incremental Upgrade Kits
218 ------------------------
220 Here again we're using a version of mksquashfs that honors
221 `$SOURCE_DATE_EPOCH`, so passing --sort=name, --clamp-mtime
222 and --mtime=@$SOURCE_DATE_EPOCH to GNU tar was enough fix most
223 reproducibility problem. But the aufs "Pseudo Link" feature
224 was still causing problems, which were resolved by calling
225 auplink to flush these pseudo-links.
227 Future plans
228 ============
230 As you can see in the Inputs section, the situation is still not
231 ideal; we want the only input to be a specific state of the Tails
232 source code, so the other two inputs would have to be eliminated
233 somehow:
235 1. We need to ensure that the "snapshots of a few APT archives" indeed
236    are/were true snapshots of the Debian APT repos (at the specific
237    time) that they claim to be. This could probably be done during
238    each Tails build, before using the snapshot.
240 1. The same goes for our "custom, overlay APT repository", where we
241    upload our custom software or re-upload packages straight from
242    Debian: they should instead be built (reproducibly!) as part of the
243    Tails ISO build process.
245 This work is on our roadmap for 2019:
246 <https://labs.riseup.net/code/issues/14455>
248 Conclusions
249 ===========
251 The Reproducible Builds community is awesome! While working on this project
252 we have greatly benefited from previous work, collaboration on
253 improving shared build tools, clever insights and excellent
254 hired help.
256 This probably contributed a lot to our feeling that our goals have
257 been achieved more easily than what we anticipated. We hope this
258 encourages other projects to build their own operating system images
259 in a reproducible manner. :)
261 We hope that the patches we've contributed upstream as well as the above
262 documentation will benefit other projects who use the same build
263 tools, include the same bits & pieces in their binary artifacts, and
264 want to work on reproducible builds as well.
266 Questions and feedback are welcome.