Unlocking an Encrypted Secondary Drive Using a Keyfile

In this blog post, I will show you how to format and encrypt a new NVMe drive with a keyfile. This will allow you to protect your data and access it easily after the root file system is decrypted.

What You’ll Need

  • A new NVMe drive (I’ll use nvme1n1 as an example)
  • A Linux system with wipefs, cryptsetup, mkfs.btrfs, and dracut installed
  • A backup of any important data on the drive

Step 1: Identify the Drive

First, run the lsblk command to list all the block devices on your system. You should see something like this below.

NAME        MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda           8:0    0 223.6G  0 disk  
├─sda1        8:1    0   512M  0 part  /boot/efi
├─sda2        8:2    0     1G  0 part  /boot
└─sda3        8:3    0 222.1G  0 part  
  └─root    253:0    0 222.1G  0 crypt /
nvme0n1     259:0    0 238.5G  0 disk  
└─nvme0n1p1 259:1    0 238.5G  0 part  
nvme1n1     259:2    0 238.5G  0 disk  

The drive I want to format is nvme1n1, which has no partitions or file systems on it.

Step 2: Format the Drive

Next, I’ll use the wipefs command to erase all the existing signatures on the drive. This will make sure that the drive is completely blank and ready for encryption. Be careful with this command, as it will destroy all the data on the drive. Run the following command:

sudo wipefs --all /dev/nvme1n1

Step 3: Create a Keyfile

Before I encrypt the drive, I’ll create a keyfile named crypto_keyfile2.bin in the /root directory. This keyfile will be used to unlock the drive without entering a passphrase. To create the keyfile, I’ll use the dd command to generate a random 4 KB file from /dev/urandom. Then, I’ll use the chmod command to set the permissions of the keyfile to read-only for the root user. Run the following commands:

# create the keyfile
sudo dd if=/dev/urandom of=/root/crypto_keyfile2.bin bs=1024 count=4
# restrict permission to readonly
sudo chmod 0400 /root/crypto_keyfile2.bin

Step 4: Encrypt the Drive

Now, I’ll encrypt the drive using LUKS (Linux Unified Key Setup), which is a standard for disk encryption. I’ll use the cryptsetup command to create a LUKS container on the drive and add the keyfile as a key. Run the following command:

sudo cryptsetup luksFormat /dev/nvme1n1 /root/crypto_keyfile2.bin Type YES in capital letters and press Enter to confirm.

Then, I’ll use the cryptsetup command to open the encrypted drive and map it to a device named encryptednvme. Run the following command:

sudo cryptsetup open --key-file /root/crypto_keyfile2.bin /dev/nvme1n1 encryptednvme

Step 5: Create a File System

Next, I’ll create a Btrfs file system on the encrypted drive. Btrfs is a modern file system that supports features like snapshots, compression, and subvolumes. I’ll use the mkfs.btrfs command to create the file system. Run the following command:

sudo mkfs.btrfs /dev/mapper/encryptednvme

You should see output like this. Please copy the device UUID as that’s what we will use to identify the device for decryption later.

btrfs-progs v5.10.1 
See http://btrfs.wiki.kernel.org for more information.

Label:              (null)
UUID:               8a7c4d9f-4f6a-4c0e-9c8a-7c9f4a9c9f4a
Node size:          16384
Sector size:        4096
Filesystem size:    238.47GiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP               1.01GiB
  System:           DUP               8.00MiB
SSD detected:       yes
Incompat features:  extref, skinny-metadata
Checksum:           crc32c
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1   238.47GiB  /dev/mapper/encryptednvme

Step 6: Mount the Drive

Now, I’ll need to mount the drive to access it. First, I’ll create a mount point in the /mnt directory. I’ll name it nvme. Run the following command:

sudo mkdir /mnt/nvme

Then, I’ll mount the drive to the mount point. Run the following command:

sudo mount /dev/mapper/encryptednvme /mnt/nvme

Step 7 (Optional): Create Subvolumes

Finally, I’ll create three Btrfs subvolumes on the drive: datavms, and storage. Subvolumes are like partitions, but they are more flexible and efficient. They allow me to organize my data and take snapshots of different parts of the file system. I’ll use the btrfs command to create the subvolumes. Run the following commands:

sudo btrfs subvolume create /mnt/nvme/data
sudo btrfs subvolume create /mnt/nvme/vms
sudo btrfs subvolume create /mnt/nvme/storage

Step 8: Setting Up Automatic Decryption

The final step is to make sure that the encrypted drive is decrypted automatically after the root file system is decrypted. This way, when you boot your device you only need to enter the password to decrypt your main filesystem. Once the main drive is decrypted crypttab will use the keyfile from the root folder of the decrypted filesystem to decrypt the second drive.

To do this, you’ll need to edit the /etc/crypttab file, which contains the information about the encrypted devices. Add the following line to the end of the file:

# Remember to use the UUID from step 5
encryptednvme UUID=<UUID> /root/crypto_keyfile2.bin luks,discard

This line tells the system to use the keyfile /root/crypto_keyfile2.bin to unlock the device with the UUID <UUID>, which is the encrypted drive. The luks option specifies that the device is a LUKS container, and the discard option enables TRIM support for SSDs.

After editing the /etc/crypttab file, you’ll need to generate a new initramfs image, which is a temporary file system that is loaded during the boot process. The initramfs image contains the necessary modules and scripts to mount the root file system and decrypt the encrypted devices. To generate a new initramfs image, run the following command:

sudo dracut -f

And that’s it! You’ve successfully formatted and encrypted your new NVMe drive with a keyfile, and set it up to decrypt automatically after the root file system is decrypted. You can now reboot your system and enjoy your secure and fast drive. 😊

Posts in this series