Finished provisioning and installation sections of alpine-server setup.

This commit is contained in:
Luc Bijl 2024-07-07 18:56:25 +02:00
parent 2a4df0dab4
commit 7f039d4f55
3 changed files with 236 additions and 1 deletions

View file

@ -1,3 +1,3 @@
# An Alpine Linux server installation # An Alpine Linux server installation
This is a relatively simple and easy setup for an [Alpine Linux](https://www.alpinelinux.org/) server. Alpine Linux makes a good base for a server because of its simplicity, lightweightness and security. 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/) for server application. With tpm encryption, secureboot, a copy on write filesystem and Podman to handle containers. Alpine Linux makes a good base for a server because of its simplicity, lightweightness and security. Check out the [Alpine Linux wiki](https://wiki.alpinelinux.org/wiki/Main_Page) for additional resources and information.

View file

@ -0,0 +1,162 @@
# Installation
To install the Alpine Linux distribution on the system, the main partition and the efi partition have to be mounted to the main system.
```
# mount -o subvol=@root /dev/mapper/luks /mnt -t btrfs
# mkdir /mnt/efi -p
# mount /dev/<disk>1 /mnt/efi -t vfat
```
Then set up the base system using `setup disk`:
```
# setup-disk -m sys /mnt
```
This will also add grub as bootloader which will be replaced but for now it will reside on the boot partition.
To make it possible to chroot into the system, mount the other directories:
```
# for i in dev proc sys run; do
> mount --rbind --make-rslave /$i /mnt/$i
> done
# chroot /mnt
```
The other setup scripts can be used to configure key aspects of the system. Besides that a few necessary services have to be activated.
```
# setup-hostname <hostname>
# setup-keymap us us-euro
# setup-timezone -i <area>/<subarea>
# setup-ntp openntpd
# rc-update add acpid default
# rc-update add seedrng boot
# rm -rf /var/tmp ; ln -s /tmp /var/tmp
# passwd root
```
> The root password does not really matter because it is going to be locked after a user has been created.
Set the `hwclock` to use `UTC` in `/etc/conf.d/hwclock` and disable writing the time to hardware. Running a NTP negates its usability.
```
clock="UTC"
clock_hctosys="NO"
clock_systohc="NO"
```
Edit `/etc/fstab` for correct mounts:
```
/dev/disk/by-label/efi /efi vfat defaults,nodev,nosuid,noexec 0 2
/dev/disk/by-label/main / btrfs defaults,noatime,subvol=/@root 0 1
/dev/disk/by-label/main /home btrfs defaults,noatime,nosuid,nodev,subvol=/@home 0 2
/dev/disk/by-label/main /var btrfs defaults,nodev,nosuid,noexec,subvol=/@var 0 2
/dev/disk/by-label/main /nix btrfs defaults,noatime,nodev,nosuid,subvol=/@nix 0 2
tmpfs /tmp tmpfs rw,size=4G,nr_inodes=5k,noexec,nodev,nosuid,mode=1777 0 0
proc /proc proc nosuid,nodev,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`.
```
# apk add booster secureboot-hook sbctl
# apk del mkinitfs grub-efi
```
To configure booster edit `/etc/booster.yaml`:
```
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:
```
/sbin/mkinitfs -o "$tmpdir"/initramfs "$NEW_VERSION-$FLAVOR"
```
to:
```
/usr/bin/booster build "$tmpdir"/initramfs --kernel-version "$NEW_VERSION-$FLAVOR"
```
and configure `/etc/kernel-hooks.d/secureboot.conf` for cmdline and secureboot.
```
cmdline="rw rd.luks.name=<uuid>=luks root=/dev/disk/by-label/main rootflags=subvol=/@root quiet splash"
signing_cert="/usr/share/secureboot/keys/db/db.pem"
signing_key="/usr/share/secureboot/keys/db/db.key"
output_dir="/efi/EFI/Linux"
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.
```
# sbctl create-keys
# sbctl enroll-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:
```
# apk fix kernel-hooks
```
and it should give no warnings if done properly.
As discussed earlier `grub` will be replaced, install `gummiboot` as a bootloader.
```
# apk add gummiboot
# gummiboot install --path=/efi
# sbctl sign -s /efi/EFI/gummiboot/gummibootx64.efi
# sbctl sign -s /efi/EFI/Boot/BOOTX64.EFI
```
And also remove some remnants of `grub`.
```
# rm -rf /efi/EFI/alpine
# rm -rf /efi/grub
# rm -rf /etc/default
# cd /boot && unlink boot
```
`gummiboot` can be configured with the file `/efi/loader/loader.conf` with which the timeout and the default OS can be specified.
```
default alpine-linux-lts.efi
timeout 2
editor no
```
Now exit the chroot and you should be able to reboot into a working Alpine system.
```
# exit
# umount -lf /mnt
# reboot
```
When booting up your screen might appear blank, this is the encryption prompt. Enter the encryption key and press enter to boot.
> Do note that "Linux Boot Manager" will have to be set to load first in your bios.

View file

@ -0,0 +1,73 @@
# Provisioning
After flasing the Alpine Linux extended ISO, partition a disk. For this action internet is required since `gptfdisk` is not included on the extended ISO, therefore it needs to be obtained from the repository.
To set it up `setup-interfaces` and `setup-apkrepos` will be used.
```
# setup-interfaces -ar
# setup-apkrepos -c1
```
A few packages will have to be installed first:
```
# apk add cryptsetup lsblk btrfs-progs gptfdisk dosfstools acpid
```
The drive should be partitioned using `gdisk` (or `cfdisk`). It should have at least two partitions with one `EFI System` partition and one `Linux filesystem` partition and look something like this:
| Number of partition | Size | Type |
|:-----:|:-----:|:-----:|
| 1 | 512 MB or more | EFI System |
| 2 | Rest of the drive | Linux filesystem |
Then to create the filesystem on the efi partition.
```
# mkfs.fat -F 32 -n efi /dev/<disk>1
```
The main 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/crypt-key.txt` with:
```
# cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1 > /tmp/crypt-key.txt && cat /tmp/crypt-key.txt
```
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`:
```
# cryptsetup luksFormat /dev/<disk>2 --type luks2 --cipher aes-xts-plain64 --hash sha512 --iter-time 4000 --key-size 512 --pbkdf argon2id --verify-passphrase
[Enter the generated key]
# cryptsetup open --type luks /dev/<disk>2 luks
```
Now to create a btrfs filesystem on the main partition use:
```
# mkfs.btrfs -L main -n 32k /dev/mapper/luks
```
with `-n` the `nodesize`, larger nodesize gives better packing and less fragmentation at the cost of more expensive memory operations while updating metadata blocks. The default is 16k.
The main partition needs to be mounted.
```
# mount /dev/mapper/luks /mnt -t btrfs
```
To create the necessary subvolumes in the main volume:
```
for i in root home var nix; do
> btrfs subvolume create /mnt/@$i
> done
```
Unmount the main partition.
```
# umount -lf /mnt
```