Skip to main content.

Filesystem-based encryption with PEFS


Live demo in BSD Now Episode 029 | Originally written by Kris for | Last updated: 2014/03/19

NOTE: the author/maintainer of the tutorial(s) is no longer with the show, so the information below may be outdated or incorrect.

In the day and age we live in, it seems security and privacy have been thrust into the forefront of the computing world. More than ever, users and companies are trying to find ways to keep their private data private. Encryption has always been a good choice and there are a number of utilities to use, some commercial and some open-source, some kernel level and some userland. On FreeBSD, most users have been using the kernel-level "GELI" framework, usually for low-level disk encryption. Typically this would sit "underneath" the user's file-system, such as UFS or ZFS. However, this may be less than optimal in a few situations, such as wanting to encrypt only a single directory or wanting to replicate ZFS snapshots which sit on top of the GELI layer. Enter the PEFS framework. PEFS, which stands for Private Encrypted File System, is a kernel-level stacked cryptographic filesystem for FreeBSD.

One of the main differences between GELI and PEFS is that, while GELI sits below your filesystem encrypting blocks of data before it hits the disk, PEFS will sit on top, encrypting files and directories before they hit the underlying filesystem. This allows PEFS to run on the top of ZFS, which can be a benefit when wanting to replicate encrypted data using ZFS send/receive functionality. In addition, PEFS also comes bundled with a PAM module, allowing for entire home directories to be encrypted and decrypted based upon the user logging into the system, which can be very beneficial to multi-user workstations. In today’s tutorial we will be taking a look at how to install and create PEFS-encrypted directories, as well as enabling PAM logins for PEFS home directory encryption.

Getting PEFS

To start, we will need to grab PEFS from the ports tree or package repo. On PC-BSD 9.2 and later, this is included in the base-world.

# cd /usr/ports/sysutils/pefs-kmod
# make install clean


# pkg install pefs-kmod

Once installed, we next need to load the pefs kernel module:

# kldload pefs

If we want to keep this module loaded across reboots, add it to /boot/loader.conf:

# echo 'pefs_load="YES"' >> /boot/loader.conf

To create our first encrypted directory, we will begin with creating two new dirs:

# mkdir ~/encrypted ~/unencrypted

By default PEFS does not store any meta-data related to your keys on disk, and as such has no way to verify the correctness of the key entered. However, to achieve this functionality, PEFS does have support for keychains. A single key can be used to replicate traditional key storage.

Next we will add a single parent key to our encrypted directory.

# pefs addchain -f -Z ~/encrypted
Enter parent key passphrase:
Reenter parent key passphrase:

The -Z flag is used to specify that this keychain will consist of only a single parent key, no children. The -f flag will skip checking the underlying filesystem to see if it is already encrypted. Next, we will mount the pefs filesystem. Note that this does not require the encryption key, that will come later.

# pefs mount ~/encrypted ~/unencrypted

Note at this point that the ~/unencrypted file-system only contains the single .pefs.db file (for the keychain), and is mounted read-only. To decrypt the directory, we will next add our key:

# pefs addkey -c ~/unencrypted
Enter passphrase:

The -c flag is used to "check" the key supplied against the keychain database, and reject a mis-typed or bad key. Now the ~/unencrypted directory should be mounted r/w and we can begin adding our private data.

# echo "testing" > ~/unencrypted/test.txt
# ls ~/unencrypted/
.pefs.db test.txt
# cat ~/unencrypted/test.txt 
# ls ~/encrypted/
.7ve2p00YVmMBFLlAzJ0k+BC85G67t4KT .pefs.db
# cat ~/encrypted/.7ve2p00YVmMBFLlAzJ0k+BC85G67t4KT 

Now we can just as easily remove our key and re-encrypt the ~/unencrypted directory:

# pefs flushkeys ~/unencrypted
# ls ~/unencrypted
.7ve2p00YVmMBFLlAzJ0k+BC85G67t4KT .pefs.db

Note that for this tutorial we used both ~/encrypted and ~/unencrypted directories. It is possible to have all this done on a single "~/encrypted" directory, simply by replacing ~/unencrypted with ~/encrypted in the commands run. Next, we will take a look at how we can use PEFS to create an encrypted home directory.

