How To Install Gentoo With LVM and Disk Encryption
Hey there. Lately, I switched my laptops and servers from a pair of
Debian/OpenBSD to Gentoo. I did it because I wanted to know and master only one
OS everywhere, but none of them were completely suitable for that: OpenBSD
doesn't work well on laptops and lacks some things that are important for me
1, while Debian uses systemd
init
system which I find unnecessarily complex and almost impossible to master.
2
As for Gentoo, it is a Linux-based OS which comes with a relatively lightweight OpenRC init system; it allows you to build and use secure alternatives from the OpenBSD world (libressl, OpenNTPD, etc.) as well. The biggest downside could be the time spent on building everything from source code, but nowadays it's not that bad. Another problem is to find a hosting provider which supports Gentoo; luckily the one I use (Vultr) does it.
This article is a quick installation checklist for experienced users. It will
help you with Gentoo installation on LVM-managed disk with encryption. I'd like
to stress out that it's not a full-disk encryption because it doesn't encrypt
/boot
partition. It won't be suitable, for example, in the case when someone
would like to implant malicious software into the kernel and spy on you. As
for me, I'd like to prevent bad people from accessing my personal information
when my laptop is lost or stolen, so it's enough to only encrypt the data
partitions.
Booting Up
I believe that you already know how to dump Gentoo ISO onto USB drive and boot from it; you can read about it in Gentoo Handbook if not.
The first thing after you boot up is to check that your network connection is
working. You can do it by inspecting network interfaces via ifconfig
. Run
net-setup <interface>
to set up a network interface if it wasn't done
automatically.
Create Partitions
It is assumed throughout the guide that you're installing Gentoo on /dev/sda
disk. If it's not correct, check available devices with lsblk
command and
replace /dev/sda
appearances with a correct device.
Partition Schema (UEFI systems)
Partition | Filesystem | Size | Description |
---|---|---|---|
/dev/sda1 | FAT32 | 256MB | UEFI ESP |
/dev/sda2 | ext4 | 256MB (at least) | /boot |
/dev/sda3 | Crypto+LVM | Rest of the disk | LVM Volumes |
Partition Schema (BIOS systems)
Partition | Filesystem | Size | Description |
---|---|---|---|
dev/sda1 | (none) | 2MB | BIOS Boot |
/dev/sda2 | ext4 | 256MB (at least) | /boot |
/dev/sda3 | Crypto+LVM | Rest of the disk | LVM Volumes |
Run parted on a selected device with optimal alignment for partitions:
# parted -a optimal /dev/sda
Then execute the following parted commands depending on the type of a system you're on.
For UEFI systems:
# Make new GPT partition table
mklabel gpt
# Create an UEFI ESP
mkpart primary 1MiB 257MiB
name 1 efi
set 1 esp on
# Create a boot partition
mkpart primary 257MiB 513MiB
name 2 boot
set 2 boot on
# Create a LVM partition
mkpart primary 513MiB 100%
name 3 data-encrypted
set 3 lvm on
# Check that everything is correct and quit
print
quit
For BIOS systems:
# Make new GPT partition table
mklabel gpt
# Create a BIOS Boot partition
mkpart primary 1MiB 3MiB
name 1 biosboot
set 1 bios_grub on
# Create a boot partition
mkpart primary 3MiB 259MiB
name 2 boot
set 2 boot on
# Create a LVM partition
mkpart primary 259MiB 100%
name 3 data-encrypted
set 3 lvm on
# Check that everything is correct and quit
print
quit
Encrypt Data Partition
Create encrypted partition
# cryptsetup -s 512 --use-random luksFormat /dev/sda3
Make encrypted partition available
# cryptsetup luksOpen /dev/sda3 data-decrypted
After that, the decrypted partition should be available via
/dev/mapper/data-decrypted
.
Create LVM Partitions
Create physical volume
# pvcreate /dev/mapper/data-decrypted
Create volume group
# vgcreate datavg /dev/mapper/data-decrypted
Optionally you can also create a swap volume. The recommendation is to create a swap volume of a size twice the size of the available RAM.
# lvcreate -L 1GiB -n swap datavg
Finally, create the root volume
# lvcreate -l 100%VG -n root datavg
After that, the root volume should be available via /dev/mapper/datavg-root
.
Create Filesystems And Mount
Format ESP partition (UEFI systems only)
# mkfs.fat -F 32 /dev/sda1
Format /boot
partition
# mkfs.ext4 -L boot /dev/sda2
Format and mount /
partition
# mkfs.btrfs -L root /dev/mapper/datavg-root
# mount /dev/mapper/datavg-root /mnt/gentoo
Format and mount swap partition if you've created it earlier
# mkswap /dev/mapper/datavg-swap
# swapon /dev/mapper/datavg-swap
Change directory to a place where the root partition is mounted
# cd /mnt/gentoo
Install The Base System
Now we need to download precompiled base system (so-called "Stage 3" tarball), extract it and configure Portage so that we could compile the kernel and other programs.
Get And Unpack Stage3
First of all, set the correct date and time so that you won't have any issues with newly created files later.
# ntpd -qg
It is almost always better to install the latest base system. To find out the
filename of its tarball, we can request a list of files from the Gentoo FTP
server. Here is a command to query files for the Hardened Gentoo for amd64
architecture
# curl --list-only ftp://gentoo.osuosl.org/pub/gentoo/releases/amd64/autobuilds/current-stage3-amd64-hardened/
You need a file with a name like stage3-*.tar.xz
. Once you found it, download and unpack it into /mnt/gentoo
# wget ftp://gentoo.osuosl.org/pub/gentoo/releases/amd64/autobuilds/current-stage3-amd64-hardened/stage3-amd64-hardened-20190113T214502Z.tar.xz
# tar xpvf stage3*.tar.xz --xattrs-include='*.*' --numeric-owner
Next step is to select a Portage mirror to download ebulds from. Below is the command to do it. 3
# mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf
Chroot Into The System
Copy DNS information to the chroot
# cp -L /etc/resolv.conf /mnt/gentoo/etc/
Mount necessary filesystems
# mount --types proc /proc /mnt/gentoo/proc
# mount --rbind /sys /mnt/gentoo/sys
# mount --make-rslave /mnt/gentoo/sys
# mount --rbind /dev /mnt/gentoo/dev
# mount --make-rslave /mnt/gentoo/dev
Chroot to the new system
# chroot /mnt/gentoo /bin/bash
(chroot) # source /etc/profile
(chroot) # export PS1="(chroot) $PS1"
Mount boot partition
(chroot) # mkdir /boot
(chroot) # mount /dev/sda2 /boot
Mount ESP partition (UEFI systems only)
(chroot) # mkdir -p /boot/efi
(chroot) # mount /dev/sda1 /boot/efi
Configure Portage And Update The World
Download latest ebuilds
(chroot) # emerge-webrsync
(chroot) # emerge --sync
Choose the right profile
(chroot) # eselect profile list
(chroot) # eselect profile set <prof-num>
Now it's time to configure Make, CC and USE flags.4 They highly depend on what kind of system you're building and the hardware you're running on. My usual choice is
COMMON_FLAGS
-
-O2
to enable reasonably safe compiler optimizations -
-march=native -mtune=native
to allow GCC to generate the code specific to the architecture of your CPU -
-pipe
to use piped IO instead of temporary files for communication between various stages of compilation
MAKEOPTS
-jN
whereN
is the number of cores/CPUs you have in the system. It enables parallel execution of make targets.
USE
for all systems
-
bash-completion
to install completers for Bash if available -
hardened
to activate security enhancements for compiler toolchain -
-jit
to disable JIT compilation which may not play well with Hardened Gentoo -
libressl
to use LibreSSL library instead of OpenSSL 5 -
vim-syntax
to install vim syntax files if available -
xattr
to add support for extended filesystem attributes
USE
for desktop systems
-
alsa
to enable ALSA sound system support -
dbus
to enable DBUS messaging system support -
-gnome -gnome-keyring
to disable GNOME support -
-kde
to disable KDE support -
-pulseaudio
to disable Pulseaudio support -
xft
to enable the X FreeType interface library -
X
to enable X11 support 6
Finally edit Portage configuration
(chroot) # $EDITOR /etc/portage/make.conf
Update the @world 7
(chroot) # emerge -avuDN @world
Configure The System
Set the timezone (see /usr/share/zoneinfo
for available timezones)
(chroot) # echo "Europe/Berlin" > /etc/timezone
(chroot) # emerge --config sys-libs/timezone-data
Generate locales to use in the system
(chroot) # $EDITOR /etc/locale.gen
(chroot) # locale-gen
(chroot) # locale -a
Set system-wide locale settings and reload the environment
(chroot) # eselect locale list
(chroot) # eselect locale set <locale-num>
(chroot) # env-update
(chroot) # source /etc/profile
(chroot) # export PS1="(chroot) $PS1"
Set the hostname
(chroot) # $EDITOR /etc/conf.d/hostname
(chroot) # $EDITOR /etc/hosts
Set root password
(chroot) # passwd
Add a regular user if necessary
(chroot) # useradd -g users -G <group1>,<group2> -m <username>
Change keyboard settings if necessary. If you switch Ctrl and CapsLock as I do,
set EXTENDED_KEYMAPS="ctrl"
.
(chroot) # $EDITOR /etc/conf.d/keymaps
Change hardware clock settings if necessary
(chroot) # $EDITOR /etc/conf.d/hwclock
Edit /etc/fstab
to set up system mount points. There are a couple of things to
consider:
-
The preferred format is
UUID=<partition-uuid> <mount-point> <fs-type> <opts> <dump> <pass>
. UUIDs are more reliable that labels or paths. To get partitions UUID, useblkid
tool. -
<dump>
should be 0 most of the time. AFAIK it is a legacy flag for legacy filesystems. -
<pass>
is the order offsck
check at a start time; it should be 0 on BTRFS filesystems becausefsck
should be run on them rarely since they are self-healing. As for other filesystems, the rule is that the root partition should have 1, while all other partitions should have higher numbers. -
<opts>
are the options to pass tomount
; I'd recommend usingnoatime,nodiratime
pair unless you need to keep track of file access times; it will speed things up a bit.
(chroot) # $EDITOR /etc/fstab
Install Necessary Programs
gentoolkit
contains a bunch of handy utilities that allow you to query and
change the Portage system
(chroot) # emerge -av app-portage/gentoolkit
doas
is a lightweight replacement for sudo
(chroot) # emerge -av app-admin/doas
Install system logger
(chroot) # emerge -av app-admin/metalog
(chroot) # rc-update add metalog default
Install cron daemon
(chroot) # emerge -av sys-process/cronie
(chroot) # rc-update add cronie default
Install DHCP client
(chroot) # emerge -av net-misc/dhcpcd
If you're on a system that frequently changes its network settings (e.g. a
laptop connection over a wireless network), I'd suggest using a connection
manager. I prefer connman
(chroot) # emerge -av net-misc/connman
(chroot) # rc-update add connman default
If you're on a system that has fixed network connection (e.g. desktop or server),
then you can simply use netifrc
(chroot) # emerge -av net-misc/netifrc
If you'd like to set up eth0
interface using DHCP at start-up
(chroot) # echo 'config_eth0="dhcp"' >> /etc/conf.d/net
(chroot) # ln -s /etc/init.d/net.lo /etc/init.d/net.eth0
(chroot) # rc-update add net.eth0 default
Install any other utilities you'd like
(chroot) # emerge -av vim tmux mc ...
Configure The Kernel
Install kernel sources and firmware
(chroot) # emerge -av sys-kernel/gentoo-sources sys-kernel/linux-firmware
Install genkernel
tool to build kernel, modules and initrd image
(chroot) # euse -p sys-apps/util-linux -E static-libs
(chroot) # euse -p sys-kernel/genkernel -E cryptsetup
(chroot) # emerge -av sys-kernel/genkernel
Install btrfs-progs for BTRFS support and dosfstools for FAT support
(chroot) # emerge -av sys-fs/btrfs-progs sys-fs/dosfstools
Configure genkernel
(chroot) # $EDITOR /etc/genkernel.conf
-
Set
MENUCONFIG
to use graphical kernel configuration tool -
Set
LVM
,LUKS
andBTRFS
to enable their support in initrd -
Set
FIRMWARE
to copy the firmware into initrd and load it early -
If
genkernel all
on the next step fails to compress initrd image with XZ, switch to another algorithm by changingCOMPRESS_INITRD_TYPE
option.
Configure the kernel
(chroot) # genkernel all
Enable the following options so that you'll be able to start the system from the encrypted partition later
- Device drivers
-> Multiple devices driver support (RAID and LVM)
-> [*] Device mapper support
-> [*] Crypt target support
- Cyptographic API
-> [*] XTS Support
-> [*] SHA224 and SHA256 digest algorithm
-> [*] AES cipher algorithms (x86_64)
-> [*] User-space interface for hash algorithms
-> [*] User-space interface for symmetric key cipher algorithms
Check that the kernel is installed. The output should contain kernel-* and initramfs-* files
(chroot) # ls /boot/
Configure Bootloader
Select GRUB platform if necessary. Use "efi-64" for UEFI and "pc" for BIOS systems
(chroot) # echo 'GRUB_PLATFORMS="efi-64"' >> /etc/portage/make.conf
If you have other OSes, install os-prober
to detect them and generate GRUB
entries
(chroot) # euse -p sys-boot/grub -E mount
(chroot) # emerge -av sys-boot/os-prober
Alternatively, you can install only GRUB itself
(chroot) # emerge -av sys-boot/grub
Install GRUB (UEFI)
(chroot) # mount -o remount,rw /sys/firmware/efi/efivars
(chroot) # grub-install --target=x86_64-efi --efi-directory=/boot/efi
Install GRUB (BIOS)
(chroot) # grub-install /dev/sda
Configure GRUB.
(chroot) # $EDITOR /etc/default/grub
Insert dolvm crypt_root=UUID=<crypt-partition-uuid>
in
GRUB_CMDLINE_LINUX_DEFAULT
to inform GRUB that you're starting system from an
encrypted partition
Compile GRUB configuration
(chroot) # grub-mkconfig -o /boot/grub/grub.cfg
Reboot
Exit the chroot
(chroot) # exit
# cd
Unmount filesystems
# umount -l /mnt/gentoo/dev{/shm,/pts,}
# umount -R /mnt/gentoo
Reboot
# reboot
Welcome to your new Gentoo!
-
Bluetooth subsystem is one example
-
I honestly tried to learn it, and I would probably agree to live with it on a desktop machine where I don't care much about services, but I can't use it for a server where it's crucial. Most of the features implemented in systemd have no use for me there; they only increase the attack surface.
-
To restrict a list of mirrors to a specific country use
-c
flag, e.g.mirrorselect -c Germany ...
-
Additional information about available USE variables you can find in
/usr/portage/profiles/use.desc
-
If you enabled
libressl
USE flag, you'd also need to setCURL_SSL="libressl"
inmake.conf
in order to avoid conflicts later becausecurl
uses OpenSSL backend by default -
It would be also handy to set
VIDEO_CARDS
and/orINPUT_DEVICES
variables in order to decrease the number of packages merged when you install the X11 server -
-avuDN
flags in the line above correspond to--ask
,--verbose
,--update
,--deep
and--newuse