Skip to content

Instantly share code, notes, and snippets.

@gmpreussner
Last active March 23, 2023 09:31
Show Gist options
  • Save gmpreussner/2965fd1b388113a0b33b32a4641a2221 to your computer and use it in GitHub Desktop.
Save gmpreussner/2965fd1b388113a0b33b32a4641a2221 to your computer and use it in GitHub Desktop.
Minimal instructions for installing a fully encrypted ArchLinux with USB boot on Lenovo Yoga 920.
# Install a fully encrypted ArchLinux on NVMe with detached LUKS
# headers and LUKS encrypted UEFI boot partition on a USB dongle.
#
# Full tutorial can be found here:
# https://headcrash.industries/reference/fully-encrypted-archlinux-with-secure-boot-on-yoga-920/
#
# Written by Gerke Max Preussner <[email protected]>
# Overview ############################################################
# Fully encrypted system drive with Btrfs file system
# Encrypted kernel, ramdisk images and bootloader configuration
# Two-factor authentication via detached LUKS header on USB dongle
# Encrypted swap space
# Secure boot enabled
# Prerequisites #######################################################
# Two USB sticks: one for the installer, one that will become the boot dongle
# Download and install the ArchLinux ISO on a USB stick (https://wiki.archlinux.org/index.php/Category:Getting_and_installing_Arch)
# If you have only one stick available, consider Archboot (https://wiki.archlinux.org/index.php/archboot)
# On Windows you can use Rufus to install the ISO (https://rufus.akeo.ie/)
# You can also boot from external CD/DVD or via Netboot
# Booting the Installer from USB ######################################
# 1. Power off laptop
# 2. Push a pin into the small hole next to power button
# 3. Select "BIOS Setup"
# 4. Navigate to "Security" page
# 5. Toggle "Secure Boot" option to "Disabled"
# 6. Save changes and exit BIOS Setup
# 7. Hold power button for 5 sec to turn off laptop
# 8. Insert ArchLinux USB installer
# 9. Push a pin into the small hole next to power button
# 10. Select "Boot Menu"
# 11. Select USB device to boot from
# 12. Wait for ArchLinux installer to boot up
# 13. Insert second USB stick
# set a bigger font
setfont sun12x22
# verify that installer is /dev/sda and dongle is /dev/sdb
lsblk
# Wireless Network Setup ##############################################
# make sure wireless adapter is detected (i.e. wlp107s0)
iw dev
# unblock and enable wireless interface
rfkill unblock all
ip link set wlp107s0 up
# optional: scan for wireless networks if needed
iw dev wlp107s0 scan | less
# connect to wireless network YourSSID with password YourKey
wpa_supplicant -i wlp107s0 -c <(wpa_passphrase "YourSSID" "YourKey") -B
# start DHCP client daemon to receive IP address
dhcpcd wlp107s0
# Verify Network Connectivity #########################################
# ping internet (Ctrl+C to exit)
ping archlinux.org
# synchronize clock
timedatectl set-ntp true
# Preparing the USB Dongle ############################################
# create three partitions on USB dongle
cgdisk /dev/sdb
# Size: 100M, Hex Code: ef00, Name: ESP
# Size: 512M, Hex Code: default (8300), Name: Boot
# Size: default (remaining space), Hex Code: default (8300), Name: Storage
#
# Select "Write" and "Quit" when done
# format ESP
mkfs.fat -F32 /dev/sdb1
# create encrypted container for /boot
cryptsetup luksFormat /dev/sdb2
cryptsetup open /dev/sdb2 cryptboot
# create and mount boot filesystem
mkfs.ext2 /dev/mapper/cryptboot
mount /dev/mapper/cryptboot /mnt
# optional: format storage partition
mkfs.fat -F32 /dev/sdb3
# Preparing the System Drive ##########################################
# Backup existing files or partitions if needed
# WARNING: the following command will discard all data on the SSD!
blkdiscard /dev/nvme0n1
# Encrypting the System Drive #########################################
# create and open encrypted container with detached LUKS header
truncate -s 2M /mnt/luksheader
cryptsetup luksFormat /dev/nvme0n1 --align-payload 4096 --header /mnt/luksheader
cryptsetup open --type luks --header /mnt/luksheader /dev/nvme0n1 cryptroot
# verify container was opened and mapped (/dev/mapper/cryptboot, /dev/mapper/cryptroot)
fdisk -l
# unmount boot partition
umount /mnt
# create Btrfs volume group
pvcreate /dev/mapper/cryptroot
vgcreate System /dev/mapper/cryptroot
# create logical volumes
lvcreate -L 8G System -n swap
lvcreate -l 100%FREE System -n root
# format logical volumes
mkswap /dev/mapper/System-swap
swapon -d /dev/mapper/System-swap
mkfs.btrfs /dev/mapper/System-root
mount /dev/mapper/System-root /mnt
# Root File System Setup ##############################################
# create Btrfs subvolumes
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@snapshots
# unmount system partition
umount /mnt
# mount Btrfs subvolumes
mount -o compress=lzo,discard,noatime,nodiratime,subvol=@ /dev/mapper/System-root /mnt
mkdir /mnt/home
mkdir /mnt/.snapshots
mount -o compress=lzo,discard,noatime,nodiratime,subvol=@home /dev/mapper/System-root /mnt/home
mount -o compress=lzo,discard,noatime,nodiratime,subvol=@snapshots /dev/mapper/System-root /mnt/.snapshots
# create nested subvolumes for special folders
mkdir -p /mnt/var/cache/pacman
btrfs subvolume create /mnt/var/cache/pacman/pkg
btrfs subvolume create /mnt/var/log
btrfs subvolume create /mnt/var/tmp
# mount /boot and ESP into root
mkdir /mnt/boot
mount /dev/mapper/cryptboot /mnt/boot
mkdir /mnt/boot/efi
mount /dev/sdb1 /mnt/boot/efi
# ArchLinux Installation ##############################################
# optional: select your preferred package server
nano /etc/pacman.d/mirrorlist
# install base packages
pacstrap /mnt base btrfs-progs efibootmgr grub-efi-x86_64 intel-ucode
# generate fstab
genfstab -Up /mnt >> /mnt/etc/fstab
# optional: add ramdisk tmp
#
# add the line:
# tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
#
# Ctrl+X and 'y' and 'Enter' to save and exit nano
nano /mnt/etc/fstab
# verify fstab
cat /mnt/etc/fstab
UUID=... / btrfs rw,noatime,nodiratime,compress=lzo,ssd,discard,space_cache,subvolid=257,subvol=/@,subvol=@ 0 0
UUID=... /home btrfs rw,noatime,nodiratime,compress=lzo,ssd,discard,space_cache,subvolid=258,subvol=/@home,subvol=@home 0 0
UUID=... /.snapshots btrfs rw,noatime,nodiratime,compress=lzo,ssd,discard,space_cache,subvolid=259,subvo=/@snapshots,subvol=@snapshots 0 0
UUID=... /none swap defaults 0 0
UUID=... /boot ext2 noauto,rw,relatime,block_validity,barrier,user_xattr,acl 0 2
UUID=... /boot/efi vfat noauto,rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 2
tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
# add boot partition to crypttab (replace <identifier> with UUID from 'blkid /dev/sda2')
nano /mnt/etc/crypttab
cryptboot UUID=<identifier> none noauto,luks
# change into installation root
arch-chroot /mnt
# Initial Ramdisk Configuration #######################################
# make copies of 'encrypt' hook files
cp /lib/initcpio/hooks/encrypt{,2}
cp /usr/lib/initcpio/install/encrypt{,2}
# add detached LUKS header support to 'encrypt2' hook
nano /lib/initcpio/hooks/encrypt2
# make the following modifications:
# ...
# warn_deprecated() {
# echo "The syntax 'root=${root}' where '${root}' is an encrypted volume is deprecated"
# echo "Use 'cryptdevice=${root}:root root=/dev/mapper/root' instead."
# }
#
#>>> local headerFlag=false
# for cryptopt in ${cryptoptions//,/ }; do
# case ${cryptopt} in
# allow-discards)
# cryptargs="${cryptargs} --allow-discards"
# ;;
#>>> header)
#>>> cryptargs="${cryptargs} --header /boot/luksheader"
#>>> headerFlag=true
#>>> ;;
# *)
# echo "Encryption option '${cryptopt}' not known, ignoring." >&2
# ;;
# esac
# done
#
# if resolved=$(resolve_device "${cryptdev}" ${rootdelay}); then
#>>> if $headerFlag || cryptsetup isLuks ${resolved} >/dev/null 2>&1; then
# [ ${DEPRECATED_CRYPT} -eq 1 ] && warn_deprecated
# dopassphrase=1
# add modules, binaries, files and hooks to mkinitcpio.conf
nano /etc/mkinitcpio.conf
...
MODULES=(btrfs i915 loop)
...
BINARIES=(/usr/bin/btrfs)
...
FILES=(/boot/luksheader)
...
HOOKS=(base ... keyboard keymap ... block ... encrypt2 lvm2 ... filesystems ...)
# generate initial ramdisk image
mkinitcpio -p linux
# Bootloader Installation #############################################
# get NVMe device identifier (remember as YourDiskId)
ls -l /dev/disk/by-id | grep nvme0n1
# change Grub defaults (replace YourDiskId)
nano /etc/default/grub
GRUB_CMDLINE_LINUX="cryptdevice=/dev/disk/by-id/YourDiskId:cryptroot:allow-discards,header"
GRUB_PRELOAD_MODULES="part_gpt part_msdos lvm"
GRUB_ENABLE_CRYPTODISK=y
GRUB_GFXMODE=1024x768x32
# configure and install Grub
grub-mkconfig -o /boot/grub/grub.cfg
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id="grub"
# System Configuration ################################################
# set time zone and configure hardware clock
ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
hwclock --systohc --utc
# uncomment desired localizations
nano /etc/locale.gen
# generate localization settings
locale-gen
echo LANGUAGE=en_US >> /etc/locale.conf
echo LANG=en_US.UTF-8 >> /etc/locale.conf
# set host name
echo myyoga920 > /etc/hostname
nano /etc/hosts
(add the following line)
...
127.0.0.1 myyoga920.localdomain myyoga920
# End of file
# update packages, install wireless & bash completion
pacman -Suy iw wpa_supplicant bash-completion
# add new user account
useradd -m -g users -G wheel,storage,power -s /bin/bash your_new_user_name
passwd your_new_user_name
# install and enable sudo
pacman -S sudo
EDITOR=nano visudo
uncomment the following line
%wheel ALL=(ALL) ALL
# disable root account
passwd -l root
# reboot
exit
umount -R /mnt
swapoff -a
reboot
# Secure Boot #########################################################
# 1. Enter a strong Administrator Password in BIOS Setup
# 2. Perform 'Reset to Setup Mode' in BIOS Setup
# install git client
sudo pacman -S base-devel git
# clone, build and install cryptboot
git clone https://github.com/xmikos/cryptboot
cd cryptboot
makepkg -si --skipchecksums
# mount boot partition, and create & enroll UEFI keys
sudo cryptboot mount
sudo cryptboot-efikeys create
sudo cryptboot-efikeys enroll
sudo cryptboot update-grub
sudo cryptboot umount
sudo shutdown -P now
# 3. Enable Secure Boot in BIOS Setup
# Post-install steps ##################################################
# install, configure and enable Snapper
sudo pacman -S snapper
sudo umount /.snapshots
sudo rm -r /.snapshots
sudo snapper -c root create-config /
sudo mount -o compression=lzo,discard,noatime,nodiratime,subvol=@snapshots /dev/mapper/System-root /.snapshots
sudo systemctl start snapper-timeline.timer
# install & configure Gnome
sudo pacman -S gnome
sudo localectl set-locale LANG=en_US.UTF-8
sudo echo LC_ALL= >> /etc/locale.conf
# install & enable NetworkManager
sudo pacman -S networkmanager
sudo systemctl enable --now NetworkManager.service
sudo nano /etc/NetworkManager/NetworkManager.conf
[ifupdown]
managed=true
# install & enable power management
sudo pacman -S tlp x86_energy_perf_policy
sudo systemctl enable tlp.service
sudo systemctl enable tlp-sleep.service
sudo pacman -S tlp-rdw
sudo systemctl enable NetworkManager-dispatcher.service
sudo systemctl mask systemd-rfkill.service
sudo systemctl mask systemd-rfkill.socket
# fire up Gnome Desktop Manager
sudo systemctl enable --now gdm.service
# Yoga Specifics ######################################################
# blacklist ideapad_laptop module
sudo nano /etc/modprobe.d/blacklist.conf
install ideapad_laptop /bin/false
# enable bluetooth
sudo systemctl enable --now bluetooth.service
# End #################################################################
For instructions on how to resume a previous installation, disable TRIM,
auto-mount boot and auto-unlock root partitions, please see the full article at:
https://headcrash.industries/reference/fully-encrypted-archlinux-with-secure-boot-on-yoga-920/
@hackabean
Copy link

