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 Florist repository.

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

Getting a stage3 tarball

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

Florist 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 Florist repository with the name stage3-seed.tar.xz.

Creating the profile directory and config

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

We will be working in the garden built-in overlay, but it is also possible to work with a custom gentoo repo.

Let’s call this profile simple_desktop:

user$mkdir garden/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 garden/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 garden/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 garden/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 garden/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 garden/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 garden/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 garden/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 garden/profiles/simple_desktop/make.defaults Enable display manager service
#... [Previous configuration] ...

GARDENHOUSE_SERVICES_default="display-manager"

This tells Florist 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 Florist to use these keys:

Config garden/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 Florist config, for further flexibility Florist allows adding custom files to the rootfs through the gardenhouse/extras/ directory.

First, create the directory for our profile:

user$mkdir -p garden/gardenhouse/extras/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 garden/gardenhouse/extras/simple_desktop/etc/conf.d
Config garden/gardenhouse/extras/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#./florist build -O ./garden simple_desktop

Once the build is complete, Florist 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 rootloader and the Gardenhouse UKI
    the rootloader executable is stored in the out directory next to the built imgaes, if secureboot is enabled, use rootloaderx64.efi.signed 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 out/simple_desktop/rootloaderx64.efi{.signed} /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-installer tool can be used to create self installing ISO images or ready to flash disk images out of florist builds.