A quick guide on how to encrypt a complete Gentoo Linux system. By now I have encrypted all my laptops and my little home server. This blog is just a reminder on how to do it, from A to Z. Perhaps it is beneficial for others too.
The objective is all parts of the systems encrypted, including /boot
, and
swap, and to enter the decryption password only once at boot.
This will be a Gentoo linux based system, making use of an UEFI boot sequence, and GRUB boot loader, with OpenRC as init system. Btrfs will be used as file system.
/dev/sda
is used as the the root disk.
Disk partitioning
Make sure to boot from a UEFI capable USB stick, e.g. from the minimal installation CD.
Create a new GTP disk label and the following partitions:
NAME SIZE TYPE Purpose
sda
├─sda1 256 MB EFI System Boot loader
├─sda2 16 GB Linux swap Encrypted swap
└─sda3 rest Linux filesystem System disk
The size of the swap partition should be twice the available RAM.
Format the EFI partition
The EFI partition /dev/sda1
is to be formatted with VFAT32:
# mkfs.vfat -F 32 -n EFI /dev/sda1
Encrypt the root file system and format it
Determine first the UUID of the root disk /dev/sda3
and use that UUID to make a decrypted device at /dev/mapper/luks-{UUID}
,
and create a subvolume gentoo
for the root file system:
# LUKS_ID=$(blkid -o value /dev/sda3 | head -1)
# cryptsetup luksFormat --type luks1 /dev/sda3
# cryptsetup luksOpen /dev/sda3 "luks-${LUKS_ID}"
# mkfs -t btrfs -L rootfs /dev/mapper/luks-${LUKS_ID}
# btrfs subvol create /dev/mapper/luks-${LUKS_ID}/gentoo
Keep note of the UUID of the root disk, stored in ${LUKS_ID}
.
It is going to be needed later.
Install Gentoo as per normal on /dev/mapper/luks-${LUKS_ID}
Mount the "gentoo" subvolume of the crypto disk on /mnt/gentoo
,,
and mount the EFI partion /dev/sda1
on its /boot/efi
directory:
# mount -o subvol=gentoo /dev/mapper/luks-${LUKS_ID} /mnt/gentoo
# mkdir/mnt/gentoo/boot/efi
# mount /dev/sda1 /mnt/gentoo/boot/efi
Download stage3 and unpack it in /mnt/gentoo.
And then chroot into the new environment:
# cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
# mount --types proc /proc /mnt/gentoo/proc
# mount --rbind /sys /mnt/gentoo/sys
# mount --rbind /dev /mnt/gentoo/dev
# mount --bind /run /mnt/gentoo/run
# chroot /mnt/gentoo /bin/bash
# source /etc/profile
# export PS1="(chroot) ${PS1}"
And then continue installing Gentoo as per the handbook.
Make sure to install at least the following packages:
- sys-fs/cryptsetup
- sys-boot/grub, with USE flag device-mapper, add GRUB_PLATFORMS="efi-64" to portage make.conf
- sys-fs/btrfs-progs
- sys-fs/dosfstools
Create a keyfile for the rootfs
A keyfile on encrypted storage to be included in the initramfs, which is also on encrypted storage.
# mkdir /etc/crypt
# dd if=/dev/urandom of=/etc/crypt/key.sda3 bs=1 count=4096`
# cryptsetup luksAddKey /dev/sda3 /etc/crypt/key.sda3
Kernel installation
The easiest and quickest way is to use the Gentoo distribution kernel.
Gentoo now comes with sys-kernel/installkernel
which can:
- install the kernel in
/boot
- create an initramfs using dracut
- generate GRUB's configuration file at
/boot/grub/grub.cfg
.
It requires some settings and USE flags for it all to work.
Create /etc/portage/package.use/installkernel
with the following content,
telling installkernel to use grub and dracut:
sys-kernel/installkernel grub dracut
Configure dracut with a file /etc/dracut.conf
, telling it which modules to
load and where the key for the root disk is:
add_dracutmodules+=" crypt btrfs dm "
install_items+=" /etc/crypt/key.sda3 "
Configure grub in /etc/default/grub
, specifying that it needs to open an
encrypted disk, load the needed modules, and some more linux command line
parameters::
GRUB_DISABLE_SUBMENU=y
GRUB_ENABLE_CRYPTODISK=y
GRUB_PRELOAD_MODULES="luks luks2 geli cryptodisk btrfs"
GRUB_CMDLINE_LINUX="rd.hostonly=1 rootfstype=btrfs rd.luks.allow-discards rd.retry=20 rd.timeout=120 rd.luks=1 rd.luks.uuid=${LUKS_ID} rd.luks.key=/etc/crypt/key.sda3:/ "
Finally emerge sys-kernel/gentoo-kernel
or sys-kernel/gentoo-kernel-bin
.
If all went well there should be kernel with an initramfs in /boot
,
and a grub config file in /boot/grub/grub.cfg
.
Install the boot loader on the EFI partition
# grub-install --efi-directory=/boot/efi
Enable encrypted swap
Encrypted swap is necessary for a properly secured system. It is easy to configure using OpenRC.
Create a file /etc/conf.d/dmcrypt
as follows:
swap=swap-sda2
source='/dev/sda2'
Add dmcrypt to the boot level start up processes:
# rc-config add dmcrypt boot
This will freshly encypt /dev/sda2
on boot, and make it available as
/dev/mapper/swap-sda2
.
It will also place a swap file system on top of it.
Update fstab
Add the following to /etc/fstab
to mount the relevant partitions on boot:
/dev/sda1 /boot/efi vfat noauto 1 2
/dev/mapper/luks-${LUKS_ID} / btrfs noatime,subvol=gentoo 0 1
/dev/mapper/swap-sda2 none swap sw,pri=10 0 0
Remember to replace ${LUKS_ID} with the UUID for the encrypted sda3
partition.
Reboot your system
If all went well then:
- The EFI boot loader will call GRUB
- GRUB will then present you with the password to open
/dev/sda3
- Once
/dev/sda3
is opened, GRUB show its menu, and then boot using the dracut initramfs - Because GRUB cannot pass on the opened device, the initramfs opens the it again using the key file prior to hading over to the linux kernel.
Enable hibernate on encrypted swap
Optionally, when using a laptop, it may be useful to enable hibernation, with the memory image written to the encrypted swap partition.
This requires the major and minor device number to be written to
/sys/power/resume
in the format "MAJOR:MINOR".
An easy way to do this is by placing a small script to be called from OpenRC's local service.
Put the following in a file /etc/local.d/70-setup-hibernate-partition.start
and make it executable:
#!/bin/bash
# Sets up the hiberntate partition by finding the swap partition name,
# and then obtaining the major:minor device id of the swap partition
# and then finally writing the major:minor to /sys/power/resume
#
# Only works when there is only one swap partition
DEV=$(swapon --show=NAME --noheadings)
MAJMIN=$(lsblk ${DEV} -o MAJ:MIN -n)
echo ${MAJMIN} > /sys/power/resume
Execute the script and verify if the contents of /sys/power/resume
is
something like 252:1
.
Conclusion
That's it. A fully encrypted system.