-
Notifications
You must be signed in to change notification settings - Fork 211
add encryption option: per-user encrypted homdir #379
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
Open
christophhagemann
wants to merge
10
commits into
openzfs:master
Choose a base branch
from
christophhagemann:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
92acd8b
Add encryption option homedir; preliminaries
christophhagemann 3a61abc
creation of homedir
christophhagemann c7b524a
PAM
christophhagemann e88a41d
systemd-part
christophhagemann e13ef00
Cleanup
christophhagemann 34a1f10
Added an option to remove an error message by zfs-mount-generator
christophhagemann 6e28502
Cosmetic changes
christophhagemann 2e9b1e8
Wrong copy&paste corrected
christophhagemann e9b2900
shellcheck and update shellscripts
christophhagemann bb9cc07
Updated scripts in per-user-encrypted home directory section
christophhagemann File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,14 +71,14 @@ 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 home directories. With any option, | ||
all ZFS features are fully available. | ||
|
||
Unencrypted does not encrypt anything, of course. With no encryption | ||
**Unencrypted** does not encrypt anything, of course. With no encryption | ||
happening, this option naturally has the best performance. | ||
|
||
ZFS native encryption encrypts the data and most metadata in the root | ||
**ZFS native encryption** encrypts the data and most metadata in the root | ||
pool. It does not encrypt dataset or snapshot names or properties. The | ||
boot pool is not encrypted at all, but it only contains the bootloader, | ||
kernel, and initrd. (Unless you put a password in ``/etc/fstab``, the | ||
|
@@ -87,12 +87,17 @@ without the passphrase being entered at the console. Performance is | |
good. As the encryption happens in ZFS, even if multiple disks (mirror | ||
or raidz topologies) are used, the data only has to be encrypted once. | ||
|
||
LUKS encrypts almost everything. The only unencrypted data is the bootloader, | ||
**LUKS** encrypts almost everything. The only unencrypted data is the bootloader, | ||
kernel, and initrd. The system cannot boot without the passphrase being | ||
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 home directory** encrypts only the datasets for each user. The system | ||
boots without the need to enter a passphrase. No userdata is accessible until | ||
the user logs in. The home directory dataset is automatically unlocked on login and | ||
locked on last logout. Mixing encrypted and non-encrypted home directories is supported. | ||
|
||
Step 1: Prepare The Install Environment | ||
--------------------------------------- | ||
|
||
|
@@ -303,7 +308,7 @@ Step 2: Disk Formatting | |
|
||
Choose one of the following options: | ||
|
||
- Unencrypted:: | ||
- Unencrypted or Per-User Encrypted Home Directories:: | ||
|
||
zpool create \ | ||
-o ashift=12 \ | ||
|
@@ -951,10 +956,154 @@ Step 6: First Boot | |
Replace ``YOUR_USERNAME`` with your desired username:: | ||
|
||
username=YOUR_USERNAME | ||
|
||
Choose one of the following: | ||
|
||
- Unencrypted, ZFS native encryption, or LUKS: | ||
|
||
:: | ||
|
||
zfs create rpool/home/$username | ||
adduser $username | ||
|
||
- Per-User Encrypted Home Directories: | ||
|
||
:: | ||
|
||
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. | ||
|
||
Tell PAM to unlock the dataset key on login:: | ||
|
||
vi /etc/pam.d/common-auth | ||
|
||
Append after the last line:: | ||
|
||
auth [success=1 default=ignore] pam_succeed_if.so service = sudo quiet | ||
auth optional pam_exec.so expose_authtok /usr/local/sbin/unlock-key-zfs-homedir | ||
|
||
The second line calls a new unlock-script, the first line disables it if we just sudo. | ||
|
||
Create the unlock-script:: | ||
|
||
vi /usr/local/sbin/unlock-key-zfs-homedir | ||
|
||
and put into it:: | ||
christophhagemann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#!/bin/sh | ||
|
||
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 reads the passwd from STDIN | ||
zfs load-key "rpool/home/$PAM_USER" | ||
|
||
Now create a systemd service to mount our unlocked dataset:: | ||
|
||
mkdir -p /etc/systemd/system/[email protected]/ | ||
vi /etc/systemd/system/[email protected]/local-mount-zfs.conf | ||
|
||
In the file, request our new service (Requires) and instruct systemd to wait for completion before continuing (After):: | ||
|
||
[Unit] | ||
Requires=user-zfs-mount@%i.service | ||
After=user-zfs-mount@%i.service | ||
|
||
zfs create rpool/home/$username | ||
adduser $username | ||
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:: | ||
|
||
vi /usr/local/sbin/mount-zfs-homedir | ||
|
||
And put into it:: | ||
|
||
#!/bin/sh | ||
|
||
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 | ||
|
||
# prevent race condition with PAM unlock: If key is not yet available, wait for it | ||
[ "$(zfs get keystatus -H -o value rpool/home/"$USERNAME")" != available ] && sleep 1 | ||
|
||
# Mount home directory 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/$USERNAME" -o encryption -H)" = off ] && exit 0 | ||
|
||
# unmount and unload key (-u) | ||
zfs umount -u "rpool/home/$USERNAME" | ||
|
||
# optional: uncomment the next two lines to take a snapshot upon logout | ||
# zfs destroy "rpool/home/$USERNAME@last-logout" || true | ||
# zfs snapshot "rpool/home/$USERNAME@last-logout" | ||
;; | ||
|
||
esac | ||
|
||
Don't forget to make the new scripts executable:: | ||
|
||
chmod a+x /usr/local/sbin/unlock-key-zfs-homedir | ||
chmod a+x /usr/local/sbin/mount-zfs-homedir | ||
|
||
|
||
|
||
|
||
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 | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.