Skip to content

Instantly share code, notes, and snippets.

@jvdi
Last active April 1, 2024 19:24
Show Gist options
  • Save jvdi/bdc5066a75b53d8349ac7a73f5510f62 to your computer and use it in GitHub Desktop.
Save jvdi/bdc5066a75b53d8349ac7a73f5510f62 to your computer and use it in GitHub Desktop.
Inatall Arch Linux with secure boot + encrypt (luks2 cryptlvm) partition + unlock lvm encrypt with TPM2 + Dualboot with windows

Arch Linux Install - Introduction

This guide will tell you how to install fully encrypted Arch base system with SecureBoot enabled . This specific guide uses Unified Boot Image for booting and therefore there is no need for software like GRUB.

Check this list before starting!

  • Your computer supports SecureBoot/UEFI
  • Your computer allows for enrollment of your own secureboot keys
  • Your computer does not have manufacturer's backdoors
  • You DO NOT need dualboot with windows You can choose whether you want Microsoft CA when enrolling keys

If you are not interested in SecureBoot, you can just skip last section of this document.

Preparing USB and booting the installer

Download the latest Archlinux ISO and copy it to your USB:

sudo dd if=/path/to/file.iso of=/dev/sdX status=progress
sync

or if you are using windows can download rufus and create a bootable usb (GPT bootable)

Reboot your machine (if enabled => disable secureboot in BIOS) and boot ArchLinux USB.

When your installer has booted, especially on laptop, you may want to enable WiFi connection:

iwctl
station list
station wlan0 connect SSID (or station wlan0 connect-hidden SSID)
<password prompt>
exit

then if not get ip, run:

# Run this command for get ip
dhcpcd

# check net
ping -c3 archlinux.org

Disk partitioning

See your disk status:

# to get list of partition and structure of it

lsblk

Following example assumes you have a nvme drive (/dev/nvme0nX). Your drive may as well report as (/dev/sdX).

You can use your favoruite tool, that supports creating the GPT partiton, for example cfdisk:

# change nvme0nX with your disk data (get from lsblk)
cfdisk /dev/nvme0nX

and then choose gpt partiton table and create something like this:

+----------------------+----------------------+----------------------+
| /dev/nvme0n1p1       |   /dev/nvme0n1p2 (encrypted using LUKS2)    |
| 1024 MB              |                  68 GB                      |
+----------------------+---------------------------------------------+
| EFI Boot Partition   |         LVM          |        LVM           |
|                      |                      |                      |
| /boot/efi            |          /           |       [Swap]         |
|                      |                      |                      |
|                      |     /dev/vg/root     |     /dev/vg/swap     |
|                      |                      |                      |
| 1024 MB              |         60 GB        |        8 GB          |
+----------------------+----------------------+----------------------+
  • So we need to EFI partitions (if already installed windows or etc... - or you have efi partiton befor it => dont need to recreate or format it just mount it)
  • for root partiton Create ext4 partiton
  • and creat a SWAP pariton
  • at the end => choose Write from bottom menu to save your change (Carefull !!!)

Format:

# EFI -> (if already installed windows or etc... - or you have efi partiton befor it => dont need to recreate or format it just mount it)
mkfs.fat -F32 /dev/nvme0n1p1

# Encrypted DISK for (root and swap)
cryptsetup luksFormat --type luks2 /dev/nvme0n1p2

Now we can create encrypted volume and open it (--perf options are optional and recommended for SSD):

cryptsetup open --perf-no_read_workqueue --perf-no_write_workqueue --persistent /dev/nvme0n1p2 cryptlvm

Configuring LVM and formatting root partition:

pvcreate /dev/mapper/cryptlvm

vgcreate vg /dev/mapper/cryptlvm

# Create 60 GB space for root
lvcreate -L 60G vg -n root

# Use another space for SWAP (68 - 60 = 8 GB)
lvcreate -l 100%FREE vg -n swap

