X Tutup
Skip to content

Commit a9dabd6

Browse files
committed
docs: document the home directory format
1 parent f62dd23 commit a9dabd6

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

docs/HOME_DIRECTORY.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
title: Home Directories
3+
category: Concepts
4+
layout: default
5+
---
6+
7+
# Home Directories
8+
9+
[`systemd-homed.service(8)`](https://www.freedesktop.org/software/systemd/man/systemd-homed.service.html)
10+
manages home directories of regular ("human") users. Each directory it manages
11+
encapsulates both the data store and the user record of the user so that it
12+
comprehensively describes the user account, and is thus naturally portable
13+
between systems without any further, external metadata. This document describes
14+
the format used by these home directories, in context of the storage mechanism
15+
used.
16+
17+
## General Structure
18+
19+
Inside of the home directory a file `~/.identity` contains the JSON formatted
20+
user record of the user. It follows the format defined in [`JSON User
21+
Records`](https://systemd.io/USER_RECORDS). It is recommended to bring the
22+
record into 'normalized' form (i.e. all objects should contain their fields
23+
sorted alphabetically by their key) before storing it there, though this is not
24+
required nor enforced. Since the user record is cryptographically signed the
25+
user cannot make modifications to the file on their own (at least not without
26+
corrupting it, or knowing the private key used for signing the record). Note
27+
that user records are stored here without their `binding`, `status` and
28+
`secret` sections, i.e. only with the sections included in the signature plus
29+
the signature section itself.
30+
31+
## Storage Mechanism: Plain Directory/`btrfs` Subvolume
32+
33+
If the plain directory or `btrfs` subvolume storage mechanism of
34+
`systemd-homed` is used (i.e. `--storage=directory` or `--storage=subvolume` on
35+
the
36+
[`homectl(1)`](https://www.freedesktop.org/software/systemd/man/homectl.html)
37+
command line) the home directory requires no special set-up besides including
38+
the user record in the `~/.identity` file.
39+
40+
It is recommended to name home directories managed this way by
41+
`systemd-homed.service` by the user name, suffixed with `.homedir` (example:
42+
`lennart.homedir` for a user `lennart`) but this is not enforced. When the user
43+
is logged in the directory is generally mounted to `/home/$USER` (in our
44+
example: `/home/lennart`), thus dropping the suffix while the home directory is
45+
active. `systemd-homed` will automatically discover home directories named this
46+
way in `/home/*.homedir` and synthesize NSS user records for them as they show
47+
up.
48+
49+
## Storage Mechanism: `fscrypt` Directories
50+
51+
This storage mechanism is mostly identical to the plain directory storage
52+
mechanism, except that the home directory is encrypted using `fscrypt`. (Use
53+
`--storage=fscrypt` on the `homectl` command line.) Key management is
54+
implemented via extended attributes on the directory itself: for each password
55+
an extended attribute `trusted.fscrypt_slot0`, `trusted.fscrypt_slot1`,
56+
`trusted.fscrypt_slot2`, … is maintained. It's value contains a colon-separated
57+
pair of Base64 encoded data fields. The first field contains a salt value, the
58+
second field the encrypted volume key. The latter is encrypted using AES256 in
59+
counter mode, using a key derived from the password via PBKDF2-HMAC-SHA512
60+
together with the salt value. The construction is similar to what LUKS does for
61+
`dm-crypt` encrypted volumes. Note that extended attributes are not encrypted
62+
by `fscrypt` and hence are suitable for carry the key slots. Moreover, by using
63+
extended attributes the slots are directly attached to the directory and an
64+
independent sidecar key database is not required.
65+
66+
## Storage Mechanism: `cifs` Home Directories
67+
68+
In this storage mechanism the home directory is mounted from a CIFS server and
69+
service at login, configured inside the user record. (Use `--storage=cifs` on
70+
the `homectl` command line.) The local password of the user is used to log into
71+
the CIFS service. The directory share needs to contain the user record in
72+
`~/.identity` as well. Note that this means that the user record needs to be
73+
registered locally before it can be mounted for the first time, since CIFS
74+
domain and server information needs to be known *before* the mount. Note that
75+
for all other storage mechanisms it is entirely sufficient if the directories
76+
or storage artifacts are placed at the right locations — all information to
77+
activate them can be derived automatically from their mere availability.
78+
79+
## Storage Mechanism: `luks` Home Directories
80+
81+
This is the most advanced and most secure storage mechanism and consists of a
82+
Linux file system inside a LUKS2 volume inside a loopback file (or on removable
83+
media). (Use `--storage=luks` on the `homectl` command line.) Specifically:
84+
85+
* The image contains a GPT partition table. For now it should only contain a
86+
single partition, and that partition must have the type UUID
87+
`773f91ef-66d4-49b5-bd83-d683bf40ad16`. It's partition label must be the
88+
user name.
89+
90+
* This partition must contain a LUKS2 volume, whose label must be the user
91+
name. The LUKS2 volume must contain a LUKS2 token field of type
92+
`systemd-homed`. The JSON data of this token must have a `record` field,
93+
containing a string with base64-encoded data. This data is the JSON user
94+
record, in the same serialization as in `~/.identity`, though encrypted. The
95+
JSON data of this token must also have an `iv` field, which contains a
96+
base64-encoded binary initialization vector for the encryption. The
97+
encryption used is the same as the LUKS2 volume itself uses, unlocked by the
98+
same volume key, but based on its own IV.
99+
100+
* Inside of this LUKS2 volume must be a Linux file system, one of `ext4`,
101+
`btrfs` and `xfs`. The file system label must be the user name.
102+
103+
* This file system should contain a single directory named after the user. This
104+
directory will become the home directory of the user when activated. It
105+
contains a second copy of the user record in the `~/.identity` file, like in
106+
the other storage mechanisms.
107+
108+
The image file should either reside in a directory `/home/` on the system,
109+
named after the user, suffixed with `.home`. When activated the container home
110+
directory is mounted to the same path, though with the `.home` suffix dropped —
111+
unless a different mount point is defined in the user record. (e.g.: the
112+
loopback file `/home/waldo.home` is mounted to `/home/waldo` while activated.)
113+
When the image is stored on removable media (such as a USB stick) the image
114+
file can be directly `dd`'ed onto it, the format is unchanged. The GPT envelope
115+
should ensure the image is properly recognizable as a home directory both when
116+
used in a loopback file and on a removable USB stick. (Note that when mounting
117+
a home directory from an USB stick it too defaults to a directory in `/home/`,
118+
named after the username, with no further suffix.)
119+
120+
Rationale for the GPT partition table envelope: this way the image is nicely
121+
discoverable and recognizable already by partition managers as a home
122+
directory. Moreover, when copied onto a USB stick the GPT envelope makes sure
123+
the stick is properly recognizable as a portable home directory
124+
medium. (Moreover it allows to embed additional partitions later on, for
125+
example for allowing a multi-purpose USB stick that contains both a home
126+
directory and a generic storage volume.)
127+
128+
Rationale for including the encrypted user record in the the LUKS2 header:
129+
Linux kernel file system implementations are generally not robust towards
130+
maliciously formatted file systems; there's a good chance that file system
131+
images can be used as attack vectors, exploiting the kernel. Thus it is
132+
necessary to validate the home directory image *before* mounting it and
133+
establishing a minimal level of trust. Since the user record data is
134+
cryptographically signed and user records not signed with a recognized private
135+
key are not accepted a minimal level of trust between the system and the home
136+
directory image is established.
137+
138+
Rationale for storing the home directory one level below to root directory of
139+
the contained file system: this way special directories such as `lost+found/`
140+
do not show up in the user's home directory.
141+
142+
## Algorithm
143+
144+
Regardless of the storage mechanism used, an activated home directory
145+
necessarily involves a mount point to be established. In case of the
146+
directory-based storage mechanisms (`directory`, `subvolume` and `fscrypt`)
147+
this is a bind mount, in case of `cifs` this is a CIFS network mount, and in
148+
case of the LUKS2 backend a regular block device mount of the file system
149+
contained in the LUKS2 image. By requiring a mount for all cases (even for
150+
those that already are a directory) a clear logic is defined to distuingish
151+
active and inactive home directories, so that the directories become
152+
inaccessible under their regular path the instant they are
153+
deactivated. Moreover, the `nosuid`, `nodev` and `noexec` flags configured in
154+
the user record are applied when the bind mount is established.
155+
156+
During activation, the user records retained on the host, the user record
157+
stored in the LUKS2 header (in case of the LUKS2 storage mechanism) and the
158+
user record stored inside the home directory in `~/.identity` are
159+
compared. Activation is only permitted if they match the same user and are
160+
signed by a recognized key. When the three instances differ in `lastChangeUSec`
161+
field, the newest record wins, and is propagated to the other two locations.
162+
163+
During activation the file system checker (`fsck`) appropriate for the
164+
selected file system is automatically invoked, ensuring the file system is in a
165+
healthy state before it is mounted.
166+
167+
If the UID assigned to a user does not match the owner of the home directory in
168+
the file system, the home directory is automatically and recursively `chown()`ed
169+
to the correct UID.
170+
171+
Depending on the `discard` setting of the user record either the backing
172+
loopback file is `fallocate()`ed during activation, or the mounted file system
173+
is `FITRIM`ed after mounting, to ensure the setting is correctly enforced.

0 commit comments

Comments
 (0)
X Tutup