notesassorted ramblings on computer

Alpine Linux Installation with LUKS2

This is a guide for installing Alpine Linux Edge with full disk encryption using LUKS2, GPT partitions (with legacy boot) and BTRFS.

Steps

  1. Fetch an ISO for the latest release from AlpineLinux.org
    • An alternative would be creating your own ISO using the alpine-edge profile of alpine-conf
  2. Boot Alpine Linux and as root with the password ‘root’
  3. Configure your installation environment.
  4. Upgrade all installed packages to version form Edge.
  5. Configure the package manager and upgrade packages to Edge
  6. Partition the disk.
  7. Create a LUKS2 container.
  8. Create the file systems.
  9. Install and configure Alpine.

Installation environment configuration

  1. Optionally setup a different keymap using setup-keymap
  2. Set a hostname using setup-hostname
  3. Configure network interfaces using setup-interfaces
  4. Up your configured network interfaces using ifup

Upgrade to Edge

In order to upgrade to Alpine Linux Edge we first of all need to configure Alpine’s package manager APK:

  1. Choose a mirror using setup-apkrepos
  2. Select the Edge repositories in /etc/apk/repositories:
    • Only select the Edge version of the community, main and testing repostories, disable all other repositories.

Now we can upgrade all installed packages using apk upgrade -U -a. Keep in mind that this won’t properly upgrade the Linux kernel since this would require a reboot. If you (for some reasons) need a newer version of the Kernel than the one available in the current release to install Alpine Linux on your hardware you need to create a custom ISO.

Partitioning the disk

In order to partition the disk we need a tool which allows us to create these partitions. You might use busybox fdisk to create MBR partitions but I personally prefer gptfdisk for creating GPT partitions, it can be installed using: apk add gptfdisk.

After you picked your partition tool you need to determine the device path of the disk you want to partition. This can be done using fdisk -l | grep ^Disk:.

Now we can create our partition in this guide the following partitions will be created:

  1. A partition with the size 512M for an unencrypted /boot
  2. A swap partition with the size 8G for an encrypted swap.
  3. A partition for LUKS using all remaining available space.

The following commands are performed to create these partitions:

# gdisk /dev/sda
GPT fdisk (gdisk) version 1.0.3

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): n
Partition number (1-128, default 1): 1
Last sector (2048-3907029134, default = 3907029134) or {+-}size{KMGTP}: +512M
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help): n
First sector (34-3907029134, default = 1050624) or {+-}size{KMGTP}:
Last sector (1050624-3907029134, default = 3907029134) or {+-}size{KMGTP}: +8G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8309
Changed type of partition to 'Linux LUKS'

Command (? for help): n
Partition number (3-128, default 3): 
First sector (34-3907029134, default = 17827840) or {+-}size{KMGTP}: 
Last sector (17827840-3907029134, default = 3907029134) or {+-}size{KMGTP}: 
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8309
Changed type of partition to 'Linux LUKS'

After creating these partition we also need to set the ‘legacy BIOS bootable’ flag on our /boot partition. This can be done with gdisk using the following commands:

Command (? for help): x

Expert command (? for help): a
Partition number (1-3): 1
Known attributes are:
0: system partition
1: hide from EFI
2: legacy BIOS bootable
60: read-only
62: hidden
63: do not automount

Attribute value is 0000000000000000. Set fields are:
  No fields set

Toggle which attribute field (0-63, 64 or <Enter> to exit):
Have enabled the 'legacy BIOS bootable' attribute.
Attribute value is 0000000000000004. Set fields are:
2 (legacy BIOS bootable)

After invoking these command partitions your partition table should roughly look like this:

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   8300  Linux filesystem
   2         1050624        17827839   8.0 GiB     8309  Linux LUKS
   3        17827840      3907029134   1.8 TiB     8309  Linux LUKS

If that’s the case write your GPT partition table to the disk and quit your Partitioning tool.

Create a LUKS2 container

In order to create a LUKS2 container the cryptsetup utility needs to be installed, this can be done using: apk add cryptsetup. With this utility we can now create a LUKS2 container on our third partition using the following commands:

# cryptsetup luksFormat --type luks2 /dev/sda3
WARNING!
========
This will overwrite data on /dev/sda3 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase for /dev/sda3:
Verify passphrase:
WARNING: Locking directory /run/cryptsetup is missing!

You can ignore the warning, cryptsetup will create this directory for us if it doesn’t exist yet. After creating the LUKS2 container it needs to be opened using: cryptsetup open --type luks2 /dev/sda3 root.