# format root
mkfs.ext4 /dev/vg/root

# Create swap
mkswap /dev/vg/swap

After all is done we need to mount our drives:

# root
mount /dev/vg/root /mnt

# swap
swapon /dev/vg/swap

# boot
mkdir -p /mnt/boot/efi
mount /dev/nvme0n1p1 /mnt/boot/efi

Now for see result

Run:

lsblk

For best performance in download speed from arch repo

  • go to mirror list file and set best arch repo at first - example:
  • add : Best Repo for IRAN - copy one of them and set it in the first repo in this file
nano /etc/pacman.d/mirrorlist

System bootstraping

In the next step it is recommended to install CPU microcode package. Depending on whether you have intel of amd you should apend intel-ucode or amd-ucode to your pacstrap

My pacstrap presents as follows:

pacstrap -K /mnt base linux linux-firmware YOUR_UCODE_PACKAGE sudo nano lvm2 dracut sbsigntools iwd git efibootmgr binutils dhcpcd

Generate fstab:

genfstab -U /mnt >> /mnt/etc/fstab

Optional Step

  • For esay-write script in arch (In real installation we not have option for copy paste script so copy all script file to a usb flash drive and mount it after generate fstab)
  • Create this files in usb flash drive
usb2
|
├── cmdline.conf
├── flags.conf
├── secureboot.conf
├── dracut-install.sh
├── dracut-remove.sh
├── 60-dracut-remove.hook
├── 90-dracut-install.hook
└── zz-sbctl.hook

  • !!!(files content is in the bellow)!!!

  • Connect the usb flash drive to computer and run:

# Check place of usb => SdaX or SdbX etc ...
lsblk

# mount usb2 to /usb2 folder
mount /dev/sdbX /mnt/usb2 --mkdir

Now you can chroot to your system and perform some basic configuration:

arch-chroot /mnt

Set the root password:

passwd

My Optional suggestion is to also install man for additional help you may require:

# manual for package Ex. -> man ls
pacman -Syu man-db

Set timezone and generate /etc/adjtime:

ln -sf /usr/share/zoneinfo/<Region>/<city> /etc/localtime
hwclock --systohc

Set your desired locale:

# at /etc/locale.gen -> uncomment locales you want
# with ctrl+w search for locales ex. en_US and remove -> # sign at first it's line
nano /etc/locale.gen

Configure your keyboard (Optional) layout (mine is adapted to polish-programmer keyboard):

nano /etc/vconsole.conf

KEYMAP=pl
FONT=Lat2-Terminus16
FONT_MAP=8859-2

Run locale-gen for generate locales

Set your hostname:

nano /etc/hostname
# Write a name for your computer at this file and close it

Create your user:

useradd --create-home YOUR_NAME
passwd YOUR_NAME

Add your user to sudo:

# add to sudo user
usermod --append --groups wheel YOUR_NAME

# Config sudo
EDITOR=nano visudo
	
%wheel	ALL=(ALL) ALL # Uncomment this line

Enable some systemd units:

# if you want system auto connect to wireless network at startup
systemctl enable iwd
# if you want system auto get ip at startup
systemctl enable dhcpcd

Creating Unified Kernel Image and configuring boot entry

Create dracut scripts that will hook into pacman:

nano /usr/local/bin/dracut-install.sh # copy this file to usb2

Write:

#!/usr/bin/env bash

mkdir -p /boot/efi/EFI/Linux
 
while read -r line; do
	if [[ "$line" == 'usr/lib/modules/'+([^/])'/pkgbase' ]]; then
		kver="${line#'usr/lib/modules/'}"
		kver="${kver%'/pkgbase'}"
		
		dracut --force --uefi --kver "$kver" /boot/efi/EFI/Linux/bootx64.efi
	fi
done

And the removal script:

nano /usr/local/bin/dracut-remove.sh # copy this file to usb2

#!/usr/bin/env bash
rm -f /boot/efi/EFI/Linux/bootx64.efi

