-- Leo's gemini proxy

-- Connecting to jacksonchen666.com:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini;lang=en

Alpine Linux With Encrypted / and /boot but not /boot/efi

2023-08-15 09:37:49Z (last updated 2023-11-21 18:26:47Z)



NOTICE: This document is licensed under CC BY-SA 4.0 because I copied stuff from an Alpine Linux Wiki page. But copyright is weird so I'm not sure if my use could be "fair use" or whatever. I'm doing it anyways.

The page where I copied some commands from.


The encryption scheme I specified in the title leaves the absolute minimum amount of data unencrypted, which will probably only contain the GRUB EFI files.


I have done a similar setup with Arch Linux with a detached LUKS header, but I'm pretty sure I never documented in a blog post, only in a post on my Mastodon account (which is already gone from public view).


Assumptions for this guide:

You know LVM

You know cryptsetup

You know how to make a fstab file

You won't follow this blindly without at least some understanding of the commands

You'll use GRUB with UEFI

You will not use syslinux with BIOS

You're using Alpine Linux (this is an Alpine Linux guide after all)


While the below linked guide works, there are a couple of things I don't like about it. It's the manual setup-alpine procedure part. So I decided to make my own.


Referred guide


Here's the instructions, for a GPT setup, and assuming your disk is /dev/vda:


1. Do setup-alpine normally, but when asked for the disk, directory for storing configs, and apk cache directory, specify "none" for all of them.


2. Run `apk add lvm2 cryptsetup`


3. For partitioning, install your favorite tool. gdisk will be used, which has the package name of "gptfdisk".


4. For filesystems, you'll need the `dosfstools` package (for EFI partition) and whatever package for whatever root filesystem you want. Install those tools. If you don't have a favorite, use `ext4`. Tools are in the package `e2fsprogs`.


5. The partitioning part:


6. Launch your partitioning program


7. Create a 512M (or something smaller) partition for EFI files. For gdisk, that's making the filesystem type "ef00".


8. Create a 512M (maybe not smaller) partition for boot files (kernels, initramfs, GRUB config).


9. Create a big partition (for your root filesystem and swap and everything else).


10. Write your partitioning changes.


11. Run `mkfs.fat -F32 /dev/vda1`


12. For /dev/vda2, the encrypted /boot/, run these commands:


cryptsetup luksFormat --type luks1 /dev/vda2
cryptsetup open /dev/vda2 boot
mkfs.ext4 /dev/mapper/boot

You can choose your own filesystem by replacing the last command with something else.


13. /dev/vda3, where everything else goes


cryptsetup luksFormat /dev/vda3
cryptsetup open /dev/vda3 stuff
pvcreate /dev/mapper/stuff
vgcreate alpine /dev/mapper/stuff
lvcreate -L 4G -n swap alpine
lvcreate -l 100%FREE -n root alpine
mkswap /dev/alpine/swap
mkfs.ext4 /dev/alpine/root

The first `lvcreate` command creates logical volume called `swap` in the `alpine` volume group with 4GiB. The second `lvcreate` command creates logical volume called `root` in the `alpine` volume group taking all the free space.


Last 2 commands formats the swap and root volumes with swap and ext4 respectively. You can choose your own filesystems (at least, for the rootfs).


You can of course adjust all of these parameters if you'd like to.


14. Mounting the filesystem for installation:


mount /dev/alpine/root /mnt/
mkdir /mnt/boot
mount /dev/mapper/boot /mnt/boot/
mkdir /mnt/boot/efi/
mount /dev/vda1 /mnt/boot/efi

Optionally run `swapon /dev/alpine/swap` (that is, after you formatted the volume with mkswap).


If you can't mount (it errors with "invalid argument"), you may need to specify the type of filesystem like `-t ext4`.


15. Installing the system by running `setup-disk -m sys /mnt/`


Installing GRUB will fail. That issue will be fixed later.


16. Chrooting into the system to do stuff. Run all of these commands in order:


mount -t proc /proc /mnt/proc
mount --rbind /dev /mnt/dev
mount --make-rslave /mnt/dev
mount --rbind /sys /mnt/sys
chroot /mnt

Now within the chroot shell, run:

source /etc/profile
export PS1="(chroot) $PS1"

All commands from now on are in the chroot. If you need to enter the the chroot again, repeat this step then continue from where you left off.


17. Creating and adding key files to your LUKS containers


18. To create a key file, you can do something like:


umask 077
dd if=/dev/urandom bs=512 count=4 of=keyfile

That will create a file named "keyfile", which will have 2048 random bytes. I'd recommend renaming it so you know which applies to which, and I'd recommend creating 2 key files for both LUKS containers. I'd also recommend moving the keys into the /etc/ directory of the installed system (not your live system that you booted externally, probably), but that's up to you.


For the rest of the guide, the key file for /dev/vda3 is /etc/root_keyfile.bin and for /dev/vda2, it's /etc/boot_keyfile.bin.


19. To add the key file as way to unlock your LUKS containers:


cryptsetup luksAddKey /dev/vda3 /etc/root_keyfile.bin
cryptsetup luksAddKey /dev/vda2 /etc/boot_keyfile.bin

