Adding an Encrypted Physical Volume to an Existing Volume Group

Recently I noticed that the 500 GB SSD on my desktop was getting dangerously low on space. I cleaned out my Downloads folder, deleted some movies I had saved, and emptied the trash to clear up some space. I knew that this was only a temporary solution and that I would need to think about adding another drive. The trouble was that the 500 GB drive was encrypted and used LVM for its partitioning. So how do I add a new drive to this existing, encrypted volume? After spending an embarrassing amount of time trying to get a drive formatted1, adding an encrypted volume to an existing volume group turned out to be pretty simple.

The first step is installing the physical drive in the computer (make sure you’re using a good cable2), but I feel that goes without saying. Once the system is up, make sure the system sees the drive using lsblk and make note of the device name. In my case, the device was /dev/sdb, so that’s what I’ll use as the example in the rest of the article. Start gdisk with gdisk /dev/sdb and remove any existing partitions with the ‘d’ option. At this point, you may be able to move directly to cryptsetup, but I created a single partition using the whole drive, then ran cryptsetup luksFormat /dev/sdb1. I recommend using the same password for the new volume as the one for the existing volume. This will be explained in a later step. Now I have an encrypted Physical Volume (PV). Open the volume with cryptsetup open /dev/sdb1 crypthome. You can call it whatever you want, but since I’m using it to be my new /home, I called it crypthome.

Now I need to add the Physical Volume to the Volume Group that is currently on the system as /. In retrospect, I probably could have created a new VG just for the /home mount, but I didn’t. Adding a PV to a VG is really pretty simple. Use lsblk to get the mapped name for the encrypted volume and vgdisplay to get the name of the VG that you’d like to extend. In my case, I issued the command vgextend data /dev/mapper/crypthome and root. You should see a return message indicating that the VG was extended. If you run vgdisplay again, you should see a new “VG Size” for the Volume Group. You still need to create the Logical Volume that will be mounted as the new /home (or whatever).

Since I wanted to use this drive for a new /home, I just created an LV using 100% of the available space. You could divide this up into a /var and /home, or whatever you want. I just needed a bigger /home, so I create the LV with lvcreate -l 100%FREE -n home data. Case is critical here. There is also a -L parameter for creating a volume of a specific size. For whatever reason, -l is used for the percent of available space. The new volume will be the /home directory, so I named it ‘home’ with the -n switch. The last argument ‘data’ is just to let lvcreate know which VG the volume is being created in. Now the volume should be there in the VG ‘data’ and it can be formatted with the usual mkfs -t ext4 /dev/data/home. If you’re creating a new /home as I did, you’ll want to mount the new volume at this point and copy over the appropriate file and directories with ‘copy -av’. Then, all that’s left to do now, is to make sure the system will see it, decrypt it, and mount it on boot.

Having the volume available at boot is a matter of updating the /etc/crypttab and the /etc/filetab. I feel like it would be easiest to just show an example here.

# lsblk -f
sda
├─sda1          vfat        FAT32              D456-5AF3                                 116M    77% /boot/efi
├─sda2          vfat        FAT32              D456-5773                                 1.5G    63% /recovery
├─sda3          crypto_LUKS 2                  343e7183-6728-4cd7-aa15-c8078175b4a1
│ └─cryptdata   LVM2_member LVM2 001           hDtcjZ-BOc6-AzGO-rkL6-Gwb9-uhx7-TnDFIf
│   └─data-root ext4        1.0                6e340b72-d286-4dfa-a533-0a206b472b3d      373G    12% /
└─sda4          swap        1                  b1f3723a-d852-4552-9ac4-ab8d3355d040
  └─cryptswap   swap        1        cryptswap ceaef10b-ff2e-4c4a-8288-d21685614fdc                  [SWAP]
sdb
└─sdb1          crypto_LUKS 2                  d4c6579e-1f82-4605-b1d5-2763dceb689b
  └─crypthome   LVM2_member LVM2 001           uNdRSv-Kyna-l7BM-ZZ3s-j6ii-wfML-oQzpXP
    └─data-home ext4        1.0                1ffb8abf-ed3e-4c18-8449-ebe322cdefa2    563.5G    33% /home
# cat /etc/fstab
UUID=6e340b72-d286-4dfa-a533-0a206b472b3d  /  ext4  noatime,errors=remount-ro  0  0
UUID=1ffb8abf-ed3e-4c18-8449-ebe322cdefa2  /home  ext4  noatime,errors=remount-ro  0  0
# cat /etc/crypttab
cryptdata UUID=343e7183-6728-4cd7-aa15-c8078175b4a1 my_keys luks,initramfs,keyscript=decrypt_keyctl
crypthome UUID=d4c6579e-1f82-4605-b1d5-2763dceb689b my_keys luks,initramfs,keyscript=decrypt_keyctl

Notice that the UUID for the LUKS volume and the Logical Volume are different. Make sure you use the correct UUID in the correct file. Otherwise, you’ll have to tell grub where devices are at boot, which kinda sucks. Also, note the option ‘keyscript=decrypt_keyctl’ in /etc/crypttab. This a script available on Debian/Ubuntu systems that caches the password and then uses it to unlock all LUKS volumes with the same password. If you don’t do this, you’ll be prompted twice for a password even if they are the same.

With all of these steps completed successfully, run update-initramfs -u, and that should do it. Reboot and you should have a new /home.

  1. The trouble turned out to be a faulty cable. Even though I should have known to try a known good cable, this allowed me to learn more about GUID fdisk (or gdisk), testdisk, badblocks, and smartctl.
  2. See the previous footnote.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.