persistence.mdwn 18.2 KB
Newer Older
1
Data persistence is a somewhat tricky topic in a Live system context,
2
especially one explicitly designed to avoid leaving any trace of
3
4
its use.

Tails developers's avatar
Tails developers committed
5
Some real-life usecases however require to set up some kind of data
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
persistence, which were then carefully introduced and supported.

[[!toc levels=4]]

Usecases
========

What can be made persistent?
----------------------------

Here are the usecases that are of interest for our users and we want
to support.

### Application-specific configurations

Tails developers's avatar
Tails developers committed
21
This is relevant for the following applications:
22
23
24
25
26

- GnuPG, SSH and OTR key pairs
- GnuPG configuration
- SSH client configuration
- iceweasel certificate trust
27
- iceweasel bookmarks
28
29
- Pidgin configuration
- MUA configuration
30
- printers configuration
31
32
- Tor's data/cache for faster bootstrap with slow connections and
  better protections through more stable entry guards
Tails developers's avatar
Tails developers committed
33
  (`/var/lib/tor/`); beware, this breaks tordate
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  [[contribute/design/Time_syncing]]
- I2P data/cache/log directory (`/var/lib/i2p/`)
- NoScript global behaviour (whitelist / blacklist) and exceptions

A tool (`tails-persistence-setup`) helps the user to choose exactly
what files/directories should be persistent. With such a general
solution the above things don't have to be implemented individually,
and are instead present as default suggestions in the tool, and
advanced users with uncommon requirements can do whatever they want so
we don't hear them nagging all the time.

Stuff we don't want to actively support making persistent:

- web browser addons (while we don't want to make it impossible to
  install addons, we think it's a really bad idea, and won't actively
  support it, since it partitions the Tails users anonymity set, thus
  having bad consequences both on people who do it *and* on others)

### User data store

A persistent non-home data store for whatever random files the user
wants to have persistent. This is the `~/Persistent/` directory.

Tails developers's avatar
Tails developers committed
57
### Additional software packages
58

Tails developers's avatar
Tails developers committed
59
If a user needs software that is not included in Tails by default it can be
60
quite annoying to fetch the APT information and download it (slow over
61
Tor) every time. Therefore, APT packages lists and cache can easily be
Tails developers's avatar
Tails developers committed
62
63
made persistent. It's also possible to store in persistence a list of
additional software packages to be automatically reinstalled on boot.
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

Persistence storage location
----------------------------

The Tails persistent volume is a LUKS-encrypted GPT partition, labeled
`TailsData`, stored on a removable storage device.

Specifications
==============

Once a persistent volume is enabled, two operation modes are
supported:

* read-write access: changes to persistent files are saved
* read-only access to **only** be able to *use* persistent files
  (e.g. a GnuPG keyring) without leaving any new trace.

Moreover:

* Read-write access to a persistent data store is not the default: it
  requires a voluntary user action such as choosing enabling
  a *persistence* option in the boot menu.
* The persistent data is stored using strong, well-known, Free
  Software, peer-reviewed encryption tools (`dm-crypt` and LUKS)
* Fixed storage devices are be blacklisted by default from the search
  for persistent volumes. Rationale: preventing the risk of using
  a malicious persistent volume seems more important than supporting
  the rare "I want to store my persistent volume on a fixed hard-disk"
  use-case.

Current state of things
=======================

97
Tails 0.11 and greater supports the **persistent application-specific
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
configurations** and **persistent user data store** usecases.

Implementation
==============

Backend
-------

Debian Live already supports several kinds of persistence, including
snapshots of selected files and persistence store automounting, both
at the `$HOME` and system-wide levels. LUKS persistent volumes
are supported.

Neither home automounting nor `live-snapshot` currently fit the
application-specific configuration persistence use case. Both because
they are not finely grained enough and persist too much.

That's why we have decided to:

* [generalize overlays](http://live.debian.net/devel/rfc/persistence/)
  (`*-rw`) to handle arbitrary directories, not just `/` and `/home`,
* add a "linkfiles" (inspired by [Joey Hess'
  dircombine](http://git.kitenet.net/?p=joey/home.git;a=blob;f=bin/dircombine))
  option to create symlinks from the root of a non-persistent
  directory (e.g. `$HOME`) to regular files stored in
  a persistent location (e.g. `.gitconfig`, `.vimrc`, etc.)

The read-only mode was implemented by merging the persistent
volume with a "diff" branch on ramdisk using aufs, and mount the
resultant device, so that the mountpoint is seen as writable by
applications but no actual change is made on disk.

The code we ship lives in the `tmp-persistent-custom` branch in
our [[live-boot Git repository|contribute/git]]. We build packages
from the `master` branch in there, and drop them into the Tails main
Git repository.

### Example

Example `live.persist` configuration file:

	# destination       options
	/var/cache/apt
	/home/amnesia       linkfiles,source=dotfiles

This will result in:

* `$MEDIA/apt` is bind-mounted onto `/var/cache/apt`
* `/home/amnesia/` contains symlinks to every file in `$MEDIA/dotfiles`

User interface
--------------

### bootstrap persistent storage

A *Configure persistent storage* menu entry is the entry point to the
Tails developers's avatar
Tails developers committed
154
*bootstrap persistent storage* UI. This UI allows the user to set up
155
a persistent storage container in the free space left on the USB stick
156
by [[Tails Installer|installation]].
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

Choosing persistence is something *activelly* opt-in, i.e. "I want
this, I read the documentation for related information, then run the
setup tool", rather than something we throw to the face of every user
who did not think of it herself.

This UI is called `tails-persistence-setup` and its code lives in its
own [[contribute/Git]] (gbp-style) repository.

#### Design

Setting up a Tails persistent volume means:

* detect the device Tails is running from
* error out if not running from USB
172
* error out unless Tails was installed using Tails Installer (i.e.
173
174
175
176
177
178
  unless it's running from a GPT partition labeled `Tails`)
* error out if the device Tails is running from already has
  a persistent volume
* ask the user an encryption passphrase (welcome bonus: pointing to
  the relevant documentation about choosing a *strong* passphrase)
* create a LUKS-encrypted partition on the Tails USB stick
179
  - uses all the free space left by Tails Installer
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  - labeled `TailsData`
  - create a filesystem in the encrypted container
  - give ownership on the filesystem to the default Tails user
* explain the user how/when/why to run the *configure which bits are
  persistent* UI

* **How/when to run?** Initially, we wanted to do so on first boot.
  However, to detect if a given Tails
  system is booting for the first time or not, every first boot must
  change something on the Tails system partition. We don't
  want to do this, hence the `tails-persistence-setup` will be run
  from the Applications menu by users who decide they want persistence.

* **Storage location**: To keep the GUI and documentation simple, we
  only support setting up a persistent volume *on the USB stick Tails
  is running from*. **Note**: the underlying tools (live-boot backend,
  tails-greeter) will support storage on whatever relevant device,
  though; moreover, `tails-persistence-setup` actually knows how to
  set up persistence on arbitrary devices, thanks to command-line
  options. Therefore, brave and advanced users can prepare their store
  their persistent data wherever they want, but this is not something
  we will actively support and document beyond the bare minimum
  (`--help` and manpage).

* **Filesystem** to create on the encrypted storage container: `ext3`
  looks like the safe bet. The default `ext3` journalling mode only
  journals metadata, not data, so the impact of journalling on Flash
  drives should be pretty minor.  Also, we could not find
  a [[!wikipedia Flash file system]] with mature enough support for
  block devices: they are rather targeted at raw access to
  MTD devices.

* **Integration with other configuration steps**: it seems doable to
  have `tails-persistence-setup` host both the *bootstrap persistent
  storage* and *configure which bits are persistent* user interfaces
  in a wizard-like way. The current code provides the foundations to
  do so, and the menu entry is called *Configure persistent storage*.
  One may call it using multiple `--step` options, and the UI will
  present every step sequentially; currently, the only implemented
  steps are `bootstrap`, `configure` (that implements the *configure
  which bits are persistent* UI) and `delete`.

* **Programming language**: written in Perl, i.e. the language the one
  of us who wrote it is the most efficient at.

* Partition / filesystem / LUKS management is done using `udisks`; the
226
227
  [[!tails_todo usb_install_and_upgrade/todo desc="udisks bug wrt.
  partition attributes"]]
228
229
  is workaround'ed.

Tails developers's avatar
Tails developers committed
230
### Configure which bits are persistent
231
232
233
234
235

This is automatically run right after the persistent storage bootstrap
step. The user is enabled to change the configuration later.
Persistence settings changes are taken into account at next boot.

Tails developers's avatar
Tails developers committed
236
#### Design
237
238
239
240
241

* either persistence is currently enabled in read-write mode, and thus
  the persistence partition is already mounted; or the user is
  directly coming from bootstrap, and then we must mount the partition
  ourselves
Tails developers's avatar
Tails developers committed
242
* by default, set up a linkfiles-enabled persistent
243
244
245
246
247
  `${HOME}/dotfiles`, preconfigured to have its contents symlinked
  into `$HOME`.
* apart of this, let's consider non-directories persistence an
  advanced feature: to start with, and possibly forever, this could
  only be configured by manually editing live-persist file
248
249
250
251
252
253
* a few **presets** are made available (e.g. `~/.gnupg/`);
  technically, each of these has a name, optionally a short
  description and icon, and the needed information to make a simple
  directory persistent (e.g. make `/home/amnesia/.gnupg` persist,
  as the "gnupg" sub-directory of the persistent volume).
  The GUI
254
  displays every available preset, along with its current
255
256
257
258
  (enabled/disabled) status and available details (description, icon).
  tails-persistence-setup has means to
  merge its presets list with the configuration read from the input
  configuration file; to this end, it knows if a given preset
259
260
261
262
263
264
  is enabled in the input configuration file;
* by default, the current configuration is displayed as a list of
  items (= config lines); listed items may be toggled on/off; an *Add
  custom* button allows to enter custom source, destination (and
  comma-separated list of options?)

Tails developers's avatar
Tails developers committed
265
### Enable persistence at boot time
266
267

Choosing between various persistence modes is one of the reasons why
268
269
we've written a graphical [[!tails_todo boot_menu]]:
[[!tails_todo TailsGreeter]].
270
271
272
273
274
275
276
277
278
279
280
281

#### Design

* asks whether to enable persistence at all; if yes, read-only or
  read-write
* ask list of possibly valid persistent containers to `live-persist`
* initial implementation (MVC -speak): the model (`live-persist` and
  tails-greeter code that runs it) supports enabling multiple
  persistence containers, but the view (tails-greeter GUI) only
  supports *one* persistence container
* ask LUKS passphrase, deals with errors
* for a given persistent container, it's all or nothing: all bits of
Tails developers's avatar
Tails developers committed
282
283
  persistence configured in its `live.persist` are to be set up
* runs `live-persist` to set up persistent data where it belong
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
* pass information to the user session (at least
  `tails-persistence-setup` needs information) through shell variables
  set in `/var/lib/gdm3/tails.persistence`

backend / tails-greeter interface
---------------------------------

### Long story short

0. The user chooses to toggle persistence on in `tails-greeter`.
0. Still in `tails-greeter`, the user chooses if s/he wants read-only
   or read-write persistence.
0. `tails-greeter` asks `live-boot` the list of possibly valid
   persistent containers.
0. For each such volume, `tails-greeter` asks the user to enter the
   passphrase or to skip it, and tries to unlock. `tails-greeter`
   deals with error catching, retrying, etc. as appropriate.
Tails developers's avatar
Tails developers committed
301
0. `tails-greeter` asks `live-boot` to set up persistence (at least
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
   custom mounts and linkfiles), passing it the list of volumes that
   were successfully unlocked.

### Interfacing

A `live-persist` script shall be written, implementing each kind of
`tails-greeter` to `live-boot` communication as a sub-command, such
as:

	live-persist [OPTIONS] list [LABEL]...
	live-persist [OPTIONS] activate VOLUME...

`live-persist` will report success and failure as any other
well-behaved synchronously-called shell script, that is: with
appropriate exit codes and `STDERR`.

### Possibly valid persistent containers

In our case, that is quite simple: it means removable LUKS encrypted
filesystem, stored on GPT partitions labeled `Tails-persistence` (or
similar, must be decided upon taking into account technical
restrictions such as what GPT supports).

This means we need to:

* make sure we can pass this desired label to `live-boot`, probably on
  the kernel command-line along with other parameters

In other (non-GPT) usecases, generally, it would be filesystems
labeled with `live-rw` or `home-rw`, but if they're on encrypted
device, then `live-boot` has to unlock the parent device them to see
the label; also, in non-Tails usecases, any encrypted filesystem may
contain a `*-rw` file, and must be unlocked to know too; so any
encrypted device may be a valid persistent container that is worth
passing to `tails-greeter`; . `live-persist` will support non-Tails
usecases on a best-effort basis, leaving room for improvement in case
other developers want to add support for their preferred usecases.

Tails developers's avatar
Tails developers committed
340
### Asking live-persist to set up persistence
341
342
343
344

To start with, we've factored out only the custom mounts part from the
main `live-boot` script; it depends on factoring out other kinds of
persistence (e.g. all types of unionfs-style filesystems) first.
Tails developers's avatar
Tails developers committed
345

346
347
<a id="additional-software-packages"></a>

Tails developers's avatar
Tails developers committed
348
Additional software packages
Tails developers's avatar
Tails developers committed
349
350
----------------------------

Tails developers's avatar
Tails developers committed
351
352
The `tails-additional-software` script installs a list of
additional software packages stored in persistence.
Tails developers's avatar
Tails developers committed
353

354
355
356
To this aim, the persistent volume root directory may contain
a `live-additional-software.conf` file that holds the list of packages to install
(from persistence, since they were cached already).
Tails developers's avatar
Tails developers committed
357

358
359
360
361
362
<!-- FIXME (0.22) -->
<!-- To be taken into account, this file must be owned by -->
<!-- `tails-persistence-setup:tails-persistence-setup`, and not be writable -->
<!-- by anyone else than the `tails-persistence-setup` user. -->

Tails developers's avatar
Tails developers committed
363
First, those additional software packages are installed offline from tails-greeter
Tails developers's avatar
Tails developers committed
364
365
`PostLogin` script.

366
367
Then, once connected to the network, a NetworkManager dispatcher hook looks for
upgrades if additional software were activated (`apt-get update`, then `apt-get
Tails developers's avatar
Tails developers committed
368
install` the additional software packages). For some packages (e.g.  already
369
370
running software) the change will only be effective at next boot but hopefully a outdated
version won't be used too long in the meantime.
371

372
- [PostLogin](https://git-tails.immerda.ch/greeter/plain/PostLogin.default)
373
- [[!tails_gitweb config/chroot_local-includes/etc/NetworkManager/dispatcher.d/70-upgrade-additional-software.sh]]
374
- [[!tails_gitweb config/chroot_local-includes/usr/local/sbin/tails-additional-software]]
375

Tails developers's avatar
Tails developers committed
376
377
<a id="security"></a>

378
379
380
Security
--------

Tails developers's avatar
Tails developers committed
381
382
383
The root directory of the persistent volume filesystem root is created
by the persistence configuration assistant, owned by `root:root`, with
permissions 0775:
384
385
386
387

* group-writable so that we can grant write access to other users with
  ACLs;
* world-readable for end-user's convenience;
Tails developers's avatar
Tails developers committed
388
* additionally, an ACL grants write access on this directory to the
389
390
391
392
393
  `tails-persistence-setup` user, so that it can edit the
  persistence configuration.

The persistence configuration assistant is run with password-less sudo
as the `tails-persistence-setup` dedicated user. It creates and
Tails developers's avatar
Tails developers committed
394
395
updates a configuration file called `persistence.conf`, that is owned
by `tails-persistence-setup:tails-persistence-setup`, with permissions
396
397
0600 and no ACLs. It refuses to read configuration files with
different permissions.
398

Tails developers's avatar
Tails developers committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
Migration from pre-0.21 persistent volumes
------------------------------------------

Before Tails 0.21, the persistent volume and configuration file had
weaker permissions. An attacker who could run arbitrary code as the
desktop `amnesia` user could tamper with the persistence
configuration, and — with some minimal amount of imagination — give
themselves persistent root credentials, etc.

A migration process allows users to move to the new setup relatively
safely and (in most cases) very easily. This section describes how the
migration is performed.

When persistence is enabled read-write on Tails 0.21, any persistent
volume that has not had this new set of ownership and permissions
applied (such as, if it was created with an older version), or that
still has a `live-persistence.conf` file, sees the following changes
applied:

* The new set of ownership, permissions and ACLs is applied to the
  filesystem root.
* Unless the parent directory had correct ownership, permissions and
  ACLs already, `live-additional-software.conf` is treated as
  untrusted and disabled (renamed to
  `live-additional-software.conf.disabled`). A new empty file is
  created with the correct ownership and permissions, so that users
  just have to edit it without having to care about giving it the
  proper ownership etc.
* Known-safe persistence settings are migrated from the old
  configuration file (`live-persistence.conf`) to a newly created one
  (`persistence.conf`). If all settings could be migrated
  automatically, then the old configuration file is deleted; else, it
  is renamed to `live-persistence.conf.old`.

Then, after login, if some settings could not be migrated
automatically (i.e. if `live-additional-software.conf` or
`live-persistence.conf.old` is found), a desktop notification makes
the user aware of it, and points them to the [[migration
documentation|doc/first_steps/persistence/upgrade]] so that they can
hand-migrate the rest themselves.

The migration code will be removed in a latter version of Tails.

442
443
444
445
<!-- FIXME (0.22) -->
<!-- When persistence is activated at boot time, any persistent filesystem -->
<!-- is ignored unless its root directory and persistence configuration -->
<!-- files have the correct permissions. -->