3 April 2014

Encrypted filesystem on top of an LVM

I always forget how to create encrypted partition inside an lvm, so that's a good reason to write it. I'm not an admin so there might be better ways to do the same.

Objective: To have an encrypted device, unmounted by default, ready for one-click mount that asks for the password.

My tools:
  • lvm2
  • system-config-lvm - gui for LVM management
  • palimpset - gui that allows to mount, unmount encrypted LUKS devices inside lvm volumes, renaming VG (volume group), LV (logical volume) and filesystem inside encrypted LUKS volume
  • ubuntu 12.04 LTS
  • mate (it offers one-click mount but probably any other desktop environment will do)
During the whole process tab button will be your friend. It will help with luks subcommands, with finding luks devices etc. So let's start:

Creating encrypted FS

  1. Create partitions that don't waste space but can store your extents and lvm metadata. Something around (n*extent_size)+1mb. Create new partition in Gparted, format as LVM and compare the total size with the available size.
  2. Create desired VGs (my_VG) and LVs (my_LV) using system-config-lvm
  3. Create luks volume using whole available space on created LV. You will be asked for a passphrase
    sudo cryptsetup luksFormat /dev/mapper/my_VG-my_LV
    
  4. Open created luks volume and register it under custom name (my_luks)
    sudo cryptsetup luksOpen /dev/mapper/my_VG-my_LV my_luks
  5. Create filesystem using whole available space on opened luks volume
    mkfs.ext4 /dev/mapper/my_luks
    
  6. (Un)mount volumes and change all the labels using sudo palimpset
That's it. Your system (places or drivemount_applet2) will report existing encrypted LV waiting to be mounted. By default file system label will be used as a mount point for on-click mount.

Shrinking encrypted FS

There is often some confusion which tools use kilo- prefix for 2^10 and which for 10^3. It looks like all commands used below use the 2^10.
  1. Prepare for the shrinking. Open luks, check the FS size and the FS itself.
    sudo cryptsetup luksOpen /dev/mapper/my_VG-my_LV my_luks
    sudo mount -r /dev/mapper/my_luks /any_custom_dir/
    df -h
    df -B1k   # show size in kilobytes (2^10 bytes)
    sudo umount /any_custom_dir/
    e2fsck -f /dev/mapper/my_luks
    
  2. Shrink the FS a bit more than you really need to (about 90%). Provide new size or shrink it maximally with -M. Option -p adds a progress bar. In my case (ext4) system didn't allow me to shrink below the possible minimum size so it looks like you don't have to calculate the new size very precisely. Units: 2^10
    resize2fs -Mp /dev/mapper/my_luks
    or
    resize2fs -p /dev/mapper/my_luks 50G
    Check if all is good
    e2fsck /dev/mapper/my_luks
  3. Shrink the LV. there is no need to shrink the luks volume as it doesn't have the concept of 'fixed size'. During every mount, luks uses all the space of the underlying device. But shrinking the LV is the tricky part. I couldn't find a way to precisely calculate the space. It looks like df shows FS size including its metadata but I don't know which size is used by resize2fs. Anyway, remember about the FS metadata (a few percent) and luks metadata (around 2MB). So add about 10% (depending on your FS type) to the FS size and shrink LV to that size.

    There are many ways to expres the new size (absolute value, difference, percentage etc. use man). The man never says if it uses 2^10 or 10^3 units but it 'seems' like the first one.

    LVM will not warn or prevent you from overwriting your data so bad assumption, calculation or a typo will result in a data loss.
    sudo cryptsetup luksClose my_luks
    sudo lvreduce -L 900G /dev/my_VG/my_LV
    
    Check how big damages were made
    sudo cryptsetup luksOpen /dev/mapper/my_VG-my_LV my_luks
    e2fsck -f /dev/mapper/my_luks
    
  4. If e2fsck said that you've just shrunk your LV too much, don't panic. Just close luks, extend LV a bit lvextend -L, open luks and check your FS again.
    df said my FS was 811G but shrinking LV to 820G (lvreduce -L 820G) was too much. However extending it to 830G was enough.

  5. Grow the FS to fill whole underlying LV, otherwise it would be a waste of space
    resize2fs -p /dev/mapper/my_luks
    e2fsck /dev/mapper/my_luks
    
That's all. Some other useful commands to check the status of devices: http://ubuntuforums.org/showthread.php?t=726724