Make those scripts executable and create pacman's hook directory:

chmod +x /usr/local/bin/dracut-*
mkdir /etc/pacman.d/hooks

Now the actual hooks, first for the install and upgrade:

nano /etc/pacman.d/hooks/90-dracut-install.hook # copy this file to usb2
[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Target = usr/lib/modules/*/pkgbase
		
[Action]
Description = Updating linux EFI image
When = PostTransaction
Exec = /usr/local/bin/dracut-install.sh
Depends = dracut
NeedsTargets

And for removal:

nano /etc/pacman.d/hooks/60-dracut-remove.hook # copy this file to usb2
[Trigger]
Type = Path
Operation = Remove
Target = usr/lib/modules/*/pkgbase

[Action]
Description = Removing linux EFI image
When = PreTransaction
Exec = /usr/local/bin/dracut-remove.sh
NeedsTargets

Check UUID of your encrypted volume and write it to file you will edit next:

# if you wnat copy this file from usb => first copy it and then run this command:
blkid -s UUID -o value /dev/nvme0n1p2 >> /etc/dracut.conf.d/cmdline.conf 
# and replace YOUR_UUID in this file with end line at this file (contain a code)

Edit the file and fill with with kernel arguments:

nano /etc/dracut.conf.d/cmdline.conf # copy this file to usb2
kernel_cmdline="rd.luks.uuid=luks-YOUR_UUID rd.lvm.lv=vg/root rd.lvm.lv=vg/swap resume=/dev/mapper/vg-swap root=/dev/mapper/vg-root rootfstype=ext4 rootflags=rw,relatime"

Create file with flags:

nano /etc/dracut.conf.d/flags.conf # copy this file to usb2
compress="zstd"
hostonly="no"

Generate your image by re-installing linux package and making sure the hooks work properly:

pacman -S linux

You should have bootx64.efi within your /boot/efi/EFI/Linux/

Now you only have to add UEFI boot entry and create an order of booting:

efibootmgr # to see your status of boot
# Create boot entry for arch
efibootmgr --create --disk /dev/nvme0n1 --label "Arch Linux" --loader 'EFI\Linux\bootx64.efi' --unicode
efibootmgr 		# Check if you have left over UEFI entries, remove them with efibootmgr -b INDEX -B and note down Arch index
efibootmgr -o ARCH_INDEX_FROM_PREVIOUS_COMMAND # 0 or whatever number your Arch entry shows as

Now you can reboot and log into your system. (if not boot to arch you can boot from usb againg and just open encrypted device and mount your created partiton and run arch-chroot for troubleshooting and check files and scripts)

❗ ❗ ❗ Compatilibity thing I noticed ❗ ❗ ❗

Some (older?) platforms can ignore entries by efibootmgr all together and just look for EFI\BOOT\bootx64.efi, in that case you may generate your UKI directly to that directory and under that name. It's very important that the name is also bootx64.efi.

SecureBoot

At this point you should enable Setup Mode for SecureBoot in your BIOS, and erase your existing keys (it may spare you setting attributes for efi vars in OS). If your system does not offer reverting to default keys (useful if you want to install windows later), you should backup them, though this will not be described here.

Configuring SecureBoot is easy with sbctl:

pacman -S sbctl

Check your status, setup mode should be enabled (You can do that in BIOS):

sbctl status
  Installed:      ✘ Sbctl is not installed
  Setup Mode:     ✘ Enabled
  Secure Boot:    ✘ Disabled

Create keys and sign binaries:

sbctl create-keys
sbctl sign -s /boot/efi/EFI/Linux/bootx64.efi #it should be single file with name verying from kernel version

Configure dracut to know where are signing keys:

nano /etc/dracut.conf.d/secureboot.conf # copy this file to usb2
uefi_secureboot_cert="/usr/share/secureboot/keys/db/db.pem"
uefi_secureboot_key="/usr/share/secureboot/keys/db/db.key"

We also need to fix sbctl's pacman hook. Creating the following file will overshadow the real one:

nano /etc/pacman.d/hooks/zz-sbctl.hook # copy this file to usb2
[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Operation = Remove
Target = boot/*
Target = efi/*
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/initcpio/*
Target = usr/lib/**/efi/*.efi*

[Action]
Description = Signing EFI binaries...
When = PostTransaction
Exec = /usr/bin/sbctl sign /boot/efi/EFI/Linux/bootx64.efi

Enroll previously generated keys (drop microsoft option if you don't want their keys - Ex. Usage: dual booting):

sbctl enroll-keys --microsoft

Reboot the system. Enable only UEFI boot and Secure boot in BIOS and set BIOS password so anyone won't simply turn off the setting. If everything went fine you should first of all, boot into your system, and then verify with sbctl or bootctl:

sbctl status
  Installed:	✓ sbctl is installed
  Owner GUID:	YOUR_GUID
  Setup Mode:	✓ Disabled
  Secure Boot:	✓ Enabled

Enroll LUKS key in TPM 🤩 - Optional but fascination

if you wnat your computer boot without password (just with your config) do:

# Install tpm2-tools:
pacman -S tpm2-tools

Enroll your LUKS volume to tpm, simply run the following command as root:

# Select 0 or 1 or 2 or ... - My suggestin 1 < YOUR_REG_NUMBER
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+1+2+3+4+5+7+8 /dev/nvme0n1p2

or if you wnat remove your key, run this command:

systemd-cryptenroll --wipe-slot=tpm2 /dev/nvme0n1p2

You will need to add a kernel argument for enable the TPM2 bits

open:

nano /etc/dracut.conf.d/cmdline.conf

and change to:

kernel_cmdline="rd.luks.options=YOUR_UUID=tpm2-device=auto rd.luks.uuid=luks-YOUR_UUID rd.lvm.lv=vg/root rd.lvm.lv=vg/swap resume=/dev/mapper/vg-swap root=/dev/mapper/vg-root rootfstype=ext4 rootflags=rw,relatime"

Ensure that dracut builds in the TPM2 libraries. Create:

nano /etc/dracut.conf.d/tpm2-tss.conf

write:

add_dracutmodules+=" tpm2-tss "

Finally, rebuild your unified kernel image:

# Run for auto
pacman -S linux
# Mybe not neeed bellow command (Because this create a other xxxx.efi boot file) - Manually create
ls /lib/modules # for check kver
dracut --force --uefi --kver "YOUR_KEY_VER" /boot/efi/EFI/Linux/bootx64.efi

Additionally, A useful script to have handy for when you change UEFI settings to reenroll your LUKS key under the different PCR values is as follows:

nano /bin/luks_reenroll_tpm

write:

systemd-cryptenroll --wipe-slot=tpm2 /dev/disk/by-uuid/UUID_HERE
# Select 0 or 1 or 2 or ... - My suggestin 1 < YOUR_REG_NUMBER
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+1+2+3+4+5+7+8 /dev/disk/by-uuid/UUID_HERE

At the end - you have a Compter with enabled Secure boot and encrypted drive

When need passphrase at boot

The goal here is to only require the passphrase when something spooky happens in your boot path.

UEFI settings change? Request password.

Some weird swap of some module of UEFI code that lives on your motherboard somewhere? Request password.

Unified Kernel Image changes? Don't even boot.

Drive in another computer? Request password.

The only time the drive should unlock is when it's in the right computer with the right configuration and the right signed unified kernel image with the right kernel arguments. If your Xorg server just auto logs in and opens a terminal well...don't do that.

Thanks from

Ataraxxia for secure-arch

Krin for TPM2 unlocking

this gist just a fork (copy this file from github to gist) wtih some additonal setting and edit and ... for my usage

if you want continue and install sway UI and some app and customaization go to secure-arch

Thank you for reading this gist and i'm sorry about my english grammer (if it's)

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