Other Seeking Advice on GELI Encryption Settings

Hi everyone,

I'm new to FreeBSD and currently practicing GELI encryption with simple ZFS Pool creation and rebuild processes. I’m seeking advice for a pool I will create later.

I’ve come across different setup variants during my research. I understand there's no one "correct" method as each approach serves its own purpose, but I’d like to understand the reasons behind these methods to decide what’s best for my situation.

From forum posts, it seems common to: Initialize the disk with a GPT table -> Create a ZFS partition -> Encrypt the partition.

For ZFS Partition Creation, I’ve seen various alignment options:

Code:
gpart create -s gpt da2

gpart add -t freebsd-zfs da2
gpart add -t freebsd-zfs -a 4k -b 1M da2
gpart add -t freebsd-zfs -a 4k da2
gpart add -t freebsd-zfs -a 1m da2

I understand that 4K alignment helps with disk read/write performance, but I'm unsure about the importance of the boundary settings.

For GELI Encryption, I've come across different arguments such as sector size, key files, data key length, boot process passphrase prompts, and checksums:

Code:
geli init -l 256 -s 4096 da2p1
geli init -l 256 -s 4096 -e aes -a hmac/sha256

dd if=/dev/random of=/root/da2.key bs=64 count=1
geli init -l 256 -b -K /root/da2.key da2p1

I’d like to understand why the decrypted sector size is set to 4096 bytes when the disk is 512e (emulates 8 logical sectors). The key file can be used for automated processes, but some think it is unnecessary. I also found passphrase file arguments in the man page, but I don't know their purpose.

Besides, the FreeBSD handbook introduce the full disk encryption, which means the partition table is also encrypted:

Code:
geli init -l 256 -s 4096 -b da2
geli attach da2
gpart create -s gpt da2.eli
gpart add -t freebsd-zfs -a 4K -b 1M da2.eli
zpool create zpool2 /dev/da2.elip1

It's curious that only a few posts mention full disk encryption. Is there a risk that the disk could be seen as RAW, and a partition table might be written on top, potentially ruining all data?

Any insights, advice, or experiences you can share would be greatly appreciated. Thank you in advance for your help!
 
The key file can be used for automated processes, but some think it is unnecessary. I also found passphrase file arguments in the man page, but I don't know their purpose.
You can use a key file, a passphrase or both. It's up to you what's "good enough" protection. The downside of only using a key file is that it could be stolen, then they could simply unlock your encryption. A passphrase might be better, because it's something only you know. Best is of course to use both, i.e. multi-factor, something you know (passphrase) combined with something you have (key file). You cannot unlock the encryption if you only have one of the two.

It's curious that only a few posts mention full disk encryption.
One of the problems is that you cannot boot such a disk, the BIOS/UEFI won't be able to read it, it needs to be unlocked first.
Is there a risk that the disk could be seen as RAW, and a partition table might be written on top, potentially ruining all data?
That risk is also there if you use the "full" disk with ZFS, the disk won't have a partition table. If you ever put that disk in some other system you might be inclined to believe it's "empty" because it has no partition table. So it's "safer" to use a partition table, that would at least give you (or somebody else) the notion there's something on that disk and it's not "empty". The partition table and partition labels can also help identify specific, individual, disks that are part of a 'collection'.
 
It's nice that we can have the AND of keyfile and passphrase, but I also want the OR.

Usage scenario:
  • When the laptop is in its home location, insert a USB stick with the key and it reboots on its own without you being there
  • When you take the laptop somewhere leave the USB stick home and it only reboots with the passphrase
 
It's nice that we can have the AND of keyfile and passphrase, but I also want the OR.

Usage scenario:
  • When the laptop is in its home location, insert a USB stick with the key and it reboot on its own without you being there
  • When you take the laptop somewhere leave the USB stick home and it only reboot with the passphrase
Well, that would be awesome!
 
Hmmm, geli already allows two keys. I wonder whether the mode is allowed where one is a passphraseless file and one is based on a passphrase.
 
Today, I tried the keyfile option, but I couldn’t find a method to create a GELI encryption partition that can be decrypted by either keyfile only or by passphrase. The only method I found requires both the keyfile and passphrase.

