This documents my installation process on my new Dell Precision 5760 laptop, which came factory installed with Dell's Ubuntu 20.04.2 LTS image (kernel 5.10.0-1020-oem).
The main goal is to install my standard Arch Linux desktop environment, along with UEFI Secure Boot and TCG/OPAL self-encrypting drive (SED) on the SSD. I originally purchased the laptop with (due to either confusion or a mis-click) a non self-encrypting Kioxia KXG70ZNV1T02 NVMe SSD. After receiving the laptop and discovering this, I swapped it out for a Samsung 990 Pro 2TB Gen 4 NVMe SSD (MZ-V9P2T0B/AM) from MicroCenter that supports OPAL 2.
Note: I'd originally wanted to use Wayland on this new machine instead of an Xorg server. Unfortunately, the list of Plasma/Wayland Showstoppers - KDE Community Wiki and the fact that SDDM doesn't have released Wayland support yet, is going to keep me on X for a while longer.
Before installing a self-encrypting SSD, make sure to record the PSID from the label on the drive. This is needed for some (e.g. my Samsung 990 Pro) drives to enable encryption, and if you don't record it first, you'll have to open the laptop up again to get the PSID.
- Power up the laptop and boot into the default Ubuntu install, configure it. Do this connected to isolated guest WiFi.
- Test hardware - speakers, mic, webcam, bluetooth (for some reason, scan doesn't show any devices).
- Create a recovery image on USB drive, following How to create a Dell-Ubuntu Image on your Dell PC
- Also download the official Dell hosted recovery image and burn to USB drive: How to recover a Dell-Ubuntu Image on your Dell PC
- Gather information on the configured repositories and factory-installed packages, and magic-wormhole it to my desktop:
sudo su -
mkdir /tmp/data && cd /tmp/data
cp /etc/apt/sources.list . && cp /etc/apt/sources.list.d/* .
apt list --installed > apt-list-installed
apt update
cp /var/lib/apt/lists/oem.archive.canonical.com* .
cp /var/lib/apt/lists/dell* .
for i in oem-fix-misc-cnl-tlp-estar-conf oem-release oem-somerville-factory-meta oem-somerville-factory-stantler-meta oem-somerville-meta oem-somerville-partner-archive-keyring oem-somerville-stantler-meta ubuntu-oem-keyring; do echo $i; apt show $i >> oem-package-info.txt; done
for i in $(dpkg-query -l | grep '^ii' | awk '{print $2}'); do apt-cache madison $i; done | tee packages.txt
apt install magic-wormhole
- Send those to my desktop via
wormhole
- Run the Ubuntu Software app and update everything; we're especially interested in updates to the Dell software and any firmware. Note that running the update seems to trigger Secure Boot errors, which is sort of troubling. Disable Secure Boot for now.
- Ok... I'm pretty sure that the Ubuntu update was trying to update the BIOS ("Dell Firmware") and that is what triggered the Secure Boot failure, but that it was a one-time thing (i.e. update the package in Ubuntu and reboot into the BIOS updater). So, disable Secure Boot and update the BIOS using the USB drive procedure. This updates the BIOS from 1.11.0 to 1.14.0. Reboot into Ubuntu and make sure it still works.
- Reboot and press F12 at the Dell splash screen to enter BIOS setup. We'll set an Admin password (which supposedly unlocks some additional settings) and change some defaults.
- BIOS SETUP -> Passwords -> Admin Password. Set an Admin password. Apply Changes. EXIT and re-enter setup.
- BIOS SETUP -> enter Admin Password
- Boot Configuration -> Boot Sequence -> un-check
UEFI HTTPs Boot
- Boot Configuration -> Secure Boot Mode -> Audit Mode. Should have been set this way from firmware update.
- Storage -> SMART Reporting -> Enable SMART Reporting.
- Connection -> Enable UEFI Network Stack -> Disabled.
- Power -> Battery Configuration -> Standard.
- Power -> USB Wake Support -> Wake on Dell USB-C Dock -> Off.
- Power -> Block Sleep -> Block Sleep -> ON.
- Power -> Lid Switch -> Power On Lid Open -> off.
- Security -> Intel Total Memory Encryption -> ON.
- Update,Recovery -> BIOS Recovery from Hard Drive -> off.
- System Management -> Asset Tag -> set to my email address and hostname of this laptop
- Pre-boot Behavior -> Fastboot -> Thorough
- Pre-boot Behavior -> Extend BIOS POST Time -> 5 seconds
- Pre-boot Behavior -> MAC Address Pass-Through -> Disabled
- Apply changes and exit; allow to boot into Ubuntu.
- Shut down/reboot.
- On a working machine, download the latest Arch Linux install media, verify the checksum and signature, and write it to a USB drive.
- Prepare for setting up the self-encrypting drive (SED) with Secure Boot support per the instructions in Drive-Trust-Alliance/sedutil issue #259: HowTo SecureBoot support
- Create a temporary directory on a computer with
openssl
,efitools
,fatresize
andsbsigntool
. - Generate your Secure Boot signing keys for the new computer:
openssl req -new -x509 -newkey rsa:2048 -sha256 -days 3650 -subj "/CN=Platform Key" -keyout PK.key -out PK.pem -nodes && openssl req -new -x509 -newkey rsa:2048 -sha256 -days 3650 -subj "/CN=Key Exchange Key" -keyout KEK.key -out KEK.pem -nodes && openssl req -new -x509 -newkey rsa:2048 -sha256 -days 3650 -subj "/CN=Image Signing Key" -keyout ISK.key -out ISK.pem -nodes
- Convert the keys to ESL format:
cert-to-efi-sig-list -g "$(uuidgen)" PK.pem PK.esl && cert-to-efi-sig-list -g "$(uuidgen)" KEK.pem KEK.esl && cert-to-efi-sig-list -g "$(uuidgen)" ISK.pem ISK.esl
- In order for UEFI drivers and option ROMS to work, obtain Microsoft's UEFI driver signing CA key and then convert it to a PEM and ESL:
openssl x509 -in MicCorUEFCA2011_2011-06-27.crt -inform DER -out UEFI.pem -outform PEM && cert-to-efi-sig-list -g "$(uuidgen)" UEFI.pem UEFI.esl
- Create db.esl:
cat ISK.esl UEFI.esl > db.esl
- Sign everything (PK by itself, then KEK by PK, then db by KEK):
sign-efi-sig-list -k PK.key -c PK.pem PK PK.esl PK.auth && sign-efi-sig-list -k PK.key -c PK.pem KEK KEK.esl KEK.auth && sign-efi-sig-list -k KEK.key -c KEK.pem db db.esl db.auth
- Download Drive-Trust-Alliance's UEFI64.img.gz (in this case I'm using the 1.20.0 version), gunzip it, and then sign its components:
fdisk -l UEFI64.img
- verify 512-byte sectors and partition start of 2048. If different, adjust the offset belowmount -t msdos -o loop,rw,uid=$(id -u),gid=$(id -g),offset=1048576 UEFI64.img /mnt/temp
cp /mnt/temp/efi/boot/bootx64.efi .
sbsign --key ISK.key --cert ISK.pem bootx64.efi && rm bootx64.efi && mv bootx64.efi.signed bootx64.efi
cp bootx64.efi /mnt/temp/efi/boot/bootx64.efi
- Now we add the fix for Drive-Trust-Alliance/sedutil#404
cp /mnt/temp/efi/boot/syslinux.cfg .
vim syslinux.cfg
and removeacpi=off noapic
cp syslinux.cfg /mnt/temp/efi/boot/syslinux.cfg
sync ; sync ; umount /mnt/temp
rm bootx64.efi
- Write the resulting
UEFI64.img
to a USB flash drive.
- Create a temporary directory on a computer with
- Continue on to the actual SED setup per the Drive-Trust-Alliance wiki:
- Download Drive-Trust-Alliance's RESCUE64.img.gz (in this case I'm using the 1.20.0 version), gunzip it, and write it to a USB flash drive with:
dd bs=4M conv=fsync status=progress oflag=direct if=RESCUE64.img of=/dev/sdX; sync; sync
- Power up, enter BIOS, ensure that SecureBoot is disabled.
- Plug the rescue image USB flash drive in and exit BIOS. On reboot, press F12 for the one-time boot menu, select the UEFI USB 3.0 drive, and enter admin password to boot from it.
- We get a DriveTrust login prompt. Log in as
root
and get dropped into a shell. Plug in the other USB drive andmount /dev/sdb1 /mnt/temp
sedutil-cli --scan
and confirm that the drive is OPAL2 compliant (12
in the second column, indicating OPAL 1.0 and 2.0).linuxpba
and verify that in the output, the drive is listed asis OPAL NOT LOCKED
sedutil-cli --initialsetup debug /dev/nvme0
- this throws an error withmethod status code NOT_AUTHORIZED
andtakeOwnership failed
. this issue seems to indicate that the new Samsung disks are a bit messed up from the factory and sedutil-cli --initialsetup fails with “NOT_AUTHORIZED” on uniniatilized drive when booting with UEFI. · Issue #291 · Drive-Trust-Alliance/sedutil which implies that the drive needs a PSID revert before it can be encrypted.sedutil-cli -–yesIreallywanttoERASEALLmydatausingthePSID <YOURPSID> /dev/nvme0
- this reportsrevertTper completed successfully
sedutil-cli --initialsetup debug /dev/nvme0
- this completes successfully and says initial setup completesedutil-cli --enablelockingrange 0 debug /dev/nvme0
sedutil-cli --setlockingrange 0 lk debug /dev/nvme0
sedutil-cli --setmbrdone off debug /dev/nvme0
- Plug in the other USB drive with our
UEFI64.img
on it,mkdir /mnt/temp && mount /dev/sdb1 /mnt/temp && ls /mnt/temp
sedutil-cli --loadpbaimage debug /mnt/temp/UEFI64.img /dev/nvme0
umount /mnt/temp
sedutil-cli --query /dev/nvme0
- this should report the drive as lockedlinuxpba
and enterdebug
as the passphrase. This should unlock the drive (in the command's own output)- set the real passphrase
sedutil-cli --setsidpassword debug REAL-PASS /dev/nvme0
sedutil-cli --setadmin1pwd debug REAL-PASS /dev/nvme0
sedutil-cli --setmbrdone on REAL-PASS /dev/nvme0
- Hard power-off the laptop by holding down the power button until it shuts off.
- Unplug both USB drives, plug in the Arch install media, and then power the laptop on again. If all goes well, we'll get a Dell splash screen and then the PBA unlock prompt. Enter the password and it will show the drive unlocking and then "Starting OS" and then after a few seconds it will reboot and show the Arch live media bootloader menu. Select "System shutdown" and the system will power off.
- Download Drive-Trust-Alliance's RESCUE64.img.gz (in this case I'm using the 1.20.0 version), gunzip it, and write it to a USB flash drive with:
Beginning from the previous steps, we have the Arch live media in the USB port. Power on, unlock the drive via PBA prompt, boot into the Arch installer.
If not already done, set up a fixed IP lease for a USB-C Ethernet adapter, and set up internal DNS for it (myprecious-wired
). Plug in to the laptop and wired network and turn it on. This ends up booting directly to the Arch installation media without unlocking the drive. Select "System restart" and F12 for the one-time boot menu. Select the UEFI Samsung disk to trigger the PBA, unlock the drive, and then continue into the Arch live installer.
- Install according to the Arch Installation Guide:
- We can skip the keymap setup (ours is US default) and checking boot mode (this laptop only supports UEFI).
ip link
shows our USB ethernet interface has link;ip addr
shows that we have a valid and correct IP.timedatectl status
reports the correct date and time.- Set up for installation over SSH according to Install Arch Linux via SSH - ArchWiki:
passwd
to set a temporary root password in the live environment; assuming you've got a relatively secure LAN, use something easy likefoobarbaz
grep PermitRootLogin /etc/ssh/sshd_config
and ensure it's set toyes
ssh -o StrictHostKeyChecking=no -o "UserKnownHostsFile /dev/null" root@192.168.0.30
and perform the rest of these steps via SSH for easy copy/paste
- Partition the disks:
fdisk -l
reports the 1.82TB Samsung SSD on/dev/nvme0n1
fdisk /dev/nvme0n1
and set up partitions:-
g
to create new GPT partition table -
n
to add partition 1; default start sector of 2048, size+1G
-
t
to change type of partition 1; change to1
,EFI System
-
n
to add partition 2; default start sector, size+70G
-
t
to chanve type of partition 2; change to19
,Linux swap
-
n
to add partiton 3; default start sector, use all available space -
t
to change type of partition 3; change to23
,Linux root (x86-64)
-
p
to verify the partition layout; it should look like this:Disk /dev/nvme0n1: 1.82 TiB, 2000398934016 bytes, 3907029168 sectors Disk model: Samsung SSD 990 PRO 2TB Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: gpt Disk identifier: E4676A78-F194-4A4E-A5D1-F9A330B88555 Device Start End Sectors Size Type /dev/nvme0n1p1 2048 2099199 2097152 1G EFI System /dev/nvme0n1p2 2099200 148899839 146800640 70G Linux swap /dev/nvme0n1p3 148899840 3907028991 3758129152 1.8T Linux root (x86-64)
-
w
to write table to disk
-
- Format the partitions:
mkfs.fat -F 32 /dev/nvme0n1p1
mkswap /dev/nvme0n1p2
mkfs.ext4 /dev/nvme0n1p3
- Mount the partitions:
mount /dev/nvme0n1p3 /mnt
mount --mkdir /dev/nvme0n1p1 /mnt/boot
swapon /dev/nvme0n1p2
less /etc/pacman.d/mirrorlist
- make sure the top 20 look sane- Update the archlinux-keyring in our live environment:
pacman -Sy && pacman -S archlinux-keyring
- Install the minimum required packages, plus the ones we'll need:
pacstrap -K /mnt base linux linux-firmware vim dhcpcd efitools sbsigntools openssl openssh puppet r10k networkmanager intel-ucode efibootmgr lsb-release git
- generate fstab:
genfstab -U /mnt >> /mnt/etc/fstab && cat /mnt/etc/fstab
and make sure it looks right - chroot into the new system:
arch-chroot /mnt
-
set the timezone:
ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
-
hwclock --systohc
-
vim /etc/locale.gen
and uncommenten_US.UTF-8 UTF-8
and then runlocale-gen
-
echo 'LANG=en_US.UTF-8' > /etc/locale.conf
-
set hostname:
echo myprecious > /etc/hostname
-
Enable NetworkManager at boot:
systemctl enable NetworkManager.service
-
Set the root password via
passwd
and store it where I store passwords. -
We'll eventually want to use a unified kernel image with Secure Boot, but for now, we'll just use EFISTUB booting via
efibootmgr
:-
Get auto-UEFI-entry to create the entries:
curl -o /root/aufii https://raw.githubusercontent.com/de-arl/auto-UEFI-entry/1647c60e4b4fe6ab85d87074230f4aef35322991/aufii
-
bash /root/aufii
and answer as appropriate, but abort after it creates the commands and run them manually in the next two steps -
efibootmgr --disk /dev/nvme0n1 --part 1 --create --label "Arch-Fallback" --loader /vmlinuz-linux --unicode 'root=UUID=2d94451b-9dd7-4be3-8475-b2ba420face8 resume=UUID=f4021375-be08-4aea-8538-fef65d4881d7 rw initrd=\intel-ucode.img initrd=\initramfs-linux-fallback.img'
-
efibootmgr --disk /dev/nvme0n1 --part 1 --create --label "Arch" --loader /vmlinuz-linux --unicode 'root=UUID=2d94451b-9dd7-4be3-8475-b2ba420face8 resume=UUID=f4021375-be08-4aea-8538-fef65d4881d7 rw initrd=\intel-ucode.img initrd=\initramfs-linux.img'
-
The output of that second command now becomes:
BootCurrent: 0001 Timeout: 0 seconds BootOrder: 0005,0000,0001,0004,0002,0003 Boot0000* Arch-Fallback HD(1,GPT,0ff51f6d-e5cf-1849-b047-12fb1ad3437d,0x800,0x200000)/File(\vmlinuz-linux)root=UUID=2d94451b-9dd7-4be3-8475-b2ba420face8 resume=UUID=f4021375-be08-4aea-8538-fef65d4881d7 rw initrd=\intel-ucode.img initrd=\initramfs-linux-fallback.img Boot0001* UEFI USB DISK 3.0 071C2A29A51FEB16 PciRoot(0x0)/Pci(0xd,0x0)/USB(4,0)/USB(0,0)/HD(2,MBR,0x9af9df7e,0x191800,0x7800)/File(\EFI\Boot\BootX64.efi)걎脈鼑䵙ⱒ뉙 Boot0002* PEBOOT HD(1,GPT,6324d913-bef4-405b-90ce-2787b3518557,0x800,0x1a9000)/File(\EFI\PEBoot\bootx64.efi) Boot0003* Linux Firmware Updater HD(1,GPT,6324d913-bef4-405b-90ce-2787b3518557,0x800,0x1a9000)/File(\EFI\ubuntu\shimx64.efi) File(.\fwupdx64.efi) Boot0004* UEFI USB DISK 3.0 071C2A29A51FEB16 2 PciRoot(0x0)/Pci(0xd,0x0)/USB(4,0)/USB(0,0)/CDROM(1,0x191800,0x1e000)/File(\EFI\Boot\BootX64.efi)걎脈鼑䵙ⱒ뉙 Boot0005* Arch HD(1,GPT,0ff51f6d-e5cf-1849-b047-12fb1ad3437d,0x800,0x200000)/File(\vmlinuz-linux)root=UUID=2d94451b-9dd7-4be3-8475-b2ba420face8 resume=UUID=f4021375-be08-4aea-8538-fef65d4881d7 rw initrd=\intel-ucode.img initrd=\initramfs-linux.img
-
-
Exit the chroot with
exit
-
- Unmount all partitions with
umount -R /mnt
reboot
to reboot the system
- F12 at the splash screen; enter BIOS Setup, unlock with Admin password, and in Boot Configuration move
PEBOOT
to the top and then after that should be "Arch" and then "Arch-Fallback". Apply changes and exit, and unplug the Arch installer media. - Let the machine boot. If all is well so far we'll boot into the PBA, unlock our drive, and then boot into the new Arch system. Note that just like the live media, we get about 30 seconds of constantly-scrolling
nouveau
errors; we'll deal with that later.- Log in as root.
ip link && ip addr
- we should have DHCP on the wired interface- Start sshd so we can SSH in for the rest:
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config && systemctl start sshd
- SSH in as root again, and log out on the console to keep things simple.
- To keep things sane, edit
init.pp
in my private puppet module to exempt this host from all of my puppet customization (just a single host-specific module), commit and push. - Generate SSH keys for root:
ssh-keygen
cat /root/.ssh/id_rsa.pub
and add that as a deploy key on my private puppet repoecho -e "Host github.com\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n" >> ~/.ssh/config && chmod 0600 ~/.ssh/config
cd /root && git clone https://github.com/jantman/workstation-bootstrap.git && cd workstation-bootstrap
./bin/run_r10k_puppet.sh --noop
and ensure that it's not going to do more than setting up iptables, my user account and group, and the/root/bin
puppet stuff- Run again without the
--noop
- At this point, the rest of installation and configuration (other than actually setting up Secure Boot) is done via puppet (starting at
7d2a48f
in my private puppet repo). First just get some minimal config with my user, dotfiles, sudo, and ssh config. Then we'll move on to Secure Boot setup before we invest time in graphics, GUI, etc. - Finally, before we go any farther, rsync over my home directory from the old laptop.
NOTE: I originally (see git history of this file) tried a number of methods of setting this up, including the ones documented in the Secure Boot article on Arch Wiki based on sbkeysync
and efi-updatevar
. What's shown below is what ended up working.
- Copy the Secure Boot keys and files that were created in Part 2 - Self-Encrypting Drive (SED) Setup to a USB drive that will be stored somewhere secure for the life of the laptop.
- As root, on the laptop, back up the current Secure Boot keys:
mkdir /root/original-efi-keys && cd /root/original-efi-keys && efi-readvar -v PK -o old_PK.esl && efi-readvar -v KEK -o old_KEK.esl && efi-readvar -v db -o old_db.esl && efi-readvar -v dbx -o old_dbx.esl
(note we're told that the PK variable was empty). - Put the USB drive in the laptop; copy the files from step 1 to the laptop and the backups from step 2 to the USB drive.
pacman -S sbupdate-git
in order to have/etc/efi-keys
created- In the directory containing our new SecureBoot keys:
for i in db.* KEK.* PK.*; do install -o root -g root -m 0600 $i /etc/efi-keys/$i; done && install -o root -g root -m 0600 ISK.pem /etc/efi-keys/db.pem && install -o root -g root -m 0600 ISK.key /etc/efi-keys/db.key && ln -s /etc/efi-keys/db.pem /etc/efi-keys/db.crt
- Create the required DER certificates for each:
cd /etc/efi-keys && for i in PK KEK db; do openssl x509 -outform DER -in $i.pem -out $i.cer; done
- Copy
/etc/efi-keys
to the same USB drive we've been using. - Configure
/etc/sbupdate.conf
mainly disablingSPLASH
and setting the kernel command line. - Run puppet again to create/update that config file.
- Run
sbupdate
to generate the initial signed image. This should succeed and create/boot/EFI/Arch/linux-signed.efi
- Add a boot entry for that:
efibootmgr --disk /dev/nvme0n1 --part 1 --create --label "SecureArch" --loader /EFI/Arch/linux-signed.efi --unicode
- Shut down the system (full power down)
- Turn the system back on, unlock the drives, F12 and boot the new "SecureArch" entry. This boots and gives the usual nouveau errors but a working system.
- Ok, let's try enabling Secure Boot. Reboot the machine again and F12. Enter BIOS Setup and unlock and go to the Boot Configuration page.
- Set to Deployed Mode, apply changes.
- DO NOT Delete All Keys.
- DBX, Delete. Apply Changes.
- DB, Replace from file. Select
db.auth
from the USB drive and Submit. Apply changes. - KEK, Replace from file. Select
KEK.auth
from the USB drive and Submit. Apply changes. - PK, Replace from file. Select
PK.auth
from the USB drive and Submit. Apply changes. - Exit. System will reboot.
- We get the PBA to unlock the disks, so that's a really good sign. Unlock the disks. It says it's booting the OS, and then shows a blank screen for a long time.
- Dell splash screen... and then the scrolling nouveau errors that let us know we're booting Arch.
bootctl status
finally shows usSecure Boot: enabled (deployed)
- Ok, we're DONE. All configuration after this point is via puppet.