I've seen some posts lately asking about GELI decryption keys on a USB stick for decrypting a root partition, so I wanted to play around with it for fun.
I documented my steps, so I thought I would share them here in case anyone is curious, but you can probably find other howtos like this on the internet.
I dug out a really old laptop for this experiment, so I'm using UFS with GPT on a BIOS system.
My disks:
da0 is the Freebsd 14.2 installer USB stick
da1 is going to be my permanent boot stick
ada0 is my internal SSD
I booted the installer and went through the usual: keymap, hostname, distribution components.
At "Partitioning," I chose the "Shell" option.
You should probably do something to wipe your internal disk first, but I'm not going over that here.
I at least destroyed my current table on my permanent boot stick:
	
	
	
		
Create a new GPT on it:
	
	
	
		
Create a freebsd-boot partition for the stage 1 and 2 boot code:
	
	
	
		
Install the protective MBR code and the stage 1 and 2 code:
	
	
	
		
Create /boot:
	
	
	
		
Setup the table and partitions on the internal SSD:
	
	
	
		
In the above, I calculated the size (-s) to use all of my available capacity for the root partition, except for the last 4g, which then went to the swap partition.
If you try this yourself, you'll need to adjust that size.
Mount the boot stick:
	
	
	
		
Encrypt root:
	
	
	
		
I wanted a passphrase also. If you don't, add '-P' above.
Attach:
	
	
	
		
# Unmount the bootstick:
	
	
	
		
Create the root FS:
	
	
	
		
(I use -t for SSD TRIM.)
Mount it:
	
	
	
		
Now this gets a little weird.
Stage 2 expects the stage 3 loader to be in the /boot directory on the UFS on your USB stick, so you need to have a /boot on your USB stick, but when / is mounted from your internal SSD, your USB stick gets mounted at /boot on that root filesystem, which means that your stage 3 boot files would be under /boot/boot/, which is not good.
I just get around this with some symlinking:
	
	
	
		
Create the fstab file that the installer will later put on the real root (internal disk) FS:
	
	
	
		
Mine has:
	
	
	
		
I have no need to setup a permanent key for swap.
GELI has a onetime feature that I can use for swap on every boot.
This line in my fstab will be enough to trigger that.
Create the loader.conf file that the installer will later add to and put on the real root (internal disk) FS:
	
	
	
		
Here's mine:
	
	
	
		
This requires some explanation.
The top line is mandatory.
The geli_eli_passphrase line is not mandatory, but I like it if I'm using a passphrase for my encrypted root partition.
Basically, before the stage 3 loader menu, I'll have a little prompt to enter my passphrase.
It only gives you one chance, but if you get it wrong, boot will continue, and it will just count as your first wrong attempt when GELI does it's "normal" passphrase prompting.
I find that "normal" prompting hard to see sometimes in all of the other boot messages, so I really like the geli_eli_passphrase option.
Use the two kern.geom.label lines also.
The geli_ada0p1 lines tell geli where the key is.
The geli_root lines are for a "just in case" scenario.
With the way GELI scans, it will find ada0p1 before it finds that same partition by its GPT label, root.
On my laptop, the position of my disk on the bus/channel/whatever is not going to change, but on a more complicated system it may.
So if I ever boot and the partition became, say, ada1p1, my loader.conf wouldn't have a keyfile specified for that.
No problem. I'll just hit ENTER on all three passphrase attempts, then when GELI gets to the GPT labels, it will prompt me for the passphrase for gpt/root, which IS in my loader.conf, so it will be able to decrypt that.
Root will fail to mount, because my vfs.root line is for "ufs:ada0p1.eli," but that's not a big deal either.
When I get the mountfrom> prompt, I'll just enter "ufs:gpt/root.eli" manually.
I left that alternate mountfrom line in loader.conf but commented-out as reminder.
Anyway, once your to-be loader.conf is created, you can hit ^d to get back to the installer.
It should immediately start extracting the usual archives.
Finish the usual steps after that: password, network, time/date, startup services, hardening, firmware, other users.
On the Final Configuration screen, choose "Exit."
On the Manual Configuration screen, choose "No."
On the "Complete" screen, choose "live system."
Login as "root" with no password.
Your root.eli should still be attached.
Copy the backup to your permanent root:
	
	
	
		
And cleanup:
	
	
	
		
Remove installer stick.
BIOS should find the pmbr code on the boot stick, which should lead to the stage 1 and 2 loader code, which should then lead to the stage 3 loader (with the optional GELI passphrase prompt first), then loader should be able to decrypt root and finish booting.
Just make sure you wait for boot to finish, then login and unmount /bootstick, before you physically remove it.
You could probably add a little service to unmount /bootstick for you.
Make sure also to mount /bootstick whenever you need to do something that updates /boot.
Do a 'geli status' and a 'geli list gpt/swap.eli' to make sure that the GELI "onetime" attachment occurred for swap.
I haven't had a chance yet to play with this old laptop much after the installation, so I can't guarantee there aren't any other caveats.
I also did not have a chance to try a similar setup on a UEFI system.
But I'm hoping someone may get something useful out of this.
				
			I documented my steps, so I thought I would share them here in case anyone is curious, but you can probably find other howtos like this on the internet.
