Note: This is an update of Will Haley's excellent post to use APFS instead of CoreStorage.
The script can't read the file containing the password on the USB thumb drive. When formatted
as FAT32 as described below, the user/group of the file is unknown/unknown. But I also tried formatting the USB thumb drive in HFS+, unchecking "Ignore permissions on this volume" and changing the file owner to root:wheel
. The file is still not readable to the boot process. Probably something to do with new security restrictions in Catalina. A script running as root reading data from a thumb drive? Makes sense.
I'll add to Will's warning below that this is a complex process on
MacOS because the OS has a lot of assumptions on where things are. I
initially wanted to have the installation as transparent as possible
by mounting my Home on /Users/chet
, but
the OS wouldn't allow it.. I
then tried mounting it on /home
, but had trouble with backup
software, notably Backblaze, which will not backup custom mount
points, and Time Machine, which would do the backup but would not
show it in the restore GUI. So I just ended up mounting it on the
standard mount point: /Volumes
.
So you want to encrypt your $HOME
on your Mac but nothing else?
Let’s stop right here.
The built in option for FileVault full disk encryption is the standard on a Mac, and I recommend going that route for encryption. It is a fairly big pain to do what you’re asking.
Though, it is possible, and that is what this guide will help you to accomplish. Although it is complicated, it is possible to encrypt a user’s home folder independently of the rest of the system. We can use a keyfile to encrypt our home, and automatically mount it at boot time.
A couple caveats.
- Again, I have to stress, FileVault is so much simpler. Or VeraCrypt.
- You must be comfortable using a USB key to decrypt your drive.
- My process works 99% of the time, but about once every few months my
$HOME
fails to mount properly and I must reboot to try again.
Full disk encryption is better than partial disk encryption, and my process certainly has some holes. It is up to you to be as secure (paranoid) as you want.
Create an Administrator
user on your Mac (with
Administrator access of course) and log out of your account and log in
as that user.
While it may be possible, I do not think it’s a good idea to mess with the home folder of a user while that user is logged in. That is why I ask you to create the Administrator user account.
Not only should you use that secondary account to follow these instructions, but you should keep that account around and never encrypt its home.
Why? Well, if your encrypted home folder fails to mount at boot time for some reason, you may be locked out of your Mac. That’s no fun. You can probably fix things via the recovery tools if that happens, but having a secondary admin account will greatly ease your burden if you need to troubleshoot. It’s your choice, but be warned, if something goes wrong and you get locked out of your machine, it will probably be very frustrating and annoying.
I believe that a keyfile is the only way to accomplish the goal of this article.
I cannot find any way to accomplish our goal using a password prompt. I don’t think you can inject/prompt for a password in the standard boot process without using a file that can be read via script.
I am naming my keyfile encryptedhome.key
. The file should
contain nothing but the password.
thePassw0rd
That is a trivial example. Will Haley uses a 1023 character random passphrase but I will use a shorter one storable in 1Password so the disk can be mounted by hand if the USB drive is lost.
cat > encryptedhome.key
*******************************
Find a USB drive. Bonus points if it has a read only
switch on it. I use an SD card which can plug into the SD slot on my iMac leaving a USB jack free.
Format the USB drive as MS-DOS (FAT), with a Master Boot Record, using
Disk Utility. Name the drive KEYDRIVE01
or something
that’s reasonably unique.
Copy your keyfile to the root of KEYDRIVE01
.
You should backup this keyfile somewhere secure. If you lose it, you will forever lose access to your encrypted disk.
I highly recommend using a dedicated disk to house this encrypted home of yours. What I mean is, a separate, distinct disk from your OS disk.
In my case, I’m using a brand new ~500GB SSD drive to act as my encrypted home.
For clarity, I’m going to refer to this disk as the “encrypted home”, even though it’s not encrypted just yet.
With your machine powered off, plug in your new encrypted home disk to your Mac. Boot up and open up your terminal.
Find the id of the disk that will server as your encrypted home.
diskutil list
My encrypted home disk is brand new and so has no partitions.
/dev/disk0 (internal, physical):
/dev/disk0 (external):
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme 512.1 GB disk0
1: EFI EFI 209.7 MB disk0s1
2: Apple_HFS SSD T3 511.8 GB disk0s2
Be extremely certain that you’re looking at the correct disk before proceeding. If you choose the wrong disk, you may lose data.
Create an APFS
Container
on your encrypted home disk. Warning: this will erase the disk. Note that I am running this command against /dev/disk0s2
based on the output of the command above. The createContainer
command runs on a partition, not the whole disk.
$ diskutil ap createContainer /dev/disk0s2
Creating container with disk0s2
Started APFS operation on disk0s2 SSD T3
Creating a new empty APFS Container
Unmounting Volumes
Switching disk0s2 to APFS
Creating APFS Container
Created new APFS Container disk5
Disk from APFS operation: disk5
Finished APFS operation on disk0s2 SSD T3
Your encrypted home disk layout should look something like this if you do diskutil list disk5
, where disk5
is the output of the previous command.
/dev/disk5 (synthesized):
#: TYPE NAME SIZE IDENTIFIER
0: APFS Container Scheme - +511.9 GB disk5
Physical Store disk0s2
Create an encrypted volume inside the APFS Container
that we just created a moment ago. I am calling my volume ChesterHome
. You can name it however you like, but then make sure you use your updated name(s) in the rest of my steps.
cat /Volumes/KEYDRIVE01/encryptedhome.key|diskutil ap addVolume disk5 APFS ChesterHome -stdinpassphrase -passphraseHint "EncryptedHome in 1PW"
Exporting new encrypted APFS Volume "ChesterHome" from APFS Container Reference disk5
Started APFS operation on disk5
Preparing to add APFS Volume to APFS Container disk5
Creating APFS Volume
Created new APFS Volume disk5s1
Mounting APFS Volume
Setting volume permissions
Disk from APFS operation: disk5s1
Finished APFS operation on disk5
Great. Now we have an encrypted drive and a USB key to unlock it, but how do we unlock it at boot when we need to login? OS X has no built in mechanism for this, so we’ll have to script it ourselves.
Technically, we can't unlock the drive as part of the login process. At least, not to my knowledge. So, we must unlock the disk at boot time. We'll unlock it then using our USB key.
Get the UUID of your USB key.
$ diskutil list |grep KEYDRIVE01
1: DOS_FAT_32 KEYDRIVE01 7.7 GB disk4s1
$ diskutil info disk4s1 |grep "Volume UUID"
Volume UUID: 68D1757B-0DFE-3CD9-97B1-4D3B2C75ECF9
Get the UUID of your Encrypted Volume
using the APFS volume disk from the output of the addVolume
command above.
$ diskutil ap list |grep disk5s1
+-> Volume disk5s1 E9E409ED-F847-4973-BD77-757A452965C1
APFS Volume Disk (Role): disk5s1 (No specific role)
By default, your volume would be mounted under /Volumes.
If you're OK with that (and you should be), skip to Create a Script.
Will Haley was able to mount it at /Users/will
(the default $HOME
) but I was not able to get the system
to mount a volume over an active home directory, possibly due to
new security restrictions in Mojave.
To mount the encrypted home disk at /home
and our users
subdirectory /home/chet
, a couple of steps are needed. First,
we need to take /home
out of the automounter (which is rarely used
on MacOS).
sudo -e /etc/auto_master
... comment out the line beginning with /home
I found this did not seem to do anything, but if you want, execute sudo vifs
and add the following line to fstab:
UUID=YOUR_ENCRYPTED_VOLUME_UUID none apfs rw,noauto,nobrowse 0 2
Again, substitute your own UUID. This line tells the system not to automount the volume at boot, and not to show the mounted drive on the desktop and the finder side bar.
Now create a file with the following contents at /opt/mount.sh
.
Replace YOUR_USB_KEY_UUID
and YOUR_ENCRYPTED_VOLUME_UUID
in the script below with the correct UUIDs for your USB key and encrypted volume found when you ran the commands above!
Modify the script as needed for your system.
#!/bin/bash
set -e
set -u
USB_KEY_UUID=68D1757B-0DFE-3CD9-97B1-4D3B2C75ECF9
ENCRYPTED_VOLUME_UUID=E9E409ED-F847-4973-BD77-757A452965C1
#LOG=/dev/stdout
LOG=/tmp/mount.log
echo "mount attempted at $(date)" > $LOG 2>&1
# Must ensure the USB key is mounted so we can access the keyfile.
diskutil mount $USB_KEY_UUID >> $LOG 2>&1
diskutil list >> $LOG 2>&1
KEY_NAME=$(diskutil info $USB_KEY_UUID | grep "Volume Name" | awk '{print $3}')
echo $KEY_NAME >> $LOG 2>&1
KEYFILE="/Volumes/$KEY_NAME/encryptedhome.key"
i="0"
while [ ! -f $KEYFILE ]
do
sleep 1
i=$[$i+1]
if [ $i -ge 30 ]
then
echo "Could not find $KEYFILE" >> $LOG 2>&1
exit 1
fi
done
password=$(cat $KEYFILE)
echo $password |wc >> $LOG 2>&1
# Unlock the encrypted volume using the key. This will also mount it on /Volumes
printf $password|diskutil ap unlockVolume $ENCRYPTED_VOLUME_UUID -stdinpassphrase -nomount >> $LOG 2>&1
## mount_apfs requires a device, not a UUID
ENCRYPTED_VOLUME_ID=$(diskutil info $ENCRYPTED_VOLUME_UUID | grep 'Device Identifier' | awk '{print $3}')
#
echo "Disk name $ENCRYPTED_VOLUME_ID" >> $LOG 2>&1
#
# sleep 15
# let diskarbitrationd handle mounting later???
# mount -v -t apfs "/dev/$ENCRYPTED_VOLUME_ID" /Volumes >> $LOG 2>&1
sleep 20 # try to get of message that it's already unmounted
diskutil info $ENCRYPTED_VOLUME_UUID >> $LOG 2>&1
diskutil unmount $USB_KEY_UUID >> $LOG 2>&1
echo "mount finished at $(date)" >> $LOG 2>&1
Lock that script down a bit and make it executable.
sudo chown root:wheel /opt/mount.sh
sudo chmod 500 /opt/mount.sh
sudo chmod +x /opt/mount.sh
OK, so how do we get that to run at boot?
Create a file at /Library/LaunchDaemons/org.dewachen.startup.mounthome.plist
using these contents.
Again, you can rename that file if you want, but make sure you update the name appropriately elsewhere!
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>RunAtLoad</key>
<true />
<key>Label</key>
<string>org.dewachen.startup.mounthome</string>
<key>ProgramArguments</key>
<array>
<string>/opt/mount.sh</string>
</array>
</dict>
</plist>
Set our mount script to run at boot.
launchctl load -w /Library/LaunchDaemons/org.dewachen.startup.mounthome.plist
Now comes the ultimate test. Keep your USB key plugged in, and reboot. Log in as any user and verify that the volume is mounted on /Volumes/ChesterHome/. You should see it in the Finder.
Create a new folder in /Volumes/ChesterHome
. Reboot.
Do you see your folder in /Volumes/ChesterHome
? Great. Data is persisting as we’d hope.
Try unplugging your USB key and rebooting. You should see that the encrypted home disk does not mount now. Re-connect your USB key and reboot again.
Hopefully the encrypted home disk is mounting properly each time you reboot as long as the USB key is plugged in.
If your encrypted home is failing to mount automatically, take a step back and try to see where you went wrong.
Can you run the mount.sh
script manually with sudo
? Do you see any errors? Do you see a file created at /tmp/mount.log
indicating that a mount was even attempted? Keep at it. I’m sure you’ll figure it out, and my apologies if I left out a step.
By default, external drives are mounted with "permissive" permissions so any user with physical possesion of the drive can see the files on it. But this is your home directory— we don't want that. Find your volume with diskutil list
:
/dev/disk4 (synthesized):
#: TYPE NAME SIZE IDENTIFIER
0: APFS Container Scheme - +511.9 GB disk4
Physical Store disk0s2
1: APFS Volume ChesterHome 383.2 GB disk4s1
Then use enable ownership on that volume:
sudo diskutil enableOwnership disk4s1
This setting is stored in a persistent database on your boot disk.
You may not have paid attention at the beginning, but to reiterate, I
highly recommend that you log out of your account and
log in as another administrator for these next steps. In fact, before
you move your own home directory, try it with a test user. Open the
Users & Groups preference pane and create a new Standard user with the
short user name of newuser
. Log in as that user and make sure the
new account works, then log out and execute the following command.
sudo rsync -a /Users/newuser /Volumes/ChesterHome
Now go back to the Users & Groups preference pane and right-click on
your New User and select Advanced Options. Change the Home directory
to /Volumes/ChesterHome/newuser
. Now reboot and when the system comes back up, you
should be able to log in as newuser
. Look around and make sure
everything is OK. Create a new file on the Desktop then open Terminal, where
you should be able to see it in /Volumes/ChesterHome/newuser/Desktop
.
Now you are ready to move your own home directory. Log out of your
main account and log in as Administrator. In order to avoid any issues
with permissions, I decided to use Carbon Copy Cloner
to do the
copying rather than rsync
, which might not be able to transfer all
the Apple-specific ACL's, extended attributes and so forth.
Once you’re satisfied and your data is backed up securely and
your USB key is backed up securely, then you should
delete your old home directory at
/Users/chet
(or wherever) from the unencrypted disk. Also
delete newuser
and its home directory and copy in /Volumes/ChesterHome/newuser
and /Users/newuser
After all, what is the point of encrypting our $HOME
if
the old unencrypted data is still there in the open?
Be extremely careful that you are deleting the data from the unencrypted disk, and not from your encrypted disk.
Finally, and this is important, with KEYDRIVE01 mounted, open your Spotlight Preference Pane and add the drive to the Privacy pane. This keeps Spotlight from trying to index the USB disk at startup which can interfere with it being automatically unmounted. Besides, you don't want your key appearing in Spotlight!
These steps took a lot of trial and error. FileVault is a much safer and easier way to get encryption, and although I have not used VeraCrypt, it is probably much simpler too.
For any of this to be worthwhile, please don’t leave your USB key plugged in to your Mac when you leave the house ;)
This site was a huge help in understanding Core Storage.
This site was a huge help in understanding Launchd
and boot scripts in OS X.
Seems this is not working for MacOS Monterey (12.0.1) either.
I loved the idea of having a USB thumb drive to control the access to the external drive.