You can make the entire physical volume encrypted, and then initrams will take care of access to encrypted PV. LVM and rest OS will not feel that encryption exists at all. You can read about that here. This may even be the preferred method for most systems, but not for my workstation. Every time I create, start and destroy the number of virtual machines. Total encryption will compromise performance on my old magnetic disk. Moreover, there is no valuable information for encryption.
That's why I decided to only encrypt my /home. I do not want anyone to benefit from my (if) a stolen workstation.
Create LV:
# lvcreate -n home -L 20g /dev/rootvg # wipefs -a /dev/rootvg/home
Now encrypt LV before creating FS:
# cryptsetup luksFormat /dev/rootvg/home WARNING! ======== This will overwrite data on /dev/rootvg/home irrevocably. Are you sure? (Type uppercase yes): YES Enter passphrase: Verify passphrase: # cryptsetup isLuks /dev/rootvg/home && echo Success Success # cryptsetup luksDump /dev/rootvg/home
According to dump, a Key Slot 0 is in use by passphrase you've entered while setup encryption.
Now, lets open encrypted volume manually and populate it:
# cryptsetup luksOpen /dev/rootvg/home home Enter passphrase for /dev/rootvg/home: # ls -l /dev/mapper/home lrwxrwxrwx. 1 root root 7 May 19 19:29 /dev/mapper/home -> ../dm-4
The last options of cryptsetup luksOpen command is a handy name. The resulting /dev/mapper/home appear.
# mkfs.ext4 -j -m0 /dev/mapper/home .. # mount /dev/mapper/home /mnt # rsync -av --one-file-system /home/ /mnt/ # umount /home /mnt ; mv /home /home.old ; mkdir /home # mount /dev/mapper/home /home
Edit /etc/crypttab and add the following line:
# cat /etc/crypttab # name device passphrasefile options home /dev/rootvg/home none luks,x-systemd.device-timeout=0
First field is a handy name, next is a device to be opened. Third field is a passphrase containing file (will decribe later), currently "none" for manual passphrase input. Fourth field is a mount options, most interesting is x-systemd.device-timeout=0 that means waiting forever for passphrase input.
Tell systemd to rescan configuration files and generate new service, then check the results:
# systemctl daemon-reload # find /var/run/systemd/generator | grep cryptsetup /var/run/systemd/generator/dev-mapper-home.device.requires/systemd-cryptsetup@home.service /var/run/systemd/generator/cryptsetup.target.requires /var/run/systemd/generator/cryptsetup.target.requires/systemd-cryptsetup@home.service /var/run/systemd/generator/dev-rootvg-home.device.wants/systemd-cryptsetup@home.service /var/run/systemd/generator/systemd-cryptsetup@home.service
Close the encrypted device manually and check whether the system is able to manage it.
# umount /dev/mapper/home # cryptsetup luksClose home # ls -l /dev/mapper/home ls: cannot access '/dev/mapper/home': No such file or directory # systemctl start systemd-cryptsetup@home.service Please enter passphrase for disk rootvg-home (home)! ********************** # ls -l /dev/mapper/home lrwxrwxrwx. 1 root root 7 May 19 21:30 /dev/mapper/home -> ../dm-4
If you now reboot, you will be prompted to enter a passphrase at boot time, and /dev/mapper/home will be activated. However, it will not be mounted, because nothing has been added to the /etc/fstab. Let's add it before rebooting:
# grep home /etc/fstab /dev/mapper/home /home ext4 x-systemd.device-timeout=0 1 2
You can save the passphrase in a file and avoid entering the passphrase manually at each boot. When can this be useful? Perhaps, if you have a root file system located in a secure place, while a remote attached drive is not. Then you can encrypt a remote disk with a passphrase located in the protected root file system.
Generate some random garbage to file:
# dd if=/dev/urandom of=/root/.passphrase bs=32 count=1 # chmod 600 /root/.passphrase # xxd -p -c 32 /root/.passphrase 25ff3c06493f809e8d9639040e1d7e093960860e07631d71388509af12b561c3
Now, let's add the new passphrase to our device (you will be prompted for known passphrase to enter):
# cryptsetup luksAddKey /dev/rootvg/home /root/.passphrase Enter any existing passphrase: # cryptsetup luksDump /dev/rootvg/home
You will see Key Slot 1 will be in use now. Let's check the new functionality:
# umount /dev/mapper/home # cryptsetup luksClose home # cryptsetup luksOpen /dev/rootvg/home home --key-file /root/.passphrase
Once manual activation is works, let's change /etc/crypttab file:
# cat /etc/crypttab # name device passphrasefile options #home /dev/rootvg/home none luks,x-systemd.device-timeout=0 home /dev/rootvg/home /root/.passphrase luksAnd reboot the system.
The following steps should be performed:
# pvs PV VG Fmt Attr PSize PFree /dev/vda2 rootvg lvm2 a-- 9.75g 3.50g # lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert home rootvg -wi-ao---- 256.00m slash rootvg -wi-ao---- 3.00g swap rootvg -wi-ao---- 1.00g var rootvg -wi-ao---- 2.00g # lvresize -L+1g /dev/rootvg/home Size of logical volume rootvg/home changed from 256.00 MiB (64 extents) to 1.25 GiB (320 extents). Logical volume rootvg/home successfully resized. # cryptsetup resize /dev/mapper/home # resize2fs /dev/mapper/home resize2fs 1.43.3 (04-Sep-2016) Filesystem at /dev/mapper/home is mounted on /home; on-line resizing required old_desc_blocks = 2, new_desc_blocks = 10 The filesystem on /dev/mapper/home is now 1308672 (1k) blocks long. # df /home Filesystem Size Used Avail Use% Mounted on /dev/mapper/home 1.3G 2.7M 1.2G 1% /home
The steps are opposite and requires exact sizing values:
# umount /dev/mapper/home # resize2fs /dev/mapper/home 1000m resize2fs 1.43.3 (04-Sep-2016) Please run 'e2fsck -f /dev/mapper/home' first. # e2fsck -f /dev/mapper/home e2fsck 1.43.3 (04-Sep-2016) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information /dev/mapper/home: 11/325120 files (0.0% non-contiguous), 47921/1308672 blocks # resize2fs /dev/mapper/home 1000m resize2fs 1.43.3 (04-Sep-2016) Resizing the filesystem on /dev/mapper/home to 1024000 (1k) blocks. The filesystem on /dev/mapper/home is now 1024000 (1k) blocks long. # cryptsetup status /dev/mapper/home /dev/mapper/home is active. type: LUKS1 cipher: aes-xts-plain64 keysize: 256 bits device: /dev/mapper/rootvg-home offset: 4096 sectors size: 2617344 sectors mode: read/write # echo $((1*1024*1024*2)) # <-- 1G in 512b sectors 2097152 # cryptsetup resize /dev/mapper/home --size 2097152 # cryptsetup status /dev/mapper/home /dev/mapper/home is active. type: LUKS1 cipher: aes-xts-plain64 keysize: 256 bits device: /dev/mapper/rootvg-home offset: 4096 sectors size: 2097152 sectors mode: read/write # lvresize -L1g /dev/rootvg/home WARNING: Reducing active and open logical volume to 1.00 GiB. THIS MAY DESTROY YOUR DATA (filesystem etc.) Do you really want to reduce rootvg/home? [y/n]: y Size of logical volume rootvg/home changed from 1.25 GiB (320 extents) to 1.00 GiB (256 extents). Logical volume rootvg/home successfully resized. # resize2fs /dev/mapper/home resize2fs 1.43.3 (04-Sep-2016) Resizing the filesystem on /dev/mapper/home to 1046528 (1k) blocks. The filesystem on /dev/mapper/home is now 1046528 (1k) blocks long.
You should have saved master key somewhere in secure place to be able recovery forgotten passphrases. So, dump it and save:
# cryptsetup luksDump --dump-master-key /dev/rootvg/home WARNING! ======== Header dump with volume key is sensitive information which allows access to encrypted partition without passphrase. This dump should be always stored encrypted on safe place. Are you sure? (Type uppercase yes): YES Enter passphrase: LUKS header information for /dev/rootvg/home Cipher name: aes Cipher mode: xts-plain64 Payload offset: 4096 UUID: f520b10c-6ea8-4565-aa82-7a382bc952c4 MK bits: 256 MK dump: 00 0f 05 0d 2a bb 78 a0 43 86 6d b0 44 3a 2c d5 bd 70 5c be 33 1c e5 1f 38 7c f8 cd 63 50 9f 2f
The other way to see master key for already opened device without need to enter passphrase:
# dmsetup table --showkeys | grep ^home home: 0 2097152 crypt aes-xts-plain64 000f050d2abb78a043866db0443a2cd5bd705cbe331ce51f387cf8cd63509f2f 0 253:3 4096
As you see it is the same key as MK dump: value. Translate it into binary form:
# echo 000f050d2abb78a043866db0443a2cd5bd705cbe331ce51f387cf8cd63509f2f | xxd -r -p > MK.bin # xxd -p -c 32 MK.bin 000f050d2abb78a043866db0443a2cd5bd705cbe331ce51f387cf8cd63509f2f
Now you can add a new passphrase without knowing the previous:
# cryptsetup luksAddKey /dev/rootvg/home --master-key-file MK.bin Enter new passphrase for key slot: Verify passphrase: # cryptsetup luksDump /dev/rootvg/home