I dug out a really old laptop for this experiment, so I'm using UFS with GPT on a BIOS system.
My disks:
da0 is the Freebsd 14.2 installer USB stick
da1 is going to be my permanent boot stick
ada0 is my internal SSD
I booted the installer and went through the usual: keymap, hostname, distribution components.
At "Partitioning," I chose the "Shell" option.
You should probably do something to wipe your internal disk first, but I'm not going over that here.
I at least destroyed my current table on my permanent boot stick:
		Code:
	
	gpart destroy -F da1
		Code:
	
	gpart create -s gpt da1
		Code:
	
	gpart add -t freebsd-boot -s 512k da1
		Code:
	
	gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 da1Create /boot:
		Code:
	
	gpart add -t freebsd-ufs -l boot da1
newfs -U -L bootfs /dev/gpt/bootSetup the table and partitions on the internal SSD:
		Code:
	
	gpart destroy -F ada0
gpart create -s gpt ada0
gpart add -t freebsd-ufs -l root -a 4k -s 460473440 ada0
gpart add -t freebsd-swap -l swap -a 4k ada0If you try this yourself, you'll need to adjust that size.
Mount the boot stick:
		Code:
	
	mount /dev/gpt/boot /mnt
		Code:
	
	mkdir -p /mnt/boot/keys
cd /mnt/boot/keys
dd if=/dev/random of=root.key bs=128k count=1
geli init -b -K root.key -s 4096 gpt/rootAttach:
		Code:
	
	geli load
geli attach -k root.key gpt/root
		Code:
	
	cd /
umount /mntCreate the root FS:
		Code:
	
	newfs -t -U -L rootfs gpt/root.eliMount it:
		Code:
	
	mount /dev/gpt/root.eli /mntStage 2 expects the stage 3 loader to be in the /boot directory on the UFS on your USB stick, so you need to have a /boot on your USB stick, but when / is mounted from your internal SSD, your USB stick gets mounted at /boot on that root filesystem, which means that your stage 3 boot files would be under /boot/boot/, which is not good.
I just get around this with some symlinking:
		Code:
	
	mkdir /mnt/bootstick
mount /dev/gpt/boot /mnt/bootstick
cd /mnt
ln -s bootstick/boot bootCreate the fstab file that the installer will later put on the real root (internal disk) FS:
		Code:
	
	vi /tmp/bsdinstall_etc/fstab
		Code:
	
	/dev/gpt/root.eli /           ufs   rw  1 1
