This post describes how to setup a Gentoo GNU/Linux system with an encrypted file system. The root file system, along with the kernel, are encrypted. This leaves the bootloader as the only unencrypted component. The resulting system has the following features:
- x86-64 architecture with multilib support
- Use EFI firmware to boot
- Use a GPT partition table
- No swap partition. For my purposes, I do not need a separate swap
partition.
- dm-crypt/LUKS encrypted root partition, including the kernel. Every part
of the system is encrypted except for the bootloader.
Boot a Live CD
To start the process, the system must be booted using a Live CD or similar. The present Gentoo minimal install disc does not support EFI booting, but two alternatives are:
- [SystemRescueCd](http://system-rescue-cd.org), a Gentoo-based system
frequently used for system recoery. This boots to a CLI.
- The normal [Ubuntu](https://ubuntu.com) installer, which boots to a
graphical environment. This is useful for easy access to a web browser.
Using the Live CD of your choice, boot the system and open a terminal.
Disk Setup
Once booted into a Linux environment, the disk can be partitioned. For this setup, three partitions are used:
- GRUB Partition
- EFI System Partition
- Root Partition
For the rest of this document, the instalation drive is assumed to be
/dev/sda
. This may be different depending on the system, especially if there
are multiple drives. The lsblk
command can help determine the correct device
to use.
Partitioning
Start parted
and direct it to the desired disk.
parted -a optimal /dev/sda
To see any existing partitions, use the print
command. Create a new GPT
partition label. In this case, a GPT label is used.
mklabel gpt
Set the units displayed to Mibibytes rather than sectors. This makes partition sizes easier to understand.
unit mib
Create the GRUB partition with a 2 MiB size.
mkpart primary 1 3
Set a name for the GRUB partition.
name 1 grub
Turn on the bios_grub
flag for the GRUB partition.
set 1 bios_grub on
Next, create the EFI system partition with a size of 128 MiB.
mkpart primary 3 131
Set a name for the EFI system partition.
name 2 efi
Finally, create the root partition. This partition uses the rest of the disk.
mkpart primary 131 -1
Set a name for the root partition.
name 3 rootfs
Create Encrypted Device
With the partitions created, a LUKS encrypted container can be created inside the root partition created above.
$ cryptsetup --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 5000 --use-random --verify-passphrase --verbose luksFormat /dev/sda3
The following options are used:
- `--cipher aes-xts-plain64` selects AES encryption in XTS mode using the
plain64 initialization vector.
- `--key-size 512` uses a 512 bit encryption key. Because XTS mode
effectivly halves the key size, this results in AES-256 encryption. To
use faster AES-128 encryption, set the key size to 256.
- `--hash sha512` uses the SHA-512 hash algorithm for the encryption keys.
- `--iter-time 5000` sets the number of milliseconds to spend on PBKDF2
password processing. Increasing this value makes it more difficult to
brute-force the password, but adds a time delay between password
attempts. A setting of 5,000 milliseconds means it takes 5 seconds for
the device to unlock after entering the password. This should be set to
be as long as is tolerable.
- `--use-random` forces the use of `/dev/random` as the entropy source.
This is generally considered more secure than using `/dev/urandom`, as
it ensures high quality random data. The downside is that using
`/dev/random` can take significantally longer, as once the entropy pool
is depleated, the system will wait until there is more entropy. When
using `/dev/urandom`, the system will generate pseudo-random data once
the entropy pool is depleated.
- `--verify-passphrase` forces the user to enter the new passphrase twice
to confirm that it is correct.
- `--verbose` produces additional output.
- `luksFormat` specifies to use a LUKS formatted container.
- `/dev/sda3` is the partition to use.
This may take a long time to run. Once it completes, the new encrypted container can be opened. This command opens the container and names it "root". It will prompt for the password used when creating the container.
$ cryptsetup open /dev/sda3 root
When this is complete, a new block device will appear at /dev/mapper/root
.
This device can now be used to install Gentoo.
Create File Systems
With the new block device available at /dev/mapper/root
, it can be formatted
with the file system of choice. In this example, the btrfs file sytem is used
and gives the partition a label of "rootfs". The label is optional and not
required.
$ mkfs.btrfs -L rootfs /dev/mapper/root
Mount the root file system. If /mnt/gentoo
does not exist, create it first.
$ mkdir /mnt/gentoo
$ mount -t btrfs -o compress /dev/mapper/root /mnt/gentoo
Create a FAT32 file system on the EFI system partition. This is where the bootloader is stored and is not encrypted. This example gives the partition a name of "ESP" (short for EFI system partition).
$ mkfs.vfat -F 32 -n ESP /dev/sda2
Create the EFI directory and mount the EFI system partition.
$ mkdir -p /mnt/gentoo/boot/efi
$ mount /dev/sda2 /mnt/gentoo/boot/efi
Gentoo Setup
With the disks configured, Gentoo can mostly be installed as usual. These instructions mirror those found in the Gentoo Handbook.
Prepare Directories
Change to the /mnt/gentoo
directory.
$ cd /mnt/gentoo
Download the latest stage 3 tarball to the /mnt/gentoo
directory. For a list
of mirrors, see the Gentoo Mirror List.
Select a mirror and download the latest stage 3 tarball located in the
releases/amd64/autobuilds
directory on the mirror.
$ wget ............................
Extract the stage 3 tarball.
$ tar xvjpf stage3-*.tar.bz2 --xattrs
Modify the /mnt/gentoo/etc/portage/make.conf
file as desired. This is a good
time to set variables such as CFLAGS, INPUT_DEVICES, L10N, LINGUAS, MAKEOPTS,
or VIDEO_CARDS. Since this is an EFI system, set GRUB_PLATFORMS="efi-64"
within make.conf
as well.
$ nano -w /mnt/gentoo/etc/portage/make.conf
Create the repos.conf
file and modify as desired.
$ mkdir /mnt/gentoo/etc/portage/repos.conf
$ cp /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
$ nano -w /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
Copy the resolv.conf
file into the new system to ensure the network is
accessible after running chroot
.
cp -L /etc/resolv.conf /mnt/gentoo/etc/
Mount necessary file systems and enter the new environment.
$ mount -t proc proc /mnt/gentoo/proc
$ mount --rbind /sys /mnt/gentoo/sys
$ mount --rbind /dev /mnt/gentoo/dev
$ chroot /mnt/gentoo /bin/bash
$ source /etc/profile
$ export PS1="(chroot) $PS1"
Configure the New System
Within the new environment, the rest of the system can be configured. First, update the portage tree.
$ emerge-webrsync
Set the timezone. Change "America/Los_Angeles" as desired. Possible values can be found in the "TZ" column in this list on Wikipedia.
$ echo "America/Los_Angeles" > /etc/timezone
$ emerge --config sys-libs/timezone-data
Adjust the locale settings as desired and regenerate the locales.
$ nano -w /etc/locale
Select the desied locale with eselect.
$ eselect locale list
[1] C
[2] en_US
[3] en_US.iso88591
[4] en_US.utf8
[5] POSIX
[ ] (free form)
$ select locale set 4
$ env-update
Configure The initramfs
The kernel alone is not able to decrypt the root file system, so an initramfs
is required. The initramfs is a minimal file system that contains the tools
required in order to unlock the full root file system and boot the system.
There are many ways to create an initramfs, but the method shown here is
called Early Userspace. Technically, the modern Linux kernel always uses an
initramfs, but it defaults to being empty. If the initramfs is empty, the
kernel reverts back to older methods of finding the root file sysetm and
executing /sbin/init
. It is also possible (and perhaps more common) to create
an external initramfs, but that will not be covered here. In this section, the
built-in initramfs is populated with the tools required to unlock the encrypted
root file system.
First, install cryptsetup
, which provides the tools needed to decrypt the
root file system. The cryptsetup
binary needs to be included in the
initramfs to decrypt the disk.
$ emerge -av cryptsetup
Create a directory to contain the initramfs configuration files. The exact
location does not matter, but this document uses /usr/src/initramfs
.
$ mkdir /usr/src/initramfs
If you use a keyboard layout other than the en-US QWERTY layout, generate a keymap binary to load in the initramfs. Here, the Dvorak layout is used.
$ loadkeys -b dvorak > /usr/src/initramfs/dvorak.keymap
Create an init script that initializes the system inside the initramfs.
$ nano -w /usr/src/initramfs/init
The primary purpose of the init script is to mount necessary file systems
(such as /dev
, /proc
, and /sys
), unlock the root file system, and then
continue the boot process by switching to the "real" root file system. The
following example does this, along with a few convience features such as
setting the keyboard layout.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
Create a configuration file describing what needs to be added to the initramfs. The following example shows the bare essentials, along with providing a custom keyboard layout. For additional information on the format of this file, see the kernel documentation for Early Userspace and initramfs.
$ nano -w /usr/src/initramfs/initramfs-list
Example configuration:
# Main directory structure
dir /bin 755 0 0
dir /dev 755 0 0
dir /etc 755 0 0
dir /lib 755 0 0
dir /lib32 755 0 0
dir /lib64 755 0 0
dir /mnt 755 0 0
dir /mnt/root 755 0 0
dir /proc 755 0 0
dir /root 700 0 0
dir /sbin 755 0 0
dir /sys 755 0 0
dir /usr 755 0 0
# Main init script
file /init /usr/src/initramfs/init 755 0 0
# Node required for the console. This is required to get a shell in the initramfs.
nod /dev/console 644 0 0 c 5 1
# Keyboard layout (optional)
file /root/dvorak.keymap /usr/src/initramfs/dvorak.keymap 755 0 0
# BusyBox
slink /bin/sh /bin/busybox 777 0 0
file /bin/busybox /bin/busybox 755 0 0
# Libraries roquired by cryptsetup (use ldd to discover)
dir /usr/lib64 755 0 0
file /sbin/cryptsetup /sbin/cryptsetup 755 0 0
dir /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 755 0 0
file /lib64/libc.so.6 /lib64/libc.so.6 755 0 0
file /lib64/libdevmapper.so.1.02 /lib64/libdevmapper.so.1.02 755 0 0
file /lib64/libpthread.so.0 /lib64/libpthread.so.0 755 0 0
file /lib64/libudev.so.1 /lib64/libudev.so.1 755 0 0
file /lib64/libuuid.so.1 /lib64/libuuid.so.1 755 0 0
file /usr/lib64/libcryptsetup.so.4 /usr/lib64/libcryptsetup.so.4 755 0 0
file /usr/lib64/libgcrypt.so.20 /usr/lib64/libgcrypt.so.20 755 0 0
file /usr/lib64/libgpg-error.so.0 /usr/lib64/libgcrypt.so.20 755 0 0
file /usr/lib64/libpopt.so.0 /usr/lib64/libpopt.so.0 755 0 0
Note that in addition to the cryptsetup
binary, all libraries required by
the binary are also included in the initramfs. These libraries can be found
using ldd
. If additional utilities are required in the initramfs, they must
be added to this configuration file.
With the initramfs configuration defined, the kernel can be configured.
Configure the Kernel
Install and configure the Linux kernel.
$ emerge -av gentoo-sources
$ cd /usr/src/linux
$ make menuconfig
Be sure to enable the following options as built-in, not as modules:
CONFIG_BLK_DEV_INITRD
CONFIG_BLK_DEV_DM
CONFIG_DM_CRYPT
CONFIG_CRYPTO_AES_X86_64
CONFIG_CRYPTO_SHA512
CONFIG_CRYPTO_XTS
In order to build the initramfs into the kernel binary, the
CONFIG_INITRAMFS_SOURCE
value must be set in the kernel configuration to the
file created previously.
(/usr/src/initramfs/initramfs-list) Initramfs source file(s)
After configuring the kernel, build and install it.
$ make
$ make modules_install
$ make install
Configure System Settings
If your system requires firmware blobs, such as those required by many
wireless network adapters, install the linux-firmware
package.
$ emerge -av linux-firmware
Configure the /etc/fstab
file to mount the file system as read-write. Add
any additional file systems that should be mounted automatically once
booted into the full system.
/dev/mapper/root / btrfs noatime,compress 0 1
Set a hostname in /etc/conf.d/hostname
.