File system creation

Next up we need to create some file system. We are going to be using ext2 for our /boot partition and Btrfs for our root file system. In order to create these file systems two additional tools need to be installed using: apk add e2fsprogs btrfs-progs.

The file system can then be created using the following commands:

# mkfs.ext2 /dev/sda1 
mke2fs 1.43.8 (1-Jan-2018)
Creating filesystem with 131072 4k blocks and 32768 inodes
Filesystem UUID: f9b1fbe3-e86e-44f2-ad9e-271a70d0e7ff
Superblock backups stored on blocks: 
	32768, 98304

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done
# mkfs.btrfs /dev/mapper/root
btrfs-progs v4.14
See http://btrfs.wiki.kernel.org for more information.

Label:              (null)
UUID:               b0a71438-b36a-489e-84fd-d126748b67e2
Node size:          16384
Sector size:        4096
Filesystem size:    1.81TiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP               1.00GiB
  System:           DUP               8.00MiB
SSD detected:       no
Incompat features:  extref, skinny-metadata
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1     1.81TiB  /dev/mapper/root

Mounting the file systems

The file system need to be mounted at a mountpoint, where are going to use /mnt for that. To mount the ext2 and btrfs file systems invoke the following commands:

# mount -t btrfs /dev/mapper/root /mnt/
# mkdir /mnt/boot
# mount -t ext2 /dev/sda1 /mnt/boot

Additionally I always like to create various subvolumes when using Btrfs. Normally I create the following subvolumes:

# btrfs subvolume create /mnt/home
Create subvolume '/mnt/home'
# btrfs subvolume create /mnt/var
Create subvolume '/mnt/var'
# btrfs subvolume create /mnt/var/log
Create subvolume '/mnt/var/log'
# btrfs subvolume create /mnt/var/tmp
Create subvolume '/mnt/var/tmp'

Install and configure Alpine

Now Alpine needs to be installed on the given mountpoint. The basic installation can be done using:

# BOOTLOADER=syslinux setup-disk -m sys /mnt/

Depending on the quality and speed of your internet connection this might take a while. The script will emit a warning in this step that the MBR needs to be fixed manually, we will do this later on.

After Alpine has been installed on the mountpoint we need to make sure that initramfs and bootloader are configured correctly. Otherwise the system will not boot properly. I also highly recommend editing /mnt/etc/fstab at this point and including appropriate mount options.

The initramfs needs to be configured in order to include the files and kernel modules required by the cryptsetup utility to decrypt our LUKS2 container. Since our root filesystem uses Btrfs we also need the appropriate Kernel modules to mount it from the initramfs. Therefore the configuration file /mnt/etc/mkinitfs/mkinitfs.conf should roughly look like this:

features="ata base scsi usb btrfs cryptsetup"

In addition to that we need to tell the initramfs which devices contains the LUKS2 container. This is done using a kernel parameter. In order to modify the kernel parameters we need to edit the bootloader configuration. This can be done by editing /mnt/etc/update-extlinux.conf. The default_kernel_opts variable in that file should contain the following items:

default_kernel_opts="cryptroot=/dev/sda3 cryptdm=root"

Next up we need to rebuild the initramfs and bootloader configurations this can be done with the following commands:

# mkinitfs -c /mnt/etc/mkinitfs/mkinitfs.conf -b /mnt/ $(ls -1 /mnt/lib/modules/)
==> initramfs: creating /mnt/boot/initramfs-hardened
# chroot /mnt/ update-extlinux -v 2>/dev/null
Updating extlinux configuration.
Found kernel: /boot/vmlinuz-hardened
Found initramfs: /boot/initramfs-hardened
1 entries found.
Installing libutil.c32 libcom32.c32 mboot.c32 menu.c32 vesamenu.c32 to /boot.

The (almost) final step is writing the MBR mentioned early. This can be done using dd(1):

# dd bs=440 conv=notrunc count=1 if=/mnt/usr/share/syslinux/gptmbr.bin of=/dev/sda
1+0 records in
1+0 records out

Finally the last steps are setting a root password, unmounting the file system and rebooting your computer. Those steps can be performed with the following commands:

# chroot /mnt passwd root
Changing password for root
New password:
Retype password:
passwd: password for root changed by root
# umount /mnt/boot/ /mnt/
# cryptsetup luksClose /dev/mapper/root
# reboot