/dev/gpt/swap.eli none        swap  sw  0 0
/dev/gpt/boot     /bootstick  ufs   rw  2 2GELI has a onetime feature that I can use for swap on every boot.
This line in my fstab will be enough to trigger that.
Create the loader.conf file that the installer will later add to and put on the real root (internal disk) FS:
		Code:
	
	vi /tmp/bsdinstall_boot/loader.conf
		Code:
	
	geom_eli_load="yes"
geom_eli_passphrase_prompt="yes"
kern.geom.label.disk_ident.enable="0"
kern.geom.label.gptid.enable="0"
geli_ada0p1_keyfile0_load="yes"
geli_ada0p1_keyfile0_type="ada0p1:geli_keyfile0"
geli_ada0p1_keyfile0_name="/boot/keys/root.key"
# These four only useful
# if the device became renamed
geli_root_keyfile0_load="yes"
geli_root_keyfile0_type="gpt/root:geli_keyfile0"
geli_root_keyfile0_name="/boot/keys/root.key"
# In case device is renamed
#vfs.root.mountfrom="ufs:gpt/root.eli"
vfs.root.mountfrom="ufs:ada0p1.eli"This requires some explanation.
The top line is mandatory.
The geli_eli_passphrase line is not mandatory, but I like it if I'm using a passphrase for my encrypted root partition.
Basically, before the stage 3 loader menu, I'll have a little prompt to enter my passphrase.
It only gives you one chance, but if you get it wrong, boot will continue, and it will just count as your first wrong attempt when GELI does it's "normal" passphrase prompting.
I find that "normal" prompting hard to see sometimes in all of the other boot messages, so I really like the geli_eli_passphrase option.
Use the two kern.geom.label lines also.
The geli_ada0p1 lines tell geli where the key is.
The geli_root lines are for a "just in case" scenario.
With the way GELI scans, it will find ada0p1 before it finds that same partition by its GPT label, root.
On my laptop, the position of my disk on the bus/channel/whatever is not going to change, but on a more complicated system it may.
So if I ever boot and the partition became, say, ada1p1, my loader.conf wouldn't have a keyfile specified for that.
No problem. I'll just hit ENTER on all three passphrase attempts, then when GELI gets to the GPT labels, it will prompt me for the passphrase for gpt/root, which IS in my loader.conf, so it will be able to decrypt that.
Root will fail to mount, because my vfs.root line is for "ufs:ada0p1.eli," but that's not a big deal either.
When I get the mountfrom> prompt, I'll just enter "ufs:gpt/root.eli" manually.
I left that alternate mountfrom line in loader.conf but commented-out as reminder.
Anyway, once your to-be loader.conf is created, you can hit ^d to get back to the installer.
It should immediately start extracting the usual archives.
Finish the usual steps after that: password, network, time/date, startup services, hardening, firmware, other users.
On the Final Configuration screen, choose "Exit."
On the Manual Configuration screen, choose "No."
On the "Complete" screen, choose "live system."
Login as "root" with no password.
Your root.eli should still be attached.
Copy the backup to your permanent root:
		Code:
	
	mount /dev/gpt/root.eli /mnt
cp /var/backups/gpt_root.eli /mnt/var/backups/
umount /mntAnd cleanup:
		Code:
	
	geli detach gpt/root
shutdown -r nowBIOS should find the pmbr code on the boot stick, which should lead to the stage 1 and 2 loader code, which should then lead to the stage 3 loader (with the optional GELI passphrase prompt first), then loader should be able to decrypt root and finish booting.
Just make sure you wait for boot to finish, then login and unmount /bootstick, before you physically remove it.
You could probably add a little service to unmount /bootstick for you.
Make sure also to mount /bootstick whenever you need to do something that updates /boot.
Do a 'geli status' and a 'geli list gpt/swap.eli' to make sure that the GELI "onetime" attachment occurred for swap.
I haven't had a chance yet to play with this old laptop much after the installation, so I can't guarantee there aren't any other caveats.
I also did not have a chance to try a similar setup on a UEFI system.
But I'm hoping someone may get something useful out of this.
 
			     
 
		