I'm toying with alpine linux since a while. I am truely impressed by it's slim footprint on the disk. So I have tried it on a Dell Notebook as a "sys" install (everything on disk). Needless to say, it worked like a charm. But how about adding uefi/grub boot and disk encryption? While reading up on available documentation, I came across a detailed post at wejn.org. The author (Michal Jirků?) makes two points:
Now that shell script is full of wonders: using nvme disks; using zfs; using software RAID (mdadm) for the non-zfs parts; and on, all the way to using secure boot with his own keys ... what a ride.
https://wejn.org/2021/01/alpinelinux-secure-boot-with-full-encryption/
This bit really triggered my interest:
There were quite a number of puzzle pieces, which I had been searching before, everything in one place. Fabulous!
So I set out to install alpine linux on a Dell Latitude E6230 with a similar structure:
The commands to achieve this are listed below. It's not strictly a shell script. Be sure to adapt sizes and key material to your liking. I did repeat this installation on another notebook. Everything worked except for the secureboot step. So I tried another notebook (Dell Latitude E7470) and it worked on the first attempt. So either I did some mistake or omission, or that particular UEFI did not successfully replace the keys.
If you try this, don't follow it blindly! I don't want to hear that you bricked your system. Nonetheless, have the appropriate amount of fun!
Thanks to Michal and others for all the documentation!
Cheers,
~ew
# --- the gory details ----------------------------------------------- # boot an alpinelinux installation stick, possibly with uefi enabled # once at the login prompt, login as root # --- install a few more tools apk add e2fsprogs lsblk parted cryptsetup lvm2 iproute2 bash # --- delete old boot block and partition table dd if=/dev/zero of=/dev/sda bs=1M count=20 # --- create new partitions; there might be better ways parted /dev/sda \ mklabel gpt \ mkpart ESP fat32 2048s 256M \ set 1 esp on set 1 boot on \ mkpart BOOT ext2 256M 512M \ mkpart OS ext2 1G 64G \ print partprobe -s /dev/sda # --- Partition 1: Efi System Partition ------------------------------ # format mkfs.vfat -F 32 /dev/sda1 # /boot/efi # --- Partition 2: ext2 for /boot ------------------------------------ # create a key file. This mantra is intented to be used interactively, # hence "echo -n", because in keyfiles, \n will NOT end the input, but # EOF will. echo -n "mai-sikkritt-mantra" > ./p2.mantra chmod 0600 ./p2.mantra # create a crypto_luks1 container on partition 2 (boot) # use luks1 format! cryptsetup luksFormat --type luks1 -d ./p2.mantra /dev/sda2 # open and format cryptsetup open -d ./p2.mantra /dev/sda2 sda2_crypt mkfs.ext2 /dev/mapper/sda2_crypt # --- Partition 3: crypto_luks1, hosting lvm2 ------------------------ # create a keyfile. This mantra is not intented to be used interactively. touch ./crypto_keyfile.bin chmod 0600 ./crypto_keyfile.bin dd bs=512 count=4 if=/dev/urandom of=./crypto_keyfile.bin # format and open crypto_luks1 container cryptsetup luksFormat --type luks1 -d ./crypto_keyfile.bin /dev/sda3 cryptsetup open -d ./crypto_keyfile.bin /dev/sda3 sda3_crypt # use as physical volume in volume group 0 pvcreate /dev/mapper/sda3_crypt vgcreate vg0 /dev/mapper/sda3_crypt # create 3 logical volumes and format them lvcreate -a y -l 2048 -n lvroot vg0 lvcreate -a y -l 2048 -n lvswap vg0 lvcreate -a y -l 2048 -n lvhome vg0 mkfs.ext4 /dev/mapper/vg0-lvroot mkswap /dev/mapper/vg0-lvswap swapon /dev/mapper/vg0-lvswap mkfs.ext4 /dev/mapper/vg0-lvhome # --- mount target tree on /mnt -------------------------------------- mount -t ext4 /dev/mapper/vg0-lvroot /mnt mkdir /mnt/boot mount -t ext2 /dev/mapper/sda2_crypt /mnt/boot mkdir /mnt/boot/efi mount /dev/sda1 /mnt/boot/efi mkdir /mnt/home mount -t ext4 /dev/mapper/vg0-lvhome /mnt/home # copy key files cp -a ./p2.mantra ./crypto_keyfile.bin /mnt/ # --- install alpinelinux on /mnt ------------------------------------ # this part can be automated by creating and editing an "answer file" setup-timezone # UTC setup-alpine -q # us us-altgr-intl setup-sshd # openssh setup-ntp # chrony apk add efibootmgr grub-efi export BOOTLOADER=grub export USE_EFI=1 setup-disk -m sys /mnt # --- now play the chroot trick :-) ---------------------------------- # a number of things need to be configured in the newly # installed system. So we make it functional ... mount -t proc /proc /mnt/proc mount --rbind /dev /mnt/dev mount --make-rslave /mnt/dev mount --rbind /sys /mnt/sys # enter chroot chroot /mnt PS1="(chroot) $PS1" apk add grub grub-efi efibootmgr # probably unneeded apk del syslinux # optional # create a configuration to generate a grub.cfg file blkid /dev/sda3 # get UUID, is used in next step cat <<EOF >/etc/default/grub GRUB_DISTRIBUTOR="Alpine" GRUB_TIMEOUT=5 GRUB_DISABLE_SUBMENU=y GRUB_DISABLE_RECOVERY=true GRUB_DISABLE_OS_PROBER=y GRUB_PRELOAD_MODULES="part_gpt cryptodisk luks ext2" GRUB_ENABLE_CRYPTODISK=y GRUB_DISABLE_LINUX_PARTUUID=true GRUB_DISABLE_LINUX_UUID=true GRUB_CMDLINE_LINUX_DEFAULT="modules=sd-mod,usb-storage,ext4 quiet rootfstype=ext4 cryptroot=UUID=<UUID-OF-sda3> cryptdm=sda3_crypt cryptkey" EOF # generate grub.cfg grub-mkconfig -o /boot/grub/grub.cfg # install grub -> /boot/efi/EFI/alpine/grubx64.efi grub-install --target=x86_64-efi --efi-directory=/boot/efi # generate initramfs; this stage must decrypt sda3, start the # volume group and mount lvroot; therefore a few more features # need to be enabled; cryptkey will include file /crypto_keyfile.bin cat <<EOF >/etc/mkinitfs/mkinitfs.conf features="ata base ide scsi usb virtio ext2 ext4 lvm cryptsetup cryptkey" EOF # refresh initramfs-lts mkinitfs -c /etc/mkinitfs/mkinitfs.conf -b / $(ls /lib/modules/) # enable cryptsetup to open these partitions in the booted system cat <<EOF >> /etc/conf.d/dmcrypt target='sda2_crypt' source='/dev/sda2' key='/p2.mantra' target='sda3_crypt' source='/dev/sda3' key='/crypto_keyfile.bin' # fin EOF # make sda2_crypt available during boot apk add cryptsetup-openrc rc-update add dmcrypt boot rc-update add lvm sysinit # ??? sysvinit or boot? # edit /etc/fstab; "lsblk -f" is your friend cat <<EOF >> /etc/fstab UUID=<UUID-of-sda2_crypt> /boot ext4 rw,relatime 0 2 UUIE=<UUID-of-lvswap> swap swap defaults 0 0 EOF rc-update add swap boot # --- secureboot ----------------------------------------------------- # first a set of properly formatted key,cert files are generated # files: {KEK,PK,db}.{auth,cer,crt,esl,key} apk add efi-mkkeys sbsigntool mkdir /etc/uefi-keys efi-mkkeys -s "Your Name" -o /etc/uefi-keys cp /etc/uefi-keys/*.auth /boot/efi/ # there is a funny error, which can be worked around sed -i 's/SecureBoot/SecureB00t/' /boot/efi/EFI/alpine/grubx64.efi # now we need to sign grub sbsign --key /etc/uefi-keys/db.key --cert /etc/uefi-keys/db.crt /boot/efi/EFI/alpine/grubx64.efi mv /boot/efi/EFI/alpine/grubx64.efi.signed /boot/efi/EFI/alpine/grubx64.efi exit # chroot exited umount -l /mnt/dev umount -l /mnt/proc umount -l /mnt/sys umount /mnt/boot/efi umount /mnt/boot umount /mnt/home umount /mnt swapoff /dev/mapper/vg0-lvswap vgchange -a n cryptsetup close sda3_crypt cryptsetup close sda2_crypt reboot # remove the usb stick # enter UEFI # - enable secure boot # - enable custom key management # - replace keys db KEK PK (apparently order is significant) with the # correspondig *.auth files # - create a uefi boot entry, if not there # - save + exit # # Now booting up should # - show grub asking for the mantra of sda2 # - show the grub.cfg menu # - boot alpine linux and start the system without any further questions # # Time to set a password on UEFI # Time for post-install activities # # Congrats!