Gardenhouse

Creating a simple desktop profile

This guide will walk through the creation of a simple profile that installs KDE Plasma, enables SDDM and adds some regular desktop tools.

All command blocks will start from the root of the Gardenhouse repository.

Commands that begin with # must be run as root, commands that begin with $ run as the regular user.

Getting a stage3 tarball

Gardenhouse requires a base Gentoo stage3 tarball to begin the installation. They can be downloaded from the Gentoo Downloads page.

Gardenhouse expects an OpenRC tarball, so ensure that you download an OpenRC tarball, not systemd.

The stage3 tarball is expected to be stored in the root of the Gardenhouse repository with the name stage3-seed.tar.xz.

Creating the profile directory and config

The profile directory is essentially just a regular Gentoo profile, Gardenhouse uses make.defaults to source further options that do not apply directly to portage.

We will call this profile simple_desktop:

user$mkdir profiles/simple_desktop

Populating the profile directory with portage configs

As stated previously, the profile directory contains all configuration files read by portage.

First, create the file profiles/simple_desktop/parent. This is where the profile defines which other profiles it inhertis from. Since we are creating a profile with KDE Plasma, we will use the gentoo plasma profile:

File profiles/simple_desktop/parent Profile inheritance
gentoo:default/linux/amd64/23.0/desktop/plasma

Secondly, we will create make.defaults. This file is the equivalent to gentoos /etc/portage/make.conf. Note that /etc/portage/make.conf will overwrite values in make.defaults.

Config profiles/simple_desktop/make.defaults Portage build configuration
COMMON_FLAGS="-O2 -pipe -march=native"
MAKEOPTS="-j2" # This number can be set to the amount of CPU cores on the build host
RUSTFLAGS="${RUSTFLAGS}"

# To reduce the build time between different builds, the buildpkg feature is recommended to retain any built packages
FEATURES="${FEATURES} getbinpkg buildpkg"

# We will be using a KDE Plasma setup, so lets exclude gtk. Gardenhouse uses dist kernels, so the dist-kernel USE flag should also be set
USE="-gtk -gnome qt5 qt6 kde gui dist-kernel homecrypt"

# For the sake of simplicity, this profile will have no license restrictions
ACCEPT_LICENSE="*"

LC_MESSAGES=C.UTF-8

Chosing the packages to install

The profiles/simple_desktop/packages file contains a simple list of all packages to install in the image, any packages that are available in Gentoo or any manually added Gentoo overlay can be specified here.

Let’s install some regular desktop utilities:

File profiles/simple_desktop/packages Package list
# Some terminal goodies
app-editors/nano
app-admin/doas

# Netifrc are also usable, but plasma has better NetworkManager integration
net-misc/networkmanager

# Plasma stuff
kde-plasma/plasma-meta
kde-apps/konsole
kde-apps/kate
kde-apps/dolphin

# Desktop apps
www-client/firefox-bin
media-gfx/krita
app-office/libreoffice-bin
media-video/vlc

Now, some of these packages are masked by default, let’s manually unmask them:

File profiles/simple_desktop/package.accept_keywords Keyword unmasking
media-gfx/krita ~amd64

For the sake of completness, let’s also set some per package USE flags:

File profiles/simple_desktop/package.use Per-package USE flags
kde-plasma/plasma-meta networkmanager kwallet bluetooth

app-admin/doas persist

Enabling the right openrc services

Now that the profile itself is set up, lets populate make.defaults with some extra Gardenhouse options

Config profiles/simple_desktop/make.defaults Enable display manager service
GARDENHOUSE_SERVICES_default="display-manager"

This tells Gardenhouse to add the service display-manager to the default runlevel during build.

The GARDENHOUSE_SERVICES_<runlevel> variable contains a space seperated string of services to set to the runlevel.

If custom runlevels are desired, they will additionally have to be defined in GARDENHOUSE_CUSTOM_RUNLEVELS

Optional: Secureboot

This part is not required, but is nice to have either way, even if it will not be utilized.

First let’s create the keys using sbctl:

root#sbctl create-keys

Now, let’s tell Gardenhouse to use these keys:

Config profiles/simple_desktop/make.defaults Secureboot key paths
SECUREBOOT_SIGN_CERT="/var/lib/sbctl/keys/db/db.pem"
SECUREBOOT_SIGN_KEY="/var/lib/sbctl/keys/db/db.key"

That’s it! From now on each built image will be signed with the generated Secureboot keys.

Adding static files

Not everything can be configured through the portage profile or the Gardenhouse config, for further flexibility Gardenhouse allows adding custom files to the rootfs through the overlay/ directory.

First, create the directory for our profile:

user$mkdir -p overlay/simple_desktop

The contents of this directory will be copied one-to-one into the rootfs, for this profile, we just need to provide the display-manager config:

user$mkdir -p overlay/simple_desktop/etc/conf.d
Config overlay/simple_desktop/etc/conf.d/display-manager Display manager configuration
CHECKVT=7
DISPLAYMANAGER="sddm"

Start the build

That’s it! Now let’s start the build:

root#./gardenhouse build simple_desktop

Once the build is complete, Gardenhouse will place the outputs in out/simple_desktop.

Installing the image

This part is flexible, essentially the installation works in four steps:

  • Partition the target disk
  • Mount and populate the efi partition with systemd-boot and the Gardenhouse UKI
    the systemd-boot executable may be found in tmp/root/usr/lib/systemd/boot/efi/bootx64.efi and should be placed in EFI/BOOT/BOOTX64.efi inside the efi partition.
    The UKI is named gardenhouse-efi_<version>.efi and should be placed inside EFI/Linux/
  • Flash the root and verity images to their respective partitions
    the root image is named gardenhouse-root_<version>.img
    the verity image is named gardenhouse-root_<version>.verity
  • Format the final partition with a filesystem and set the label USERDATA

In the end it may look something like this, assuming the target disk is at /dev/sda and version is 19701010000:

root#sfdisk /dev/sda <<EOF
label: gpt
device: /dev/sda
start=, size=512M, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name="EFI"
start=, size=4G, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, name="gh19701010000"
start=, size=400M, type=2C7357ED-EBD2-46D9-AEC1-23D437EC2BF5, name="vr19701010000"
start=, size=4G, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709, name="gh0"
start=, size=400M, type=2C7357ED-EBD2-46D9-AEC1-23D437EC2BF5, name="vr0"
start=, type=4D21B016-B534-45C2-A9FB-5C16E091FD2D, name="USERDATA"
EOF
root#mount /dev/sda1 /mnt/boot
root#mkdir -p /mnt/boot/EFI/{BOOT,Linux}
root#cp tmp/root/usr/lib/systemd/boot/efi/bootx64.efi /mnt/boot/EFI/BOOT/BOOTX64.efi
root#cp out/simple_desktop/gardenhouse-efi_19701010000.efi /mnt/boot/EFI/Linux/
root#umount /mnt/boot
root#dd if=out/simple_desktop/gardenhouse-root_19701010000.img of=/dev/sda2 bs=4M status=progress
root#dd if=out/simple_desktop/gardenhouse-root_19701010000.verity of=/dev/sda3 bs=4M status=progress
root#mkfs.btrfs -f -L USERDATA /dev/sda6

The gardenhouse script also contains further commants for building disk images or a simple EFI installer.