Code:
root@freebsd_test:~ # gpart destroy -F da5
da5 destroyed
root@freebsd_test:~ # gpart create -s gpt da5
da5 created
root@freebsd_test:~ # gpart add -t freebsd-zfs -a 1m da5
da5p1 added
root@freebsd_test:~ # geli init -l 256 -s 4096 -K /root/keyfile da5p1
Enter new passphrase:
Reenter new passphrase:

Metadata backup for provider da5p1 can be found in /var/backups/da5p1.eli
and can be restored with the following command:

        # geli restore /var/backups/da5p1.eli da5p1

root@freebsd_test:~ # geli attach da5p1
Enter passphrase:
geli: Wrong key for da5p1.
geli: There was an error with at least one provider.
root@freebsd_test:~ # geli attach -k /root/keyfile da5p1
Enter passphrase:
root@freebsd_test:~ #

Additionally, I would like to understand more about alignment when creating partitions using gpart. Which option would you use when creating a ZFS partition?

I’ve noticed that there are sector size differences for the same size SSD (e.g., 250GB) from different brands. What should I do in this case if I want to set up RAID between these different brand SSDs? I don’t mind reducing the partition size by 1-2GB to accommodate these differences.

Do the following commands suit my use case? Or can ZFS handle that automatically, even during the process of replacing a broken HDD/SSD?
Code:
gpart add -t freebsd-zfs -s -4194304 da0
 
Hi everyone,

I'm new to FreeBSD and currently practicing GELI encryption with simple ZFS Pool creation and rebuild processes. I’m seeking advice for a pool I will create later.

I’ve come across different setup variants during my research. I understand there's no one "correct" method as each approach serves its own purpose, but I’d like to understand the reasons behind these methods to decide what’s best for my situation.

From forum posts, it seems common to: Initialize the disk with a GPT table -> Create a ZFS partition -> Encrypt the partition.

For ZFS Partition Creation, I’ve seen various alignment options:

Code:
gpart create -s gpt da2

gpart add -t freebsd-zfs da2
gpart add -t freebsd-zfs -a 4k -b 1M da2
gpart add -t freebsd-zfs -a 4k da2
gpart add -t freebsd-zfs -a 1m da2

I understand that 4K alignment helps with disk read/write performance, but I'm unsure about the importance of the boundary settings.

The "-b 1M" argument is usually unnecessary. But it's occasionally important for some SSDs which require that alignment, and it doesn't hurt much, which is why it's recommended. Even if you don't have an affected SSD right now, you might want to copy your pool to one later.

For GELI Encryption, I've come across different arguments such as sector size, key files, data key length, boot process passphrase prompts, and checksums:

Code:
geli init -l 256 -s 4096 da2p1
geli init -l 256 -s 4096 -e aes -a hmac/sha256

dd if=/dev/random of=/root/da2.key bs=64 count=1
geli init -l 256 -b -K /root/da2.key da2p1

I’d like to understand why the decrypted sector size is set to 4096 bytes when the disk is 512e (emulates 8 logical sectors). The key file can be used for automated processes, but some think it is unnecessary. I also found passphrase file arguments in the man page, but I don't know their purpose.

512e means that the underlying disk really has 4k sectors. Operations that aren't 4k aligned will be slow. So it's best to ensure that both ZFS and geli will only operate 4k at a time. That

Besides, the FreeBSD handbook introduce the full disk encryption, which means the partition table is also encrypted:

Code:
geli init -l 256 -s 4096 -b da2
geli attach da2
gpart create -s gpt da2.eli
gpart add -t freebsd-zfs -a 4K -b 1M da2.eli
zpool create zpool2 /dev/da2.elip1

It's curious that only a few posts mention full disk encryption. Is there a risk that the disk could be seen as RAW, and a partition table might be written on top, potentially ruining all data?

Any insights, advice, or experiences you can share would be greatly appreciated. Thank you in advance for your help!

I have two other pieces of advice. Read geli(8) for the details of both.
* If you have more than one encrypted disk, consider lowering kern.geom.eli.threads
* If you're using ZFS on top of geli, set vfs.zfs.vdev.aggregation_limit .
 
