Compare commits
5 commits
866d57e144
...
9d1328a863
Author | SHA1 | Date | |
---|---|---|---|
9d1328a863 | |||
28f2727ffa | |||
b8775e8116 | |||
db6c437353 | |||
a7ebacbeb2 |
5 changed files with 618 additions and 28 deletions
|
@ -1,3 +1,3 @@
|
|||
# Ampel Blog
|
||||
|
||||
This is the repository containing the files for the [blog](https://blog.ampel.dev) of the Ampel organisation.
|
||||
This is the repository containing the [mkdocs](https://www.mkdocs.org) files for the [blog](https://blog.ampel.dev) of the Ampel organisation.
|
||||
|
|
|
@ -12,7 +12,7 @@ categories:
|
|||
- Base installation
|
||||
---
|
||||
|
||||
This blog entry will demonstrate how to install a `luks` encrypted `x86_64` [Void Linux](https://voidlinux.org/) `musl` operating system on a `ext4` filesystem. This entry is based on the [Void Handbook](https://docs.voidlinux.org/about/index.html) and the [Void man pages](https://man.voidlinux.org/man-pages.7).
|
||||
This blog entry will demonstrate how to install a `luks` encrypted `x86_64` [Void Linux](https://voidlinux.org/) `musl`/`UEFI signed UKI` operating system on a `ext4` filesystem. This entry is based on the [Void Handbook](https://docs.voidlinux.org/about/index.html) and the [Void man pages](https://man.voidlinux.org/man-pages.7).
|
||||
|
||||
<!-- more -->
|
||||
|
||||
|
@ -48,7 +48,7 @@ sh# mkfs.ext4 -L root /dev/mapper/root
|
|||
|
||||
## Installation
|
||||
|
||||
To install Void Linux `musl` on the system, the ESP and LFP have to be mounted to the live (ISO) environment:
|
||||
To install Void Linux on the system, the ESP and LFP have to be mounted to the live (ISO) environment:
|
||||
|
||||
``` shell-session
|
||||
sh# mount -t ext4 /dev/mapper/root /mnt
|
||||
|
@ -148,7 +148,7 @@ and set the directory where the UKI will be deposited:
|
|||
UEFI_BUNDLE_DIR="/efi/EFI/Linux"
|
||||
```
|
||||
|
||||
Create and enroll the secureboot keys into the system
|
||||
Create and enroll the secureboot keys into the system:
|
||||
|
||||
``` shell-session
|
||||
sh# sbctl create-keys
|
||||
|
|
503
docs/desktop-os/posts/02-gentoo-openrc-install.md
Normal file
503
docs/desktop-os/posts/02-gentoo-openrc-install.md
Normal file
|
@ -0,0 +1,503 @@
|
|||
---
|
||||
title: A hardened Gentoo-Linux/openrc base installation
|
||||
slug: gentoo-openrc-base-install
|
||||
date: 2025-07-19
|
||||
draft: true
|
||||
authors:
|
||||
- nils
|
||||
- luc
|
||||
tags:
|
||||
- Gentoo Linux
|
||||
categories:
|
||||
- Base installation
|
||||
---
|
||||
|
||||
This blog entry will demonstrate how to install a hardened `x86_64` [Gentoo Linux](https://www.gentoo.org/) `musl`/`openrc`/`UEFI signed UKI` operating system on an encrypted `ZFS` pool with automatic decryption using TPM. This entry is based on the [Gentoo `x86_64` handbook](https://wiki.gentoo.org/wiki/Handbook:AMD64) and the [Gentoo wiki](https://wiki.gentoo.org/wiki/Main_Page). Gentoo supplies the right tools to build a Linux operating system from scratch, suited to the hardware and needs of the user. This form of customizability and optimizability together with the strong community behind Gentoo makes it a good choice for a desktop operating system.
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## Provisioning
|
||||
|
||||
To install Gentoo this guide will be using the [Alpine Extended ISO](https://alpinelinux.org/downloads/). It provides all of the necessary utilities for bootstrapping Gentoo. Make sure to boot with secureboot in setup mode or to already have keys ready to deploy.
|
||||
|
||||
After booting the Alpine Linux extended ISO, partition the disks. For this action internet is required since `zfs`, `sgdisk` and various other necessary packages are not included on the extended ISO, therefore they need to be obtained from the Alpine package repository.
|
||||
|
||||
Set it up with `setup-interfaces` and `setup-apkrepos`:
|
||||
|
||||
``` shell-session
|
||||
sh# setup-interfaces -ar #(1)!
|
||||
sh# setup-apkrepos -c1
|
||||
```
|
||||
|
||||
1. To use Wi-Fi simply run `setup-interfaces -r` and select `wlan0` or similar.
|
||||
|
||||
Install the necessary packages:
|
||||
|
||||
``` shell-session
|
||||
sh# apk add zfs lsblk sgdisk wipefs dosfstools zlevis #(1)!
|
||||
```
|
||||
|
||||
1. The `zlevis` package is as of this moment not yet in the alpine package repository. Try to get it into the `bin` via a different method and add its dependencies `tpm2-tools` and `jose`.
|
||||
|
||||
and load the `ZFS` kernel module:
|
||||
|
||||
``` shell-session
|
||||
sh# modprobe zfs
|
||||
```
|
||||
|
||||
Wipe the existing disk partitions:
|
||||
|
||||
``` shell-session
|
||||
sh# zpool labelclear -f /dev/<disk>
|
||||
sh# wipefs -a /dev/<disk>
|
||||
sh# sgdisk --zap-all /dev/<disk>
|
||||
```
|
||||
|
||||
Create on the disk an `EFI system` partition (ESP) and a `Linux filesystem` partition (LFP):
|
||||
|
||||
``` shell-session
|
||||
sh# sgdisk -n 1:1m:+512m -t 1:ef00 /dev/<disk>
|
||||
sh# sgdisk -n 2:0:-10m -t 2:8300 /dev/<disk>
|
||||
```
|
||||
|
||||
Reload the device nodes:
|
||||
|
||||
``` shell-session
|
||||
sh# mdev -s
|
||||
```
|
||||
|
||||
Format the ESP with a FAT32 filesystem:
|
||||
|
||||
``` shell-session
|
||||
sh# mkfs.fat -F 32 -n esp /dev/<disk>1
|
||||
```
|
||||
|
||||
## ZFS pool creation
|
||||
|
||||
The `ZFS` system pool is going to be encrypted. First generate an encryption key and save it temporarily to the file `/tmp/rpool.key` with:
|
||||
|
||||
``` shell-session
|
||||
sh# cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1 > /tmp/rpool.key && cat /tmp/rpool.key
|
||||
```
|
||||
|
||||
> All the while we use `zlevis` for automatic decryption, this key is required when making changes are made to the BIOS or secureboot, so make sure to save it.
|
||||
|
||||
Create the system pool:
|
||||
|
||||
``` shell-session
|
||||
sh# zpool create -f \
|
||||
-o ashift=12 \
|
||||
-O compression=lz4 \
|
||||
-O acltype=posix \
|
||||
-O xattr=sa \
|
||||
-O dnodesize=auto \
|
||||
-O encryption=on \
|
||||
-O keyformat=passphrase \
|
||||
-O keylocation=prompt \
|
||||
-m none \
|
||||
rpool /dev/<disk>2
|
||||
```
|
||||
|
||||
Then create the system datasets:
|
||||
|
||||
``` shell-session
|
||||
sh# zfs create -o mountpoint=none rpool/root
|
||||
sh# zfs create -o mountpoint=legacy -o quota=48g rpool/root/gentoo
|
||||
sh# zfs create -o mountpoint=legacy -o quota=32g rpool/root/gentoo/var
|
||||
sh# zfs create -o mountpoint=/home -o atime=off -o setuid=off -o devices=off -o quota=<home-quota> rpool/home
|
||||
```
|
||||
|
||||
> Setting the `<home-quota>` depends on the total size of the pool, generally try to reserve some empty space in the pool.
|
||||
|
||||
Write the encryption key to TPM with `zlevis`:
|
||||
|
||||
``` shell-session
|
||||
sh# zlevis encrypt rpool '{}' < /tmp/rpool.key
|
||||
```
|
||||
|
||||
> We are using the default configuration settings for `zlevis encrypt` but a different configuration is possible by setting `'{}'` accordingly.
|
||||
|
||||
<break>
|
||||
|
||||
> To check if it worked, perform `zlevis decrypt rpool`.
|
||||
|
||||
Finally, export the zpool:
|
||||
|
||||
``` shell-session
|
||||
sh# zpool export rpool
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
To install Gentoo Linux on the system, the ESP and the datasets of the system pool have to be mounted to the live (ISO) environment.
|
||||
|
||||
First import and decrypt the system pool:
|
||||
|
||||
``` shell-session
|
||||
sh# zpool import -N -R /mnt rpool
|
||||
sh# zfs load-key -L file:///tmp/rpool.key rpool
|
||||
```
|
||||
|
||||
Then mount the datasets and the ESP on `/mnt`:
|
||||
|
||||
``` shell-session
|
||||
sh# mount -t zfs rpool/root/gentoo /mnt
|
||||
sh# mkdir /mnt/var
|
||||
sh# mount -t zfs rpool/root/gentoo/var /mnt/var
|
||||
sh# mkdir /mnt/efi
|
||||
sh# mount -t vfat /dev/disk/by-label/esp /mnt/efi
|
||||
```
|
||||
|
||||
Now we are going to fetch a `stage 3` tarball, the archive containing a minimal Gentoo environment. Which will act as the seed of the Gentoo install. Replace the `<release_date>` with the latest stage file release:
|
||||
|
||||
``` shell-session
|
||||
sh# wget https://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-musl-hardened/stage3-amd64-musl-hardened-<release_date>.tar.xz #(1) #(2)!
|
||||
```
|
||||
|
||||
1. It is also possible to use `links` instead of `wget` which provides a small user interface for navigation:
|
||||
|
||||
``` shell-session
|
||||
sh# links https://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-musl-hardened
|
||||
```
|
||||
|
||||
2. There are also other mirrors like `https://ftp.snt.utwente.nl/pub/os/linux/gentoo/releases/amd64/autobuilds/current-stage3-amd64-musl-hardened/` which might provide a faster download depending on your location. Check out <https://www.gentoo.org/downloads/mirrors/> for other mirrors.
|
||||
|
||||
Unpack the stage file in the root of the system:
|
||||
|
||||
``` shell-session
|
||||
sh# tar -xpf stage3-*.tar.xz --numeric-owner -C /mnt
|
||||
```
|
||||
|
||||
To have a functional chroot into the system, copy resolv.conf and bind the system process directories:
|
||||
|
||||
``` shell-session
|
||||
sh# cp /etc/resolv.conf /mnt/etc/
|
||||
sh# for dir in dev proc sys run; do
|
||||
> mount --rbind --make-rslave /$dir /mnt/$dir
|
||||
> done
|
||||
sh# chroot /mnt
|
||||
```
|
||||
|
||||
Configure `portage` (1) before doing anything else, an example file is given below:
|
||||
{ .annotate }
|
||||
|
||||
1. The package manager of Gentoo Linux, which provisions build files from the [Gentoo ebuild repository](https://wiki.gentoo.org/wiki/Ebuild_repository#The_Gentoo_ebuild_repository) or any [additional ebuild repositories](https://wiki.gentoo.org/wiki/Portage#Ebuild_repositories).
|
||||
|
||||
|
||||
``` shell title="/etc/portage/make.conf" linenums="1"
|
||||
# A Gentoo installation is highly personal so diverting from this example is encouraged.
|
||||
# Please consult /usr/share/portage/config/make.conf.example for a more detailed example.
|
||||
|
||||
# Compiler flags
|
||||
COMMON_FLAGS="-march=native -O3 -pipe"
|
||||
CFLAGS="${COMMON_FLAGS}"
|
||||
CXXFLAGS="${COMMON_FLAGS}"
|
||||
FCFLAGS="${COMMON_FLAGS}"
|
||||
FFLAGS="${COMMON_FLAGS}"
|
||||
RUSTFLAGS="${RUSTFLAGS} -C target-cpu=native"
|
||||
|
||||
# Compile options
|
||||
MAKEOPTS="-j8 -l9" #(1)!
|
||||
|
||||
# WARNING: Changing your CHOST is not something that should be done lightly.
|
||||
# Please consult https://wiki.gentoo.org/wiki/Changing_the_CHOST_variable before changing.
|
||||
CHOST="x86_64-pc-linux-musl"
|
||||
|
||||
# NOTE: This stage was built with the bindist USE flag enabled
|
||||
|
||||
# This sets the language of build output to English.
|
||||
# Please keep this setting intact when reporting bugs.
|
||||
LC_MESSAGES=C.utf8
|
||||
|
||||
# Logging
|
||||
PORTAGE_ELOG_CLASSES="log warn error"
|
||||
PORTAGE_LOGDIR="/var/log/portage"
|
||||
PORTAGE_LOGDIR_CLEAN="find \"\${PORTAGE_LOGDIR}\" -type f ! -name \"summary.log*\" -mtime +7 -delete"
|
||||
|
||||
# Only accept free licenses
|
||||
ACCEPT_LICENSE="-* @FREE"
|
||||
|
||||
# USE flags
|
||||
USE="${USE} -debug -telemetry -modemmanager -ext* -ppp -systemd -elogind -X -kde -gnome -gtk-doc -webengine hardened dist-kernel udev initramfs secureboot modules-sign apparmor acpi networkmanager dbus hwaccel bash-completion man pam pipewire vulkan wayland jpeg png" #(2)!
|
||||
|
||||
# Emerge flags
|
||||
EMERGE_DEFAULT_OPTS="${EMERGE_DEFAULT_OPTS} --with-bdeps y --quiet-build y"
|
||||
|
||||
# Secureboot settings
|
||||
SECUREBOOT_SIGN_KEY="/var/lib/sbctl/keys/db/db.key"
|
||||
SECUREBOOT_SIGN_CERT="/var/lib/sbctl/keys/db/db.pem"
|
||||
MODULES_SIGN_KEY="${SECUREBOOT_SIGN_KEY}"
|
||||
MODULES_SIGN_CERT="${SECUREBOOT_SIGN_CERT}"
|
||||
MODULES_SIGN_HASH="sha512"
|
||||
```
|
||||
|
||||
1. The `MAKEOPTS` defines (`-j` the number of jobs/processes) and limits (`-l` the load average) how many parallel make/compilation processes can be launched from `portage`. The number of parallel processes are limited by the number of available logical CPUs and by RAM, each process can take up to `2 GB` of RAM. The load average `-l` is generally set slighly above the number of jobs `-j`.
|
||||
|
||||
2. This selection of global (removed `-`) USE flags is rather personal and should be set according to the preferences of the user.
|
||||
|
||||
Synchronise the ebuild repositories and emerge some relevant packages:
|
||||
|
||||
``` shell-session
|
||||
sh# emaint sync
|
||||
sh# emerge -a app-portage/gentoolkit app-editors/vim sys-libs/timezone-data net-misc/openntpd sys-apps/musl-locales
|
||||
```
|
||||
|
||||
Configure some key aspects of the system:
|
||||
|
||||
``` shell-session
|
||||
sh# echo <hostname> > /etc/hostname
|
||||
sh# echo TZ="/usr/share/zoneinfo/<region>/<city>" > /etc/env.d/timezone
|
||||
sh# echo MUSL_LOCPATH="/usr/share/i18n/locales/musl" > /etc/env.d/musl_locales #(1)!
|
||||
sh# env-update && source /etc/profile
|
||||
sh# eselect locale set <locale> #(2)!
|
||||
sh# rc-update add ntpd default
|
||||
sh# passwd root #(3)!
|
||||
```
|
||||
|
||||
1. Musl does not support locales out of the box. They are not necessary but some programs rely on them to set the language of their application.
|
||||
|
||||
2. The correct `<locale>` can be found in the locale list:
|
||||
|
||||
``` shell-session
|
||||
sh# eselect locale list
|
||||
```
|
||||
|
||||
3. The root password does not really matter because it is going to be locked after a user has been created.
|
||||
|
||||
Edit the `fstab` to set the correct mounts:
|
||||
|
||||
``` shell title="/etc/fstab"
|
||||
rpool/root/gentoo / zfs rw,noatime,xattr,posixacl,casesensitive 0 1
|
||||
rpool/root/gentoo/var /var zfs rw,noatime,nodev,nosuid,xattr,posixacl,casesensitive 0 2
|
||||
/dev/disk/by-label/esp /efi vfat defaults,nodev,nosuid,noexec,umask=0077 0 2
|
||||
tmpfs /tmp tmpfs rw,nodev,nosuid,noexec,mode=1777 0 0
|
||||
proc /proc proc nodev,nosuid,noexec,hidepid=2 0 0
|
||||
```
|
||||
|
||||
Configure the kernel command-line to be able to boot correctly:
|
||||
|
||||
``` shell title="/etc/kernel/cmdline"
|
||||
rw root=ZFS=rpool/root/gentoo rootflags=noatime quiet splash
|
||||
```
|
||||
|
||||
The installation of the hardware firmware on the system, such as the CPU microcode, is hardware specific:
|
||||
|
||||
=== "AMD CPU"
|
||||
|
||||
The microcode updates for systems with an AMD CPU are all contained in `sys-kernel/linux-firmware`, accept its license:
|
||||
|
||||
``` shell title="/etc/portage/package.license/kernel"
|
||||
sys-kernel/linux-firmware linux-fw-redistributable @BINARY-REDISTRIBUTABLE
|
||||
```
|
||||
|
||||
and emerge it:
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a sys-kernel/linux-firmware
|
||||
```
|
||||
|
||||
=== "Intel CPU"
|
||||
|
||||
The microcode updates for systems with an Intel CPU require alongside `sys-kernel/linux-firmware` also `sys-kernel/intel-microcode`, accept its licenses:
|
||||
|
||||
``` shell title="/etc/portage/package.license/kernel"
|
||||
sys-kernel/linux-firmware linux-fw-redistributable @BINARY-REDISTRIBUTABLE
|
||||
sys-firmware/intel-microcode intel-ucode
|
||||
```
|
||||
|
||||
and emerge them:
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a sys-kernel/linux-firmware sys-firmware/intel-microcode
|
||||
```
|
||||
|
||||
Emerge `sbctl` and `sbsigntools` which will be used alongside `dracut` (1) to sign the build Unified Kernel Image (UKI):
|
||||
{ .annotate }
|
||||
|
||||
1. The initramfs builder.
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a app-crypt/sbctl app-crypt/sbsigntools
|
||||
```
|
||||
|
||||
> Verify that secureboot mode is `on` and in `setup mode` with `sbctl status`.
|
||||
|
||||
Create and enroll the secureboot keys into the system:
|
||||
|
||||
``` shell-session
|
||||
sh# sbctl create-keys
|
||||
sh# sbctl enroll-keys #(1)!
|
||||
```
|
||||
|
||||
1. Whilst enrolling the keys it might be necessary to add the `--microsoft` flag if you are unable to use custom keys.
|
||||
|
||||
Enable `dracut` to create a UKI with `ukify`:
|
||||
|
||||
``` shell title="/usr/lib/kernel/install.conf"
|
||||
layout=uki
|
||||
initrd_generator=dracut
|
||||
uki_generator=ukify
|
||||
```
|
||||
|
||||
and enable automatic signing with `sbsign`:
|
||||
|
||||
``` shell title="/etc/kernel/uki.conf"
|
||||
[UKI]
|
||||
SecureBootSigningTool=sbsign
|
||||
```
|
||||
|
||||
Tell `portage` to generate a UKI when installing a kernel:
|
||||
|
||||
``` shell title="/etc/portage/package.use/installkernel"
|
||||
sys-kernel/installkernel dracut ukify uki
|
||||
```
|
||||
|
||||
Emerge the configured Gentoo kernel and its necessary kernel modules for this system:
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a sys-fs/zfs-kmod sys-kernel/gentoo-kernel
|
||||
```
|
||||
|
||||
Set the required USE flags for `systemd-utils` such that on emerging the bootloader `systemd-boot` will be installed:
|
||||
|
||||
``` shell title="/etc/portage/package.use/systemd-utils"
|
||||
sys-apps/systemd-utils kernel-install boot ukify
|
||||
```
|
||||
|
||||
and emerge `systemd-utils`:
|
||||
|
||||
``` shell-session
|
||||
sh# sys-apps/systemd-utils (sys-power/acpi sys-power/acpid sys-power/acpi_call)
|
||||
```
|
||||
|
||||
Install the bootloader on the ESP:
|
||||
|
||||
``` shell-session
|
||||
sh# bootctl install
|
||||
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed" to "/efi/EFI/systemd/systemd-bootx64.efi".
|
||||
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed" to "/efi/EFI/BOOT/BOOTX64.EFI".
|
||||
Random seed file /efi/loader/random-seed successfully refreshed (32 bytes).
|
||||
Created EFI boot entry "Linux Boot Manager".
|
||||
```
|
||||
|
||||
and configure the bootloader:
|
||||
|
||||
``` shell title="/efi/loader/loader.conf"
|
||||
timeout 3
|
||||
editor no
|
||||
```
|
||||
|
||||
> One may verify the signed files by running `sbctl verify`.
|
||||
|
||||
Add some relevant services:
|
||||
|
||||
``` shell-session
|
||||
sh# rc-update add acpid default
|
||||
sh# rc-update add zfs-mount sysinit
|
||||
sh# rc-update add zfs-import sysinit #(1)!
|
||||
sh# rc-update add zfs-load-key sysinit #(2)!
|
||||
```
|
||||
|
||||
1. Omit if a faster boot time is preferred.
|
||||
|
||||
2. Omit if a faster boot time is preferred.
|
||||
|
||||
Now exit the chroot, unmount the datasets and reboot:
|
||||
|
||||
``` shell-session
|
||||
sh# exit
|
||||
sh# umount -lf /mnt
|
||||
sh# reboot
|
||||
```
|
||||
|
||||
## Optional installation
|
||||
|
||||
### Repositories
|
||||
|
||||
[GURU](https://wiki.gentoo.org/wiki/Project:GURU) is an extra repository containing ebuilds that are not available in the Gentoo repository. Although the packages it contains might not be as well tested as in the main repository they are still necessary for some setups, such as some dependencies required for automatic decryption or graphical user interfaces. Add GURU with:
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a app-eselect/eselect-repository
|
||||
sh# eselect repository enable guru
|
||||
sh# emaint sync --repo guru
|
||||
```
|
||||
|
||||
To allow unstable packages from GURU set the `~amd64` keyword for it:
|
||||
|
||||
``` shell title="/etc/portage/package.accept_keywords/guru"
|
||||
*/*::guru ~amd64
|
||||
```
|
||||
|
||||
[Portage-ample](https://git.ampel.dev/ampel/portage-ample) is an extra extra repository containing ebuilds maintained by us, the [Ampel organisation](https://ampel.dev). Add portage-ample with:
|
||||
|
||||
``` shell-session
|
||||
sh# eselect repository add portage-ample git https://git.ampel.dev/ampel/portage-ample
|
||||
sh# emaint sync --repo portage-ample
|
||||
```
|
||||
|
||||
### Automatic decryption
|
||||
|
||||
Automatic decryption will be managed with `zlevis`, which is able to unlock an encrypted `ZFS` root pool with keys saved in a TPM. Currently it is only available in the [portage-ample](https://git.ampel.dev/ampel/portage-ample) repository and also has some dependencies in the `guru` repository.
|
||||
|
||||
Set the `dracut` flag for `zlevis`:
|
||||
|
||||
``` shell title="/etc/portage/package.use/zlevis"
|
||||
app-crypt/zlevis dracut
|
||||
```
|
||||
|
||||
emerge `zlevis`:
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a app-crypt/zlevis
|
||||
```
|
||||
|
||||
and enable the `zlevis` module for `dracut`:
|
||||
|
||||
``` shell title="/etc/dracut.conf.d/zlevis.conf"
|
||||
nofsck="yes"
|
||||
add_dracutmodules+=" zlevis "
|
||||
```
|
||||
|
||||
### Swap
|
||||
|
||||
### Compiler cache
|
||||
|
||||
Compiler cache can speed up recompile's, by avoiding recompilation of the same object files by fetching the result from a cache directory. The package `ccache` enables a compiler cache for `C/C++` object files, present in the Gentoo Kernel for example. Emerge it with:
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a dev-utils/ccache
|
||||
```
|
||||
|
||||
and edit its configuration file:
|
||||
|
||||
``` shell title="/etc/ccache.conf"
|
||||
cache_dir = /var/cache/ccache
|
||||
|
||||
max_size = 20G
|
||||
umask = 002
|
||||
hash_dir = false
|
||||
compiler_check = %compiler% -dumpversion
|
||||
|
||||
compression = true
|
||||
compression_level = 1
|
||||
```
|
||||
|
||||
Configure `portage` to allow `ccache` for specified packages:
|
||||
|
||||
``` shell title="/etc/portage/env/enable-ccache.conf"
|
||||
FEATURES="ccache"
|
||||
CCACHE_DIR="/var/cache/ccache"
|
||||
```
|
||||
|
||||
such that for every `C/C++` package with which you want to use `ccache`:
|
||||
|
||||
``` shell title="/etc/portage/package.env/ccache"
|
||||
sys-kernel/gentoo-kernel enable-ccache.conf
|
||||
...
|
||||
```
|
||||
|
||||
### Users
|
||||
|
||||
### Networking
|
||||
|
||||
## Concluding remarks
|
|
@ -12,7 +12,7 @@ categories:
|
|||
- Base installation
|
||||
---
|
||||
|
||||
This blog entry will demonstrate how to install [Alpine Linux](https://www.alpinelinux.org/) for a server application. Alpine Linux will run on a raid configured encrypted ZFS filesystem with automatic decryption using TPM. 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 blog entry will demonstrate how to install `x86_64` [Alpine Linux](https://www.alpinelinux.org/) for a server application. Alpine Linux will run on a raid configured encrypted ZFS filesystem with automatic decryption using TPM. 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.
|
||||
|
||||
<!-- more -->
|
||||
|
||||
|
@ -25,20 +25,18 @@ After booting the Alpine Linux extended ISO, partition the disks. For this actio
|
|||
To set it up the `setup-interfaces` and `setup-apkrepos` scripts present on the Alpine Linux ISO will be used.
|
||||
|
||||
``` shell-session
|
||||
sh# setup-interfaces -ar
|
||||
sh# setup-interfaces -ar #(1)!
|
||||
sh# setup-apkrepos -c1
|
||||
```
|
||||
|
||||
> To use Wi-Fi simply run `setup-interfaces -r` and select `wlan0` or similar.
|
||||
1. To use Wi-Fi simply run `setup-interfaces -r` and select `wlan0` or similar.
|
||||
|
||||
A few packages will have to be installed first.
|
||||
|
||||
``` shell-session
|
||||
sh# apk add zfs lsblk sgdisk wipefs dosfstools acpid mdadm zlevis
|
||||
sh# apk add zfs lsblk sgdisk wipefs dosfstools mdadm zlevis
|
||||
```
|
||||
|
||||
> The `zlevis` package is as of this moment not yet in the alpine package repository. Try to get it into the `bin` via a different method and add its dependencies `tpm2-tools` and `jose`.
|
||||
|
||||
and load the ZFS kernel module:
|
||||
|
||||
``` shell-session
|
||||
|
@ -156,12 +154,10 @@ sh# zfs create -o mountpoint=/home -o atime=off -o setuid=off -o devices=off -o
|
|||
Write the encryption key to TPM with `zlevis`:
|
||||
|
||||
``` shell-session
|
||||
sh# zlevis encrypt rpool '{}' < /tmp/rpool.key
|
||||
sh# zlevis encrypt rpool '{"pcr_ids":"0,1,7"}' < /tmp/rpool.key #(1)!
|
||||
```
|
||||
|
||||
> We are using the default configuration settings for `zlevis encrypt` but a different configuration is possible by setting `'{}'` accordingly.
|
||||
|
||||
<break>
|
||||
1. See [zlevis functionality](https://docs.ampel.dev/zlevis/functionality/) to see the functionality of each `pcr_id`, and the other options that can be set.
|
||||
|
||||
> To check if it worked, perform `zlevis decrypt rpool`.
|
||||
|
||||
|
@ -245,8 +241,8 @@ sh# rc-update add mdadm-raid boot
|
|||
Configure ZFS to mount:
|
||||
|
||||
``` shell-session
|
||||
sh# rc-update add zfs-import sysinit
|
||||
sh# rc-update add zfs-mount sysinit
|
||||
sh# rc-update add zfs-import sysinit
|
||||
sh# rc-update add zfs-load-key sysinit
|
||||
```
|
||||
|
||||
|
@ -264,20 +260,20 @@ proc /proc proc nodev,nosuid,noexec,hidepid=2
|
|||
|
||||
Install the following packages to make `mkinitfs` compatible with secureboot and TPM decryption:
|
||||
|
||||
``` shell-sessions
|
||||
sh# apk add secureboot-hook sbctl tpm2-tools zlevis
|
||||
``` shell-session
|
||||
sh# apk add secureboot-hook sbctl zlevis zlevis-mkinitfs #(1)!
|
||||
```
|
||||
|
||||
Configure `mkinitfs` to disable trigger and to add the `zlevis-hook`:
|
||||
1. The `mkinitfs-zlevis` package is as of this moment not yet in the alpine package repository, for the relevant steps see the [zlevis mkinitfs-implementation](https://docs.ampel.dev/zlevis/implementation/#mkinitfs).
|
||||
|
||||
Configure `mkinitfs` to disable the trigger and to add the `zlevis` module:
|
||||
|
||||
``` shell title="/etc/mkinitfs/mkinitfs.conf"
|
||||
features="... zlevis"
|
||||
disable_trigger="yes"
|
||||
```
|
||||
|
||||
> The `mkinitfs` package that supports `zlevis` is as of this moment not yet in the alpine package repository, for the relevant steps see the [zlevis mkinitfs-implementation](https://docs.ampel.dev/zlevis).
|
||||
|
||||
The most important step is the creation of a UKI using `secureboot-hook` which also automatically signs them. Configure the `kernel-hooks` to set the kernel cmdline options and secureboot:
|
||||
The most important step is the creation of a UKI using the `secureboot-hook` of `mkinitfs`, which also automatically signs them. Configure the `kernel-hooks` to set the kernel cmdline options and secureboot:
|
||||
|
||||
``` shell title="/etc/kernel-hooks.d/secureboot.conf"
|
||||
cmdline="rw root=ZFS=rpool/root/alpine rootflags=noatime quiet splash"
|
||||
|
@ -285,7 +281,7 @@ cmdline="rw root=ZFS=rpool/root/alpine rootflags=noatime quiet splash"
|
|||
signing_cert="/var/lib/sbctl/keys/db/db.pem"
|
||||
signing_key="/var/lib/sbctl/keys/db/db.key"
|
||||
|
||||
output_dir="/efi/efi/linux"
|
||||
output_dir="/efi/EFI/Linux"
|
||||
output_name="alpine-linux-{flavor}.efi"
|
||||
```
|
||||
|
||||
|
@ -293,10 +289,10 @@ Use `sbctl` to create secureboot keys and sign them:
|
|||
|
||||
``` shell-session
|
||||
sh# sbctl create-keys
|
||||
sh# sbctl enroll-keys
|
||||
sh# sbctl enroll-keys #(1)!
|
||||
```
|
||||
|
||||
> Whilst enrolling the keys it might be necessary to add the `--microsoft` flag if you are unable to use custom keys.
|
||||
1. Whilst enrolling the keys it might be necessary to add the `--microsoft` flag if you are unable to use custom keys.
|
||||
|
||||
Set the cache-file of the ZFS pool:
|
||||
|
||||
|
@ -312,16 +308,16 @@ sh# apk fix kernel-hooks
|
|||
|
||||
and it should give no warnings if done properly.
|
||||
|
||||
To install `gummiboot` as friendly bootloader:
|
||||
To install `systemd-boot` as friendly bootloader:
|
||||
|
||||
``` shell-session
|
||||
sh# apk add gummiboot
|
||||
sh# gummiboot install
|
||||
sh# apk add systemd-boot
|
||||
sh# bootctl install
|
||||
```
|
||||
|
||||
> One may verify the signed files by running `sbctl verify`.
|
||||
|
||||
Configure `gummiboot` to specify the timeout and the default OS :
|
||||
Configure `systemd-boot` to specify the timeout and the default OS :
|
||||
|
||||
``` shell title="/efi/loader/loader.conf"
|
||||
default alpine-linux-lts.efi
|
||||
|
|
91
docs/server-os/posts/04-maintaining-zfs-system.md
Normal file
91
docs/server-os/posts/04-maintaining-zfs-system.md
Normal file
|
@ -0,0 +1,91 @@
|
|||
---
|
||||
title: Maintaining a system build on ZFS
|
||||
slug: maintaining-a-system-build-on-zfs
|
||||
date: 2025-08-02
|
||||
draft: false
|
||||
authors:
|
||||
- luc
|
||||
tags:
|
||||
- Alpine Linux
|
||||
- Gentoo Linux
|
||||
categories:
|
||||
- Maintenance
|
||||
---
|
||||
|
||||
ZFS opens up novel methods to safely maintain a system. In this blog entry we will outline these methods in the form of an update protocol. To keep your system healthy this protocol should be executed on a weekly/monthly basis.
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## Pre-update
|
||||
|
||||
To be able to rollback the system after a system update, one may create a `snapshot` of the root filesystem:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# zfs snapshot rpool/root/alpine@previous
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# zfs snapshot rpool/root/gentoo@previous
|
||||
```
|
||||
|
||||
Furthermore, `zfs list -t snapshot` can be used to list snapshots and `zfs destroy` can be used to remove snapshots.
|
||||
|
||||
## Update
|
||||
|
||||
We may perform a system update:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk upgrade
|
||||
sh# reboot
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -auDU @world
|
||||
sh# reboot
|
||||
```
|
||||
|
||||
If the system does not behave accordingly after reboot, one may `rollback` to the previous snapshot:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# zfs rollback -r rpool/root/alpine@previous
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# zfs rollback -r rpool/root/gentoo@previous
|
||||
```
|
||||
|
||||
## Post-update
|
||||
|
||||
To maintain the performance of the SSDs in the system, perform a `trim` on the ZFS-pool:
|
||||
|
||||
``` shell-session
|
||||
sh# zpool trim --secure --wait rpool #(1)!
|
||||
```
|
||||
|
||||
1. Some devices may not support the option `--secure`.
|
||||
|
||||
A `scrub` on the ZFS-pool checks and repairs the data in the pool and is usually performed after a `trim`:
|
||||
|
||||
``` shell-session
|
||||
sh# zpool scrub rpool
|
||||
```
|
||||
|
||||
A `scrub` may take a while, its progress can be checked with:
|
||||
|
||||
``` shell-session
|
||||
sh# zpool status rpool
|
||||
```
|
||||
|
||||
> A ZFS scrub only repairs if `mirror` or a `zraid` mode is set in the pool.
|
Loading…
Add table
Add a link
Reference in a new issue