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

2023-08-15 09:37:49Z (last updated 2024-07-31 03:12:16Z)

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:

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.

  1. Run apk add lvm2 cryptsetup

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

  1. 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.

  1. The partitioning part:

  1. Launch your partitioning program

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

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

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

  1. Write your partitioning changes.

  1. Run mkfs.fat -F32 /dev/vda1

  1. 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.

  1. /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.

  1. 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.

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

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

  1. 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.

  1. Creating and adding key files to your LUKS containers

  1. 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.

  1. 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)

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

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

GRUB_PRELOAD_MODULES="luks cryptodisk part_gpt lvm"
GRUB_ENABLE_CRYPTODISK=y

  1. 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= cryptdm=root

Of course, the "" 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:

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= cryptdm=root cryptkey=/etc/root_keyfile.bin

  1. 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

  1. 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"

  1. 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.

  1. 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.

  1. Run all of these commands:

grub-install
grub-mkconfig -o /boot/grub/grub.cfg
mkinitfs -c /etc/mkinitfs/mkinitfs.conf -b / 
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.

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

  1. 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

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

What you should expect:

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:

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

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

And within /dev/vda3:

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

=> public inbox (comments and discussions) | public inbox archives | (mailing list etiquette for public inbox)

Proxy Information
Original URL
gemini://jacksonchen666.com/posts/2023-08-15/09-37-49/index.gmi
Status Code
Success (20)
Meta
text/gemini;lang=en
Capsule Response Time
134.515039 milliseconds
Gemini-to-HTML Time
3.063645 milliseconds

This content has been proxied by September (ba2dc).