Skip to content

by 2000

(We recommend this tutorial for advanced Linux users)

Full disk encryption: LVMonLUKS with a separate home partition and hibernation with a swapfile

Note: If you don’t necessarily need a separate home partition the tutorial provided in the wiki article “Encrypted installation” may suffice. With the exception of the swapfile creation it fully relies on GUI-tools.

What you’ll end up getting:

  • LVMonLUKS – fully LUKS encrypted single partition containing two logical volumes (“virtual” partitions)
    (1) a logical volume (lv) holding a ext4 filesystem with /boot, /‘root’ and
    (2) a separate lv (ext4) for /home
  • optional free space in the volume group to hold lvm-snapshots and/or potentially extend/shrink the logical volumes later on
  • swapfile, with the ability to hibernate

e. g. end result with a 500GiB drive on a UEFI system

+--------------+-----------------------------------------------------------------------+
 Boot  512MiB | LV 1      40GiB    | LV 2     430GiB      |  free 30GiB 
 /boot/efi          | /   (+swapfile)     | /home                     |                    
                        | /dev/vg0/lvroot   | /dev/vg0/lvhome     |                    
                        |_ _ _ _ _ _ _ _ _ |_ _ _ _ _ _ _ _ _ _ _ |_ _ _ _ _ _ _
 /dev/sda1       |       LUKS (dm-crypt) encrypted /dev/sda2               
+--------------+------------------------------------------------------------------------+

e. g. end result with a 500GiB drive on a BIOS (legacy) system

+-----------+-------------------------------------------------------------------+
      8MiB     | LV 1      40GiB | LV 2     430GiB       | free 30GiB  
 bios_grub  | /   (+swapfile)    | /home                    |                      
                   | /dev/vg0/lvroot  | /dev/vg0/lvhome    |                    
                   |_ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ 
 /dev/sda1  |      LUKS (dm-crypt) encrypted /dev/sda2       
+-----------+--------------------------------------------------------------------+

The following is a tutorial on setting up this type of system with the help of calamares (the EOS installer) and the cli.

++++++++++++++++++++++++++++++++++++++++++

#01 – Boot into Live-CD environment & set up partitions

With the help of GParted, just follow the steps described below.


(a) for UEFI systems:

  • create a GPT partition table
  • create sda1 with 300 to 512MiB, format fat32 and set boot & esp flag
  • create sda2 with xGiB unformatted
  • leave a rest of 8GiB unallocated (on the far right)
+---------------------+-------------------------+---------------------+
 300-512MiB       |      rest          xGiB |        8GiB     
 flag: boot & esp |      unformatted      | unallocated 
 format: fat32      |                               |                    
 /dev/sda1           |      /dev/sda2         |                    
+---------------------+-------------------------+---------------------+

(b) for BIOS (legacy boot) systems:

  • create a GPT partition table
  • create sda1 with 8MiB, leave unformatted and set bios_grub flag
  • create sda2 with xGiB unformatted
  • leave a rest of 8GiB unallocated (on the far right)
+-----------------+-------------------------+--------------------------+
8MiB                 |      rest          xGiB     |        8GiB 
flag: bios_grub  |      unformatted         | unallocated 
unformatted      |                                  |             
/dev/sda1         |      /dev/sda2             |             
+------------------+----------------------------+----------------------+

The unallocated 8GiB of space will hold a temporary installation. We will later reclaim this space by adding it to the LUKS partition on /dev/sda2 and then assign it to e. g. our home volume. For this to work the LUKS partition must reside to the left of the temporary partition because growing a LUKS partition on the right is easy to achieve.

With other storage types, /dev/sda1 could also be called /dev/nvme0n1p1 for example; in this case just substitute sda1 with nvme0n1p1.


#02 – Install temporary system with calamares

Set up calamares like you usually would (Location, Keyboard, Users, …) but
choose Manual partioning and edit (double-click the partition(s) in the list view) to the specifications given below …


(a) for UEFI systems:

  1. /dev/sda1
  • Mount point -> /boot/efi
  • set boot flag
  • keep fat32
  1. free space
  • Mount point -> /
  • File system -> ext4
  • Encrypt: choose short password as this is only temporary

Let Calamares finish the installation. If you get a warning about missing esp or boot flag(s) on /dev/sda1 just add them with GParted and continue with the install.


(b) for BIOS (legacy boot) systems:

  1. free space
  • Mount point -> /
  • File system -> ext4
  • Encrypt: choose short password as this is only temporary