/dev/vda3 is the LUKS device, and /etc/root_keyfile.bin is the key filename. cryptsetup will ask you for an existing password, which you'll have to enter.


Repeat for whatever /dev/vda2 is to you. (/dev/vda2 is the /boot)


20. Run `apk add grub grub-efi efibootmgr` to get GRUB and the tools


21. Edit the file /etc/default/grub and add these lines:


GRUB_PRELOAD_MODULES="luks cryptodisk part_gpt lvm"
GRUB_ENABLE_CRYPTODISK=y

22. Now check the GRUB_CMDLINE_LINUX_DEFAULT line. Make sure it contains the keywords "cryptroot" and "cryptdm". It should look something like this after you did all the previous steps:


cryptroot=UUID=<UUID> cryptdm=root

Of course, the "<UUID>" would be an actual UUID, but that's pretty much unique for everyone so guessing it is impossible.


You'll need to add "cryptkey" after those arguments.


About those arguments:


cryptroot specifies what is the partition that's going to be decrypted. Because our LUKS container is on /dev/vda3, it should be the UUID of /dev/vda3.


cryptdm sets the mapping name. In our case, it's root. That's equivilent to `cryptsetup open /dev/vda3 root`.


cryptkey probably isn't in your config, but you can specify the file path to a file **within the init filesystem** (AKA initramfs). It's important because it'll unlock the root partition (after unlocking the boot partition containing the keys). You can set this as the same filepath to the keyfile on your root filesystem, but you'll have to copy that path to /etc/mkinitfs/features.d/cryptkey.files.


You can set "cryptdm" to whatever you want, "cryptkey" to a file path of your choosing (it should be the path to the key file for the /dev/vda3 LUKS container), and "cryptroot" is probably already correct.


In my case, I set it to something like this:


cryptroot=UUID=<UUID> cryptdm=root cryptkey=/etc/root_keyfile.bin

23. After saving the /etc/default/grub file, now edit /etc/mkinitfs/features.d/cryptkey.files.


With 1 file path per line, delete all of them and replace with file paths to all of your key files. So the file would look something like this:


/etc/root_keyfile.bin
/etc/boot_keyfile.bin

24. Now edit /etc/mkinitfs/mkinitfs.conf. The "features" line should have at least a "cryptsetup", but probably with "keymap" after it. Move "keymap" before "cryptsetup", and add "cryptkey" after "cryptsetup". So you should have something like this at the end:


features="[...] cryptsetup cryptkey"

25. Now edit /etc/conf.d/dmcrypt. It will be used to unlock the boot LUKS container so that it can be mounted. Here's an example:


# boot
target='boot'
source='/dev/vda2'
key='/etc/boot_keyfile.bin'

"target" is the mapping name. You should already know by now what it means if you read throughly.


For "source", I would use something within /dev/disk/by-uuid/ but UUIDs are not exactly guessable, so it's left to you.


26. Now fill up /etc/fstab. It depends. In my case, I had to switch to using UUIDs for the root partition, and specifying my swap partition. Read the man page if you're lost.


27. Run all of these commands:


grub-install
grub-mkconfig -o /boot/grub/grub.cfg
mkinitfs -c /etc/mkinitfs/mkinitfs.conf -b / <kernel_version>
rc-update add dmcrypt boot

Argument for "<kernel_version>" can be found in /lib/modules/. In my case, I had to use 6.1.45-0-virt.

Mkinitfs reference


This finalizes the bootloader, initramfs, and a service that'll unlock things.


28. Exit the chroot shell by running `exit` or pressing Ctrl-D.


29. Run all of these commands **outside of the chroot** to unmount everything:


cd
umount -l /mnt/dev
umount -l /mnt/proc
umount -l /mnt/sys
umount /mnt/boot/efi
umount /mnt/boot
umount /mnt
swapoff /dev/alpine/swap
vgchange -an
cryptsetup close stuff
cryptsetup close boot

30. Reboot into the new system and hope everything works.


What you should expect:

GRUB asks you for a passphrase

You should be able to select entries

You should be able to boot into the system

You will not be asked for a password/passphrase twice

/boot/ should be mounted


These instructions has been tested, and it works in a virtual machine. If it didn't work for you, you may have screwed something up in the process.


NOTES:

- Key mapping may be incorrect in GRUB, because GRUB has to also handle the password. I'm not sure what to do about that.



Compared to running `setup-disk -e -m sys -L /dev/vda`:

It puts your root filesystem into LVM on LUKS

Swap is part of LVM on LUKS

/boot/ is not encrypted


Partitioning scheme (disk in this case is /dev/vda):

/dev/vda1 will be EFI (/boot/efi/)

/dev/vda2 will be /boot/

/dev/vda3 will be where we throw everything on it, has LUKS encryption


And within /dev/vda3:

LVM layer

A logical volume that will contain / (filesystem: use whatever you want to or ext4 if you don't know)

A logical volume that will be your swap


Could I put all of this in a script? I probably could!


public inbox (comments and discussions)

public inbox archives

(mailing list etiquette for public inbox)

-- Response ended

-- Page fetched on Fri May 10 05:23:01 2024