Compare commits

...

2 commits

Author SHA1 Message Date
nils
b8e473b64f Removed raid mention 2024-10-27 12:14:09 +01:00
Nils
440a2b9dce Yes 2024-10-27 12:04:30 +01:00
3 changed files with 97 additions and 83 deletions

View file

@ -1,5 +1,5 @@
# An Alpine Linux desktop installation # An Alpine Linux desktop installation
This guide will demonstrate how to install [Alpine Linux](https://www.alpinelinux.org/) with encryption, secureboot and a graphical wayland session using wayfire. Alpine Linux makes a perfect base for those who want a minimal, simple and secure Linux installation. This installation will also make use of [Nix](https://nixos.org/) and [Home-manager](https://github.com/nix-community/home-manager) which allows for easy deployment and user independent packages. Check out the [Alpine Linux wiki](https://wiki.alpinelinux.org/wiki/Main_Page) for additional resources and information. This guide will demonstrate how to install [Alpine Linux](https://www.alpinelinux.org/) with encryption, secureboot and a graphical wayland session using wayfire. Alpine Linux makes a perfect base for those who want a minimal, simple and secure Linux installation. Check out the [Alpine Linux wiki](https://wiki.alpinelinux.org/wiki/Main_Page) for additional resources and information.
> Note that all this documentation is focused on the `x86_64` architecture. > Note that all this documentation is focused on the `x86_64` architecture.

View file

@ -1,26 +1,41 @@
# Installation # Installation
To install the Alpine Linux distribution on the system, the alpine root partition and the EFI partition have to be mounted to the main system. To install the Alpine Linux distribution on the system, the datasets of the system pool and the EFI partitions have to be mounted to the main system.
First import and decrypt the system pool.
```
# zpool import -N -R /mnt tank
# zfs load-key tank
```
Mount the datasets in the system pool and decrypt the home dataset.
```
# mount tank/root/alpine /mnt -t zfs -o noatime
# zfs mount tank/home
# zfs mount tank/var
```
Mount the ESP.
``` ```
# mount /dev/vg/alpine_root /mnt -t ext4
# mkdir /mnt/esp # mkdir /mnt/esp
# mount /dev/disk/by-label/esp /mnt/esp -t vfat # mount /dev/disk/by-label/esp /mnt/esp -t vfat
``` ```
Then install Alpine Linux using `setup disk` Then install Alpine Linux.
``` ```
# export BOOTLOADER=none
# setup-disk -m sys /mnt # setup-disk -m sys /mnt
``` ```
> This will also add `grub` as bootloader which will be replaced but for now it will reside on the ESP. To have a functional chroot into the system, bind the system process directories.
To have a functional chroot into the system, bind the system process directories
``` ```
# for i in dev proc sys run; do # for dir in dev proc sys run; do
> mount --rbind --make-rslave /$i /mnt/$i > mount --rbind --make-rslave /$dir /mnt/$dir
> done > done
# chroot /mnt # chroot /mnt
``` ```
@ -33,7 +48,6 @@ The other setup scripts can be used to configure key aspects of the system. Besi
# setup-timezone -i <area>/<subarea> # setup-timezone -i <area>/<subarea>
# setup-ntp openntpd # setup-ntp openntpd
# rc-update add acpid default # rc-update add acpid default
# rc-update add lvm boot
# rc-update add seedrng boot # rc-update add seedrng boot
# rm -rf /var/tmp # rm -rf /var/tmp
# ln -s /tmp /var/tmp # ln -s /tmp /var/tmp
@ -50,49 +64,38 @@ clock_hctosys="NO"
clock_systohc="NO" clock_systohc="NO"
``` ```
Edit `/etc/fstab` for correct mounts Configure ZFS to mount.
``` ```
/dev/disk/by-label/esp /esp vfat defaults,nodev,nosuid,noexec 0 2 rc-update add zfs-import sysinit
/dev/vg/alpine_root / ext4 defaults,noatime 0 1 rc-update add zfs-mount sysinit
/dev/vg/home /home ext4 defaults,noatime,nodev,nosuid 0 2
/dev/vg/var /var ext4 defaults,nodev,nosuid,noexec 0 2
/dev/vg/nix /nix ext4 defaults,noatime,nodev,nosuid 0 2
tmpfs /tmp tmpfs rw,size=4G,nr_inodes=5k,nodev,nosuid,noexec,mode=1777 0 0
proc /proc proc nodev,nosuid,noexec,hidepid=2 0 0
``` ```
By default, Alpine Linux uses `mkinitfs` to create an initial ram filesystem, although it is minimal that also means that it lacks some functionality which is needed for a proper setup. Because of this `mkinitfs` and `grub-efi `will be replaced with `booster` and `secureboot-hook`. Edit `/etc/fstab` for correct mounts:
``` ```
# apk add booster secureboot-hook sbctl tank/root/alpine / zfs rw,noatime,xattr,posixacl,casesensitive 0 1
# apk del mkinitfs grub-efi /dev/disk/by-label/esp /esp vfat defaults,nodev,nosuid,noexec 0 2
tmpfs /tmp tmpfs rw,nodev,nosuid,noexec,mode=1777 0 0
proc /proc proc nodev,nosuid,noexec,hidepid=2 0 0
``` ```
To configure booster edit `/etc/booster.yaml`: By default, Alpine Linux uses `mkinitfs` to create an initial ram filesystem.
``` ```
enable_lvm: true # apk add secureboot-hook sbctl
busybox: false
modules: vfat,nls_cp437,nls_iso8859_1
``` ```
The most important step is the creation of a UKI using `secureboot-hook` which also automatically signs them. First the hook itself will have to be tweaked to use `booster` instead of `mkinitfs`, edit `/etc/kernel-hooks.d/50-secureboot.hook` and change the line: Configure `/etc/mkinitfs/mkinitfs.conf` to disable it's hook:
``` ```
/sbin/mkinitfs -o "$tmpdir"/initramfs "$NEW_VERSION-$FLAVOR" # echo 'disable_trigger=yes' >> /etc/mkinitfs/mkinitfs.conf
``` ```
to: The most important step is the creation of a UKI using `secureboot-hook` which also automatically signs them. Configure `/etc/kernel-hooks.d/secureboot.conf` for cmdline and secureboot.
``` ```
/usr/bin/booster build "$tmpdir"/initramfs --kernel-version "$NEW_VERSION-$FLAVOR" cmdline="rw root=ZFS=tank/root/alpine quiet splash"
```
and configure `/etc/kernel-hooks.d/secureboot.conf` for cmdline and secureboot.
```
cmdline="rw rd.luks.name=<uuid>=luks rd.lvm.vg=vg root=/dev/vg/alpine_root modules=ext4 quiet splash"
signing_cert="/usr/share/secureboot/keys/db/db.pem" signing_cert="/usr/share/secureboot/keys/db/db.pem"
signing_key="/usr/share/secureboot/keys/db/db.key" signing_key="/usr/share/secureboot/keys/db/db.key"
@ -101,12 +104,6 @@ output_dir="/esp/efi/linux"
output_name="alpine-linux-{flavor}.efi" output_name="alpine-linux-{flavor}.efi"
``` ```
Here `<uuid>` has to be replaced with the UUID of the partition which contains the volume group:
```
# blkid /dev/<disk>2 >> /etc/kernel-hooks.d/secureboot.conf
```
Use `sbctl` to create secureboot keys and sign them. Use `sbctl` to create secureboot keys and sign them.
``` ```
@ -116,7 +113,13 @@ Use `sbctl` to create secureboot keys and sign them.
> Whilst enrolling the keys it might be necessary to add the `--microsoft` flag if you are unable to use custom keys. > Whilst enrolling the keys it might be necessary to add the `--microsoft` flag if you are unable to use custom keys.
Now to see if everything went succesfully run: Set the cache-file of the ZFS pool.
```
# zpool set cachefile=/etc/zfs/zpool.cache tank
```
Now to see if everything went successfully, run:
``` ```
# apk fix kernel-hooks # apk fix kernel-hooks
@ -124,7 +127,7 @@ Now to see if everything went succesfully run:
and it should give no warnings if done properly. and it should give no warnings if done properly.
As discussed earlier `grub` will be replaced, install `gummiboot` as a bootloader. To install `gummiboot` as friendly bootloader:
``` ```
# apk add gummiboot # apk add gummiboot
@ -133,28 +136,28 @@ As discussed earlier `grub` will be replaced, install `gummiboot` as a bootloade
# cp /usr/lib/gummiboot/gummibootx64.efi /esp/efi/boot/bootx64.efi # cp /usr/lib/gummiboot/gummibootx64.efi /esp/efi/boot/bootx64.efi
``` ```
Sign the bootloader with `sbctl` Sign the bootloader with `sbctl`.
``` ```
# sbctl sign -s /esp/efi/boot/bootx64.efi # sbctl sign -s /esp/efi/boot/bootx64.efi
``` ```
and also remove some remnants of `grub`. > One may verify the signed files by running `sbctl verify`, in this case `ESP_PATH=/esp` should be defined to work properly.
```
# rm -rf /boot/grub
# rm -rf /etc/default
# cd /boot && unlink boot && cd ..
```
`gummiboot` can be configured with the file `/esp/loader/loader.conf` with which the timeout and the default OS can be specified. `gummiboot` can be configured with the file `/esp/loader/loader.conf` with which the timeout and the default OS can be specified.
``` ```
default alpine-linux-<flavor>.efi default alpine-linux-lts.efi
timeout 2 timeout 5
editor no editor no
``` ```
> Here, there should be lines explaining the setup of automatic decryption with TPM using Clevis. Which is still in development...
```
# clevis encrypt tpm2 '{}' << ''
```
Before finishing the installation `networkmanager` will be installed for networking. Also install `networkmanager-wifi` and `wpa_supplicant` for Wi-Fi functionality. Before finishing the installation `networkmanager` will be installed for networking. Also install `networkmanager-wifi` and `wpa_supplicant` for Wi-Fi functionality.
``` ```
@ -163,16 +166,15 @@ Before finishing the installation `networkmanager` will be installed for network
# rc-update add networkmanager default # rc-update add networkmanager default
``` ```
Wi-Fi will not yet work. For Wi-Fi configuration see the [network section](post-install/network). Wi-Fi will not yet work. For Wi-Fi configuration see the network section.
> If internet does not work after reboot create the config file as described in the [network section](post-install/network) and restart the service. > If internet does not work after reboot create the config file as described in the network section and restart the service.
Now exit the chroot and you should be able to reboot into a working Alpine system. Now exit the chroot and you should be able to reboot into a working Alpine system.
``` ```
# exit # exit
# umount -lf /mnt # umount -lf /mnt
# zpool export tank
# reboot # reboot
``` ```
When booting up your screen might appear blank, this is the encryption prompt. Enter the encryption key and press enter to boot.

View file

@ -9,15 +9,24 @@ To set it up `setup-interfaces` and `setup-apkrepos` will be used.
# setup-apkrepos -c1 # setup-apkrepos -c1
``` ```
> To use wifi simply run `setup-interfaces -r` and select `wlan0` or similar.
A few packages will have to be installed first: A few packages will have to be installed first:
``` ```
# apk add e2fsprogs cryptsetup lvm2 lsblk sgdisk wipefs dosfstools acpid # apk add zfs lsblk sgdisk wipefs dosfstools acpid
```
and load the ZFS kernel module
```
# modprobe zfs
``` ```
Wipe the existing disk partitions Wipe the existing disk partitions
``` ```
# zpool labelclear -f /dev/<disk>
# wipefs -a /dev/<disk> # wipefs -a /dev/<disk>
# sgdisk --zap-all /dev/<disk> # sgdisk --zap-all /dev/<disk>
``` ```
@ -41,45 +50,48 @@ Then, format the ESP with a FAT32 filesystem
# mkfs.fat -F 32 -n esp /dev/<disk>1 # mkfs.fat -F 32 -n esp /dev/<disk>1
``` ```
## Volume group creation ## ZFS pool creation
The root partition of the system is going to be encrypted using `cryptsetup`. First generate a key that will be used to encrypt the device and save it temporarily to the file `/tmp/luks.key` with: The ZFS system pool is going to be encrypted. First generate an encryption key and save it temporarily to the file `/tmp/tank.key` with:
``` ```
# cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1 > /tmp/luks.key && cat /tmp/luks.key # cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1 > /tmp/tank.key && cat /tmp/tank.key
``` ```
> Later on in the guide `clevis` will be used for automatic decryption. So, this key only has to be entered a few times. However, if any changes are made to the BIOS or secure-boot then this key will be needed again, so make sure to write it down. > Later on in the guide `clevis` will be used for automatic decryption, so this key only has to be entered a few times. However, if any changes are made to the bios or secureboot then this key will be needed again, so make sure to write it down.
Then format the partition using `cryptsetup`: Create the system pool:
``` ```
# cryptsetup luksFormat /dev/<disk>2 --type luks2 --cipher aes-xts-plain64 --hash sha512 --iter-time 4000 --key-size 512 --pbkdf argon2id # zpool create -f \
[Enter the generated key] -o ashift=12 \
# cryptsetup open --type luks /dev/<disk2> luks -O canmount=off \
-O compression=lz4 \
-O acltype=posix \
-O xattr=sa \
-O dnodesize=auto \
-O atime=off \
-O normalization=formD \
-O encryption=on \
-O keyformat=passphrase \
-O keylocation=prompt \
-m none \
tank /dev/<disk2>
``` ```
Create the LVM volume group Then create the system datasets:
``` ```
# vgcreate vg /dev/mapper/luks # zfs create -o mountpoint=none tank/root
# zfs create -o mountpoint=legacy -o quota=24g tank/root/alpine
# zfs create -o mountpoint=/home -o setuid=off -o devices=off -o quota=<home-quota> tank/home
# zfs create -o mountpoint=/var -o exec=off -o setuid=off -o devices=off -o quota=16g tank/var
``` ```
Then create partitions inside the volume group: > Setting the `<home-quota>` depends on the total size of the pool, generally try to reserve some empty space in the pool.
Finally, export the zpool:
``` ```
# lvcreate --name alpine_root -L 24G vg # zpool export tank
# lvcreate --name home -L <home-quota> vg
# lvcreate --name var -L 16G vg
# lvcreate --name nix -L 32G vg
```
> Setting the `<home-quota>` depends on the total size of the volume group, generally try to reserve some empty space in the volume group.
Create the filesystems on the logical partitions:
```
for i in alpine_root home var nix; do
> mkfs.ext4 /dev/vg/$i
> done
``` ```