Let Calamares finish the installation. Ignore the window notice “Option to use GPT on BIOS”. We had that set up by gparted already. Continue with the install.



#03 – Reboot & test; reboot into live-cd

After the install finishes reboot and check if you can access the encrypted system.
You should now have a LUKS encrypted system (without the fun stuff like logical volumes, separate /home partition etc.).
Reboot into the Live-Cd environment.


#04 – Open (unencrypt) and mount temporary system

In the live-CD environment, open a Terminal and type (or mark and copy line with ctrl-c and paste in terminal with shift-ctrl-v) …

sudo cryptsetup luksOpen /dev/sda3 crypttemp
sudo mkdir -p /media/crypttemp
sudo mount /dev/mapper/crypttemp /media/crypttemp

Our temporary installation data is now accessible under /media/crypttemp and can be copied to the new system we will be setting up in the next steps.


#05 – Set up new LVMonLUKS system
sudo su
cryptsetup luksFormat --type luks1 /dev/sda2

The –type luks1 is crucial because GRUB does not support LUKS2 yet. If your /boot directory is on a LUKS-encrypted device and you use GRUB as your bootloader, it won’t work with LUKS2.
Choose a secure password (https://xkcd.com/936/)

cryptsetup luksOpen /dev/sda2 crypt
pvcreate /dev/mapper/crypt
vgcreate vg0 /dev/mapper/crypt

A good starting size for the root volume (lvroot) is about 30GiB. If you’re planning on using a swapfile residing on root later on, you should factor that in.
Resizing the volumes later on is quite easy, so don’t give this too much thought.
You could assign all the free space left to the home volume with
lvcreate --extents 100%FREE vg0 -n lvhome
but for growing the volumes later on and for snapshots one needs empty space inside the volume group, so I usually choose a size for lvhome that leaves about 30GiB overall unused space in the volume group (assuming a 500GB drive e. g. 500 – 0.512 – 40 – 430 = 29.488)

lvcreate -L 40G vg0 -n lvroot
lvcreate -L 430G vg0 -n lvhome

Create a ext4 filesystem on the logical volumes.

mkfs.ext4 -L root /dev/mapper/vg0-lvroot
mkfs.ext4 -L home /dev/mapper/vg0-lvhome
exit

#06 – Mount new system to /mnt
sudo mount /dev/mapper/vg0-lvroot /mnt
sudo mkdir -p /mnt/home
sudo mount /dev/mapper/vg0-lvhome /mnt/home

(*) additionally for UEFI systems:

sudo mkdir -p /mnt/boot/efi
sudo mount /dev/sda1 /mnt/boot/efi

lsblk

should now provide a similar output to the following (ignore the sizes, these come from a test install) …


(a) for UEFI systems:

NAME             MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
loop0              7:0    0  1.7G  1 loop  /run/archiso/sfs/airootfs
sda                8:0    0   20G  0 disk  
├─sda1             8:1    0  512M  0 part  /mnt/boot/efi
├─sda2             8:2    0 12.7G  0 part  
│ └─crypt        254:1    0 12.7G  0 crypt 
│   ├─vg0-lvroot 254:2    0   10G  0 lvm   /mnt
│   └─vg0-lvhome 254:3    0    1G  0 lvm   /mnt/home
└─sda3             8:3    0  6.9G  0 part  
  └─crypttemp    254:0    0  6.9G  0 crypt /media/crypttemp
sr0               11:0    1  1.8G  0 rom   /run/archiso/bootmnt

(b) for BIOS (legacy boot) systems:

NAME             MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
loop0              7:0    0  1.7G  1 loop  /run/archiso/sfs/airootfs
sda                8:0    0   20G  0 disk  
├─sda1             8:1    0    8M  0 part  
├─sda2             8:2    0 12.2G  0 part  
│ └─crypt        254:1    0 12.2G  0 crypt 
│   ├─vg0-lvroot 254:2    0   10G  0 lvm   /mnt
│   └─vg0-lvhome 254:3    0    1G  0 lvm   /mnt/home
└─sda3             8:3    0  7.8G  0 part  
  └─crypttemp    254:0    0  7.8G  0 crypt /media/crypttemp
sr0               11:0    1  1.8G  0 rom   /run/archiso/bootmnt


#07 – Copy temporary system to empty new mount points
sudo rsync -avA /media/crypttemp/ /mnt

#08 – Unmount temporary system
sudo umount /media/crypttemp
sudo cryptsetup luksClose crypttemp

#09 – Add existing keyfile to Slot 1 of our LUKS-partition

See which slots have keys

sudo cryptsetup luksDump /dev/sda2 | grep Slot

A LUKS-partition can store and be opened by up to eight different passwords. Right now only Slot 0 contains a key (your chosen password) to decrypt. We will now add a second key which was generated by the temporary install. We will reference this key in the next step.

sudo cryptsetup luksAddKey /dev/sda2 /mnt/crypto_keyfile.bin

#10 – Set up /etc/crypttab
sudo cryptsetup luksUUID /dev/sda2

for example returns 384fb0a7-101a-4c58-8ed7-4ea177a761e0. Your UUID will be different, so make sure you use your UUID in the next step!

sudo leafpad /mnt/etc/crypttab

contains an uncommented line starting with luks-
Change this line to the following; remember to use your UUID.

cryptlvm UUID=384fb0a7-101a-4c58-8ed7-4ea177a761e0 /crypto_keyfile.bin luks

Save and exit.


#11 – Set up /etc/mkinitcpio.conf
sudo leafpad /mnt/etc/mkinitcpio.conf

Change the HOOKS=… line by adding lvm2 and resume (before filesystems).

HOOKS="base udev autodetect modconf block keyboard keymap encrypt lvm2 resume filesystems fsck"

Save and exit.


#12 – Set up /etc/fstab
sudo blkid -s UUID -o value /dev/mapper/vg0-lvroot

returns the UUID of the root volume. For example 5bd28f54-6804-423c-a8c5-f13913793b9a.

sudo blkid -s UUID -o value /dev/mapper/vg0-lvhome

returns the UUID of the home volume. For example de5f20c7-6d53-4f0b-a2c4-8cd8a64eb454.

sudo leafpad /mnt/etc/fstab

contains a line starting with /dev/mapper/luks-
Remove this line and add the following; remember to use your UUIDs.

UUID=5bd28f54-6804-423c-a8c5-f13913793b9a / ext4 defaults,acl,noatime,discard 0 0

UUID=de5f20c7-6d53-4f0b-a2c4-8cd8a64eb454 /home ext4 defaults,acl,noatime,discard 0 0

Save and exit.


#13 – Set up /etc/default/grub
sudo cryptsetup luksUUID /dev/sda2

returns the UUID of the cryptdevice. For example 384fb0a7-101a-4c58-8ed7-4ea177a761e0.

sudo leafpad /mnt/etc/default/grub

In the line starting with GRUB_CMDLINE_LINUX_DEFAULT=…

  • change cryptdevice= entry to the following; remember to use your UUID
cryptdevice=UUID=<YOUR-UUID>:cryptlvm:allow-discards rd.luks.options=discard
  • change root=… to
root=/dev/mapper/vg0-lvroot

It should now resemble the following:

GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=UUID=384fb0a7-101a-4c58-8ed7-4ea177a761e0:cryptlvm:allow-discards rd.luks.options=discard root=/dev/mapper/vg0-lvroot loglevel=3 nowatchdog"

Save and exit.


#14 – Repair GRUB system
sudo su
arch-chroot /mnt
mkinitcpio -p linux
grub-mkconfig -o /boot/grub/grub.cfg

(a) for UEFI systems:

grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=EndeavourOS-grub
rm -rf /boot/efi/EFI/EndeavourOS
cp /boot/efi/EFI/EndeavourOS-grub/grubx64.efi /boot/efi/EFI/boot/bootx64.efi

(b) for BIOS (legacy boot) systems:

grub-install --target=i386-pc /dev/sda

exit

#15 – Reboot & test new encrypted LVMonLUKS system
sudo umount -R /mnt
sudo reboot

DONE! You should now have a functioning LVMonLUKS system with a separate logical volume for /home.

++++++++++++++++++++++++++++++++++++++++++

# OPTIONAL – Add space of temporary partition to LUKS-partition

You could simply reformat /dev/sda3 and use it as unencrypted storage, but here we will reclaim the space and assign it to e. g. our home volume.


#16 – Reboot into the Live-Cd environment.

#17 – Delete sda3 (temporary EndeavourOS Install)
sudo fdisk -l

displays some information regarding our disks and partitions.

We will now delete /dev/sda3. Just enter the characters below in the given order.

sudo fdisk /dev/sda
> p
> d
> 3 (delete partition 3)
> w (write changes to disk)

#18 – Extend /dev/sda2 (LUKS-partition) and the volume group
sudo fdisk /dev/sda
> d
> 2 (delete partition 2)
> n
> 2 (recreate partition 2)
>   (first sector is 'default'; press enter)
>   (last sector is 'default'; press enter)
> n (keep existing filesystem signature)
> w (write changes to disk)
sudo cryptsetup luksOpen /dev/sda2 crypt
sudo cryptsetup resize crypt -v
sudo e2fsck -f /dev/mapper/vg0-lvroot
sudo e2fsck -f /dev/mapper/vg0-lvhome
sudo pvresize /dev/mapper/crypt

The volume group vg0 now contains the space we freed up by deleting /dev/sda3. It was added as free space one could use for snapshots or future assigning to the root or home volume (which we’ll do in the next step) or to additional (new) volumes.


#19 – Grow home volume

Theoretically you should be able to resize logical volumes with KDE Partition Manager. I’ve actually never tried this and will stick to the cli.


Some information on how to convert/calculate sectors, MB, PE’s:

  • sectors / 2048 / 4 = PE
  • PE *4 = MiB *2048 = sectors
    If your calculations return a non-integer of PE’s, you have to round it down!

sudo fdisk -l
sudo vgdisplay
sudo lvdisplay
will provide information regarding used (allocated) and free space.

Examples for different growing possibilities:

  • grow lvroot by 32326 PE
    sudo lvextend -l+32326 /dev/mapper/vg0-lvroot
  • extend the volume to 150GB
    sudo lvextend -L150G /dev/mapper/vg0-lvroot
  • extend the volume by 10GB
    sudo lvextend -L+10G /dev/mapper/vg0-lvroot
  • fill all of the unallocated space in the volume group
    sudo lvextend -l +100%FREE /dev/vg0-lvroot

But we will now add the formerly freed up space (8GiB) to the home volume.

sudo lvextend -L+8G /dev/mapper/vg0-lvhome

adds 8GB to the logical home volume.

The filesystem residing in our logical volume needs to be adjusted as well. We will grow the filesystem to the maximum size to add the 8GB.

sudo resize2fs -p /dev/mapper/vg0-lvhome

Let’s check the resized logical volumes filesystem …

sudo e2fsck -f /dev/mapper/vg0-lvhome

DONE! You can leave the live-cd environment and reboot into your LVMonLUKS-system.

++++++++++++++++++++++++++++++++++++++++++

# OPTIONAL – Add a swapfile (with working hibernation)

#20 – Make a swapfile

Note: If you want to use hibernation, then you must add swap because the content of the RAM will be written to the swap partition/file. This also means that the swap size should be at least the size of RAM. Read here about choosing swap sizes for example.

Choose you swapfile size (e. g. “8” for 8GB).

swapsizeGB=8

The following commands will produce a swapfile with your chosen size:

swapsize=$(( swapsizeGB * 1024 ))
sudo dd if=/dev/zero of=/swapfile count=$swapsize bs=1MiB status=progress
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

To check …

swapon --show

#21 – Edit /etc/fstab to enable the swapfile after reboot
sudo leafpad /etc/fstab

Add the following line …

/swapfile none swap defaults,pri=-2 0 0

Save and exit.


#22 – Activate hibernation
sudo blkid -s UUID -o value /dev/mapper/vg0-lvroot

returns the UUID of the root volume. For example 53d2a76e-13b8-4a29-affc-197b33a706c1.

sudo filefrag -v /swapfile | awk '{if($1=="0:"){print $4}}'

returns the swapfile offset. For example 997376.., which means 997376.

sudo leafpad /etc/default/grub

Add the resume=UUID= and resume_offset= entry to the end of GRUB_CMDLINE_LINUX_DEFAULT=; remember to use your UUID and offset.

GRUB_CMDLINE_LINUX_DEFAULT="[...] resume=UUID=53d2a76e-13b8-4a29-affc-197b33a706c1 resume_offset=997376"

Save and exit.


If you didn’t already follow step #11 and add resume to /etc/mkinitcpio.conf, do this now …

sudo leafpad /etc/mkinitcpio.conf

Change the HOOKS=… line by adding resume (before filesystems).

HOOKS="base udev autodetect modconf block keyboard keymap encrypt lvm2 resume filesystems fsck"

Save and exit.


Let the system know that some things have changed …

sudo mkinitcpio -p linux
sudo grub-mkconfig -o /boot/grub/grub.cfg

DONE! You should now have a swapfile and be able to hibernate.

++++++++++++++++++++++++++++++++++++++++++

Initially posted on the forum: 2019-08-19
Wiki version: 2020-07-29

LVMonLUKS

  • by