The "-b 1M" argument is usually unnecessary. But it's occasionally important for some SSDs which require that alignment, and it doesn't hurt much, which is why it's recommended. Even if you don't have an affected SSD right now, you might want to copy your pool to one later.



512e means that the underlying disk really has 4k sectors. Operations that aren't 4k aligned will be slow. So it's best to ensure that both ZFS and geli will only operate 4k at a time. That



I have two other pieces of advice. Read geli(8) for the details of both.
* If you have more than one encrypted disk, consider lowering kern.geom.eli.threads
* If you're using ZFS on top of geli, set vfs.zfs.vdev.aggregation_limit .
Thank you for your advice, asomers.

After reading the man page, it seems that kern.geom.eli.threads controls how many threads are used for GELI encryption. In this case, shouldn’t it be set higher to improve performance? Or should it be set lower since it is for each GELI disk? (I will have around 14 disks with GELI encryption: 3x Mirror Boot Pool, 6x RAID-Z2 Data Pool, 3x Mirror Data Pool, and 2x Single Data Pool.)

For vfs.zfs.vdev.aggregation_limit, which controls the size of aggregated I/O requests, I would like to know what value I should set for this parameter. I see various posts from different operating systems using different values. Some use 131072 (min), while others use 1048576 (max).

It's nice that we can have the AND of keyfile and passphrase, but I also want the OR.

Usage scenario:
  • When the laptop is in its home location, insert a USB stick with the key and it reboots on its own without you being there
  • When you take the laptop somewhere leave the USB stick home and it only reboots with the passphrase
To cracauer, I am interested in that scenario. Unfortunately, I cannot find a related command to create a GELI encrypted partition that matches the scenario. Could you please show the setup or commands that can be used for this case?
 
Usage scenario:
  • When the laptop is in its home location, insert a USB stick with the key and it reboots on its own without you being there
  • When you take the laptop somewhere leave the USB stick home and it only reboots with the passphrase
To cracauer, I am interested in that scenario. Unfortunately, I cannot find a related command to create a GELI encrypted partition that matches the scenario. Could you please show the setup or commands that can be used for this case?
Such a scenario is not possible with geli(8). A passphrase AND keyfile(s) initialized provider can be attached (decrypted) only with all key components, not with one or the other.

These are the possible passphrase/keyfile cases:
  • passphrase only
  • passphrase and keyfile(s)
  • keyfile(s) only

Today, I tried the keyfile option, but I couldn’t find a method to create a GELI encryption partition that can be decrypted by either keyfile only or by passphrase. The only method I found requires both the keyfile and passphrase.
Those cases are well documented in the manual, You must have missed it: geli(8)
Code:
     init       Initialize providers which need to be encrypted. ...
                ...

               -P                Do not use a passphrase as a component of
                                 the User Key.  Cannot be combined with the
                                 -J option.

     attach     Attach the given providers.
                ...
                -p             Do not use a passphrase as a component of the
                               User Keys.  Cannot be combined with the -j
                               option.

Example for passphrase only provider (or providers separated by space) initialization and attach:
Code:
 # geli init  <provider>

 # geli attach  <provider>

Example for passphrase and keyfile(s) provider initialization and attach:
Code:
 # geli init  -K  /path/to/keyfile1  -K /path/to/keyfile2 -K /path/to/keyfile3 <provider>

 # geli attach  -k  /path/to/keyfile1  -k /path/to/keyfile2 -k /path/to/keyfile3  <provider>

Example for keyfile(s) only provider initialization and attach:
Code:
 # geli init  -P  -K  /path/to/keyfile1  -K /path/to/keyfile2 -K /path/to/keyfile3  <provider>

 # geli attach  -p  -k  /path/to/keyfile1  -k /path/to/keyfile2 -k /path/to/keyfile3  <provider>

See EXAMPLES section of manual for more elaborate use cases.
 
Such a scenario is not possible with geli(8). A passphrase AND keyfile(s) initialized provider can be attached (decrypted) only with all key components, not with one or the other.

These are the possible passphrase/keyfile cases:
  • passphrase only
  • passphrase and keyfile(s)
  • keyfile(s) only
