Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add encryption option: per-user encrypted homdir #379

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
146 changes: 140 additions & 6 deletions docs/Getting Started/Debian/Debian Bullseye Root on ZFS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ Contributing
Encryption
~~~~~~~~~~

This guide supports three different encryption options: unencrypted, ZFS
native encryption, and LUKS. With any option, all ZFS features are fully
available.
This guide supports four different encryption options: unencrypted, ZFS
native encryption, LUKS and per-user encrypted homedirs. With any option,
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved
all ZFS features are fully available.

Unencrypted does not encrypt anything, of course. With no encryption
happening, this option naturally has the best performance.
Expand All @@ -93,6 +93,11 @@ entered at the console. Performance is good, but LUKS sits underneath ZFS, so
if multiple disks (mirror or raidz topologies) are used, the data has to be
encrypted once per disk.

Per-user encrypted homdirs encrypts only the datasets for each user. The system
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved
boots without the need to enter a passphrase. No user-data is accessible until
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved
the user logs in. The homdirs-datasets are automatically unlocked on login and
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved
locked on last logout. Mixing encrypted and non-encrypted homdirs is supported.
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved

Step 1: Prepare The Install Environment
---------------------------------------

Expand Down Expand Up @@ -303,7 +308,7 @@ Step 2: Disk Formatting

Choose one of the following options:

- Unencrypted::
- Unencrypted (choose this if you want per-user encyprtion later on)::
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved

zpool create \
-o ashift=12 \
Expand Down Expand Up @@ -951,10 +956,139 @@ Step 6: First Boot
Replace ``YOUR_USERNAME`` with your desired username::

username=YOUR_USERNAME

Choose one of the following:

- Unencrypted homedir or whole-disk encryption
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved

::

zfs create rpool/home/$username
adduser $username

- Encrypted homdir per user, automatic decryption on login
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved

::

zfs create rpool/home/$username -o encryption=on -o keyformat=passphrase -o keylocation=prompt -o canmount=noauto -o org.openzfs.systemd:ignore=on
zfs mount rpool/home/$username
adduser $username

**Note**: Use the same strong password for ZFS encryption and user password. Please note: After a breach of your password changing the ZFS password does not restore protection.
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved

Tell PAM to unlock the dataset key on login::

printf "auth [success=1 default=ignore] pam_succeed_if.so service = sudo quiet\n\
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved
auth optional pam_exec.so expose_authtok /usr/local/sbin/unlock-key-zfs-homedir\n"\
>> /etc/pam.d/common-auth

The second line calls a new unlock-script, the first line disables it if we just sudo.
rlaager marked this conversation as resolved.
Show resolved Hide resolved

Create the unlock-script::

touch /usr/local/sbin/unlock-key-zfs-homedir
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved
chmod a+x /usr/local/sbin/unlock-key-zfs-homedir
vi /usr/local/sbin/unlock-key-zfs-homedir

and put into it::
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved

#!/bin/bash

set -e

# called from PAM common_auth to unlock
# we get the login password (must be the same as ZFS password) on stdin

# exit if root
[ "$PAM_USER" == "root" ] && exit 0

# do nothing if no dataset exists
zfs list rpool/home/$PAM_USER || exit 0

# exit if our dataset is not encrypted
[ `zfs list rpool/home/$PAM_USER -o encryption -H` == off ] && exit 0

# exit if already mounted for some reason
findmnt "/home/$PAM_USER" && exit 0

# still here? unlock now
zfs load-key "rpool/home/$PAM_USER" < /dev/stdin

Now create a systemd service to mount our unlocked dataset::

mkdir -p /etc/systemd/system/[email protected]/
printf "[Unit]\n\
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved
Requires=user-zfs-mount@%%i.service\n"\
> local-mount-zfs.conf

Write the service definition::

vi /etc/systemd/system/[email protected]

with this content::

# local service to mount encrypted homdirs

[Unit]
Description=User ZFS mount /home/ for UID %i
After=dbus.service
StopWhenUnneeded=yes
IgnoreOnIsolate=yes

[Service]
ExecStart=/usr/local/sbin/mount-zfs-homedir start %i
ExecStop=/usr/local/sbin/mount-zfs-homedir stop %i
Type=oneshot
RemainAfterExit=yes
Slice=user-%i.slice

Finally, create the helper script::

touch /usr/local/sbin/mount-zfs-homedir
chmod a+x /usr/local/sbin/mount-zfs-homedir
vi /usr/local/sbin/mount-zfs-homedir

And put into it::

#!/bin/bash
christophhagemann marked this conversation as resolved.
Show resolved Hide resolved

set -e

# called from systemd via /etc/systemd/system/[email protected]
# to mount/unmount
# we get: $1 - start/stop, $2 - UID

# get username from UID passed to us by systemd
USERNAME=$(id -nu $2)

# gracefully exit if no such dataset exists
zfs list rpool/home/$USERNAME || exit 0

case $1 in
start)
# exit if already mounted
findmnt "/home/$USERNAME" && exit 0

# Mount homedir of user we are logging in as
zfs mount "rpool/home/$USERNAME"
;;

stop)
# if the dataset of the user logging out is not encrypted, leave it alone
[ `zfs list rpool/home/$PAM_USER -o encryption -H` == off ] && exit 0

zfs umount "rpool/home/$USERNAME"
zfs unload-key "rpool/home/$USERNAME"
;;

esac



zfs create rpool/home/$username
adduser $username


In either case, continue::

cp -a /etc/skel/. /home/$username
chown -R $username:$username /home/$username
usermod -a -G audio,cdrom,dip,floppy,netdev,plugdev,sudo,video $username
Expand Down