Hey I am following your tutorial and I was wondering if you have made a mistake in line 200:

add boot partition to crypttab (replace with UUID from 'blkid /dev/sda2')

Shouldn't there be sdb2 ?

I have finished my setup to the line 319. Sadly grub does not recognize my encrypted USB as a valid file system. Is secure boot option necessary to make it work ? Thank you kindly for all the hard work you put into this.

@gmpreussner
Copy link
Author

Hello hackabean, secure boot is not required, but recommended. The crypttab entry is for the encrypted partition on the main drive, not the boot partition on the USB stick. The main drive should be mounted as sda, while the USB drive is mounted as sdb. The Yoga BIOS comes with a preloaded configuration for Windows secure boot. You might have to reset the configuration and disable Secure Boot. Check my full tutorial for details.

@hackabean
Copy link

hackabean commented Sep 8, 2019

Hey, thanks for the reply. I have just finished the setup. Everything works as it is supposed to now, even with secure boot. In my case I added boot device UUID to crypttab and it works (although I might need to change it in the future). I have seen your full tutorial, without it, I wouldn't be able to learn so much and accomplish this magnificent project. I appreciate you sharing your insights. It was very clear and easy to follow. One thing to note though if you are planning to make another install like that in the future. Recent Arch ISO has updated cryptsetup to version 2.2.0 which means by default it is using Luks2, that means the encrypted USB partition will not be recognized by GRUB. I struggled with this bit for few days until I read the manual on Arch wiki. source: https://wiki.archlinux.org/index.php/GRUB#Encrypted_/boot

@ProfessorStrawberry
Copy link

ProfessorStrawberry commented Apr 12, 2020

I have trouble booting after the first reboot. Grub says Error: no such device: xxxxx-xxxx-xxxx-xxxx-xxxxx.

# add boot partition to crypttab (replace <identifier> with UUID from 'blkid /dev/sda2')
nano /mnt/etc/crypttab
cryptboot    UUID=<identifier>    none    noauto,luks

You said, the nvme is supposed to be mounted at /dev/sda? Shouldn't that be /dev/nvme0n1?
Oh and as of 01/2020 grub supports luks2. Is there any chance, you could update your instructions for that use case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment