Other Auto-decrypt geli at boot with key, or fallback to password

I'm looking to implement a way to optionally auto-decrypt a single drive system at boot. The flow would be like this:
  • Install FreeBSD, one disk, use GELI encryption
  • Login, create a key: /root/quick-boot-with-no-password.key
  • Create a reboot/shutdown script that offers two option: reboot with auto-decrypt, or not
  • If auto-decrypt:
    • copy /root/quick-boot-with-no-password.key to /boot
    • reboot
    • look for key, see that it is present, use it with no password, finish boot
    • after boot, secure delete the key copy in /boot
  • If no auto-decrypt
    • no key copied to /boot
    • reboot
    • look for the key, see that it's not present and ask for a password, finish boot
    • after boot, nothing to do
Side note: This is for a home server. It allows me easy reboots, and offers good enough security (it's a home server).

I'm new to FreeBSD. I read geli(8) and was able to use setkey to add a key just fine. I then tried adding this to /boot/loader.conf

Code:
geli_da0p4_keyfile1_load="YES"
geli_da0p4_keyfile1_type="da0p4:geli_keyfile1"
geli_da0p4_keyfile1_name="/boot/quick-boot-with-no-password.key"

I was hoping that would skip the password, but I still get the password prompt. I'm not sure if it's even using that key. The docs are a little light with regards to what exactly that does (or I just don't know where to look for more info).

Is there a simple way to achieve this in the .conf files? If not, is it possible to use a shell script to implement the logic?
 
Hello.
To implement geli auto unlock at boot you need to move /boot to the separate unencrypted partition.
I did it this way:
1. Created 512M partition for /boot-env
2. Moved /boot to /boot-env
This step is required because 'loader' expects to boot/kernel/conf files to be in '/boot'. That is happening because boot-env partition is mounted as root for 'loader'. You can't mount boot-env part at /boot directly (I believe it is possible to configure it this way, but you need to change loader (boot) config(s) to use another path during boot).
Now it looks like this:

Bash:
$ ll /boot-env
total 4
drwxr-xr-x  15 root  wheel  1536 May 21 18:16 boot/

3. Created symlink /boot -> /boot-env/boot, so system can access /boot at the expected location (OS update is working fine in this scenario).

Code:
lrwxr-xr-x  1 root  wheel  13 May 21 18:12 /boot@ -> boot-env/boot

4. Put correct 'loader.conf'.
Make sure to put correct block dev name in all geli config lines.
Most probably you will need to specify the root FS location, below sample for zfs.

Code:
geli_${disk}_keyfile_load="YES"
geli_${disk}_keyfile_type="${disk}:geli_keyfile"
geli_${disk}_keyfile_name="/boot/path_to_geli.key"
vfs.root.mountfrom="zfs:zroot/<path to root>"

5. Now you can put a key file at the configured path and your partition will be auto unlocked during boot (can be root FS).
I recommend to create a script which will remove the key from /boot after system boots.
It is best to shred and the delete the key from /boot and also reset the geli key after boot.
I also recommend to create geli metadata (use 'geli backup') and geli key backup and store it encrypted in a safe place. This way you will be able to restore access to your encrypted data in any case, even if you completely destroy geli metadata and/or reset/loose keys.
If geli key file is not present during boot you will be asked for password.
Note, also, I believe currently there is a bug in subsystem which unlocks geli during boot: if you will configure 2 keys for key slot 0 and 1, the unlock process will ask for password in any case and the password doesn't work in this case, even after removing second key the problem still intact. In short: for now use only one key slot if you need auto unlock boot.
 
Thanks for the reply and insights. I must be hitting the bug you mentioned. I cannot seem to get it to make use of a key file and not also ask for a passphrase.

This is unfortunate. I'd really like to give FreeBSD a shot, but encryption at rest and trivial reboots on a headless server are a must for me. I've not messed around with SoL. Maybe something like that offers a reasonable workaround. Or maybe I'll just wait and see if 14 solves my problems.
 
The following works for me pretty well using one of the many cloud providers and ansible:

01. Identify which data needs to be protect by data at rest protection (DARP) and what is a suitable amount of space for the task.
02. Create one or multiple files using an appropriate size to hold all data which require DARP.

Code:
truncate -s 1G /darp/data00.img

03. Encrypt file(s) using geli (see handbook for further details) only using a keyfile and no user password. (see man geli)

Code:
$ mdconfig -t vnode -f /darp/data00.img
# To avoid the step above put mdconfig_md0="-t vnode -f /darp/data00.img" in your rc.conf
$ pwgen -s 1024 1 > keyfile.dat
# Initiate GELI encryption
$ cat keyfile.dat | geli init -P -K - -s 4096 /dev/md0
# Attach GELI container, will be represented as /dev/md0.eli afterwards
$ cat keyfile.dat | geli attach -p -k - /dev/md0

04. Create your filesystem using /dev/md0.eli
Code:
newfs /dev/md0.eli

05. Mount encrypted filesystem
Code:
$ mkdir -p /data00
$ mount /dev/md0.eli /data00

06. Unmount, detach encrypted filesystem, and release file /darp/data00.img
Code:
$ unmount /data00
$ geli detach /dev/md0.eli
$ mdconfig -d -u md0

The process of GELI attach and detach can be put in a rc-script to mount and unmount automatically at bootup and shutdown of the (virtual) server while fetching the keyfile from a remote site using http, ftp, ssh or whatever comes to mind here. The whole process of DARP can be automated pretty well using ansible.

I hope I covered everything, but in the end it's pretty straight forward process.
 
Thanks tanis. This seems like a reasonable workaround. I appreciate your response.

I've also setup Serial Over LAN (SOL), which also provides a reasonable workaround if you have local network access to the server. (I'm actually pleasantly surprise with the utility of SOL. I've been using the html5-based interface on my motherboard's BMC for the longest time. SOL is far more convenient and lets you monitor the full boot process.)
 
That’s actually my default go-to solution, if you need some Linux flavour you can replace GELI with LUKS and be fine. It’s easy to maintain and in case of a disaster easy to recover without compromising on the security part. If you got a real drive, just use it instead of the file image. If you need different passwords for each instance, dataset or whatever your DARP unit is, you are fine as well. DARP is part of my basic setup, as it is a mandatory requirement. The impact on performance is also not that huge, multiple Terabytes can be handled easily ( sure it depends on the hardware as well 🤓).

Edit: Just for clarification LUKS is Linux specific, sometimes Linux is requirement and then I just keep the ansible playbook but switch from GELI to LUKS.
 
Back
Top