Noted. Thank you for your explanation.
 
To cracauer, I am interested in that scenario. Unfortunately, I cannot find a related command to create a GELI encrypted partition that matches the scenario. Could you please show the setup or commands that can be used for this case?

I was thinking aloud about a future project. AFAIK no OS offers this yet.
 
Thank you for your advice, asomers.

After reading the man page, it seems that kern.geom.eli.threads controls how many threads are used for GELI encryption. In this case, shouldn’t it be set higher to improve performance? Or should it be set lower since it is for each GELI disk? (I will have around 14 disks with GELI encryption: 3x Mirror Boot Pool, 6x RAID-Z2 Data Pool, 3x Mirror Data Pool, and 2x Single Data Pool.)

Remember: kern.geom.eli.threads is per-disk. If you have 14 disks, then the default is too high. I suggest adjusting it so that you have 1-2 threads per-core.
For vfs.zfs.vdev.aggregation_limit, which controls the size of aggregated I/O requests, I would like to know what value I should set for this parameter. I see various posts from different operating systems using different values. Some use 131072 (min), while others use 1048576 (max).


To cracauer, I am interested in that scenario. Unfortunately, I cannot find a related command to create a GELI encrypted partition that matches the scenario. Could you please show the setup or commands that can be used for this case?
I suggesting checking the kern.geom.eli.use_uma_bytes and vm.kmem_zmax sysctls. Set vfs.zfs.vdev.aggregation_limit to the maximum value of those two. Note that the kern.geom.eli.usa_uma_bytes sysctl doesn't exist until FreeBSD 14.2. But for me, it has the value of 135168 .
 
It's nice that we can have the AND of keyfile and passphrase, but I also want the OR.

Usage scenario:
  • When the laptop is in its home location, insert a USB stick with the key and it reboots on its own without you being there
  • When you take the laptop somewhere leave the USB stick home and it only reboots with the passphrase
Hmm, so perhaps another option is that when you're at home, GELI is setup with the file in one slot and when you take your laptop outside of your home, part of that process is deleting the key in that slot. So, every time you remove the laptop from the house, you rotate your key.

Would that work or just cause more headache? I think I would like to make reboots hands off where possible so the system can come up on its own.
 
Hmmm, geli already allows two keys. I wonder whether the mode is allowed where one is a passphraseless file and one is based on a passphrase.
Such a scenario is not possible with geli(8).
Luks on Linux allows it, you can use both keys and passphrase, the one that is provided first will unlock the encryption.

@ cracauer@, actually it's possible to use two different user keys (passphrases / key file(s)) for the same provider to decrypt the provider with one or the other user key. I didn't realize until recent:

Thread freebsd-loader-conf-rc-conf-configuration-unlock-data-geli-providers-mount-zfs-pool-after-mounts.96361

The User Key(s) (passphrase, keyfile(s)), are stored as "Master Key Copies" in two slots, which are differentiated by index number (0 and 1) in the geli(8) metadata (see attach and setkey arguments, -n keyno option).

To create a provider with two different passphrase / passphrase, passphrase / keyfile(s), keyfile(s) / keyfile(s) combination, first initialize the provider with the preferred method, which will store the User Key in both Master Key Copy slots, then inject the second User Key in one of the Master Key Copy slots, using setkey -n <0|1> argument-option, which will overwrite the first User Key copy.
 
T-Daemon that is great because I don't want give up using FreeBSD on my new PC, so I thought to start the PC (which is headless) through a key but still be able to access with the passphrase set up at the installation.

However I am still feeling that I can provide the passphrase through a line in rc.conf. 🤔
 
I mentioned that because I was wondering if others did that and if they find it adds security or mostly increases headache? I used that technique before but ultimately stopped doing that because I felt I was a bit too paranoid even though I was doing it for fun. In certain environments, I would remove the LUKS headers so if the drive were recovered outside of my control, the device would not appear to be LUKS and subsequently, when in a secure environment, I would restore the headers and unlock the drive.

Along the same lines of security, are LUKS and GELI generally about the save level of security or is LUKS more secure as it provides a newer algorithm and is 512 bits versus 256 bits?
 
Back
Top