To get started, if this is an existing user, we will want to move their files out of their home directory:

# mv /usr/home/test /usr/home/test.old
# mkdir /usr/home/test
# chown test:test /usr/home/test
# pefs addchain -f -Z /usr/home/test
# pefs mount /usr/home/test /usr/home/test

Enter your username password.

# pefs addkey /usr/home/test

Enter your user's password. Next move out the .pefs.db file

# mv /usr/home/test/.pefs.db /tmp/.pefs.db

Copy data back into the encrypted filesystem.

# tar cvf - -C /usr/home/test.old . | tar xvf - -C /usr/home/test 

Unmount pefs.

# umount /usr/home/test

Copy database file back.

# mv /tmp/.pefs.db /usr/home/test/
# chown test:test /usr/home/test/.pefs.db

Re-mount pefs.

# pefs mount /usr/home/test /usr/home/test

If your /home directory is a symlink to /usr/home, you may need to adjust the passwd file. PEFS will not work on symlinks, run "vipw" and adjust your users home dir to the real path.

Lastly we need to add the PAM module to our login process.

Edit /etc/pam.d/system:

--- system  2013-08-26 09:39:18.014375012 -0400
+++ system  2014-02-25 09:36:57.141849155 -0500
@@ -9,6 +9,7 @@
 auth       requisite   no_warn allow_local
 #auth      sufficient     no_warn try_first_pass
 #auth      sufficient      no_warn try_first_pass
+auth       sufficient     try_first_pass delkeys
 auth       required     no_warn try_first_pass nullok

 # account
@@ -18,6 +19,7 @@

 # session
 #session   optional      want_agent
+session        optional         delkeys
 session        required      no_fail

 # password

Now we should be able to open a fresh login with the "test" user, and the home-directory will be automatically decrypted upon login, and re-encrypted at logout.

PEFS also supports more advanced keychain functionality, such as escalating privledge and such (which are outside the scope of this tutorial today). For reference, take a look at the manpage or the wiki.

Latest News

New announcement


We understand that Michael Dexter, Brad Davis, and George Rosamond think there should be more real news....

Two Year Anniversary


We're quickly approaching our two-year anniversary, which will be on episode 105. To celebrate, we've created a unique t-shirt design, available for purchase until the end of August. Shirts will be shipped out around September 1st. Most of the proceeds will support the show, and specifically allow us to buy...

New discussion segment


We're thinking about adding a new segment to the show where we discuss a topic that the listeners suggest. It's meant to be informative like a tutorial, but more of a "free discussion" format. If you have any subjects you want us to explore, or even just a good name...

How did you get into BSD?


We've got a fun idea for the holidays this year: just like we ask during the interviews, we want to hear how all the viewers and listeners first got into BSD. Email us your story, either written or a video version, and we'll read and play some of them for...

Episode 237: AsiaBSDcon 2018


Direct Download:HD VideoMP3 AudioHD Torrent This episode was brought to you by Headlines AsiaBSDCon 2018 has concluded We have just returned from AsiaBSDCon in Tokyo, Japan last weekend Please excuse our jetlag The conference consisted two days of meeting followed by 2 days of paper presentations We arrived a few days early to see some sights and...

Episode 236: How a cd works


Direct Download:HD VideoMP3 AudioHD Torrent This episode was brought to you by Headlines Pledge: OpenBSD’s defensive approach to OS Security The meaning of Pledge is same as in the real world, that is, “a solemn promise or undertaking”. So, in OpenBSD: Calling pledge in a program means to promise...

Episode 235: I C you BSD


Direct Download:HD VideoMP3 AudioHD Torrent This episode was brought to you by Headlines How I coined the term 'open source' In a few days, on February 3, the 20th anniversary of the introduction of the term "open source software" is upon us. As open source software grows in popularity and powers some...

Episode 234: Code and Community


Direct Download:HD VideoMP3 AudioHD Torrent This episode was brought to you by Headlines Google Summer of Code 2018 FreeBSD FreeBSD Google Summer oF Code Ideas You can join #freebsd-soc on the efnet IRC network to chat with FreeBSD developers interested in mentoring student proposals and projects, past FreeBSD/GSoC students, and other students applying to...