Compare commits
2 commits
main
...
zfs-deskto
Author | SHA1 | Date | |
---|---|---|---|
|
b8e473b64f | ||
|
440a2b9dce |
3 changed files with 97 additions and 83 deletions
|
@ -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.
|
||||||
|
|
|
@ -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.
|
|
|
@ -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
|
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in a new issue