From 7c4dd1553e56df3d68f2d1a5c285f5b16abe95c0 Mon Sep 17 00:00:00 2001 From: xyny <60004820+xynydev@users.noreply.github.com> Date: Sun, 10 Sep 2023 14:29:26 +0000 Subject: [PATCH] feat: startingpoint modules (#33) * feat: add startingpoint modules some modules authored by @gerblesh original source: https://github.com/ublue-os/startingpoint/pull/135 * docs: better readme for modules dir * docs: yafti deps * docs: sp more information * feat: startingpoint modules in container * docs: sentence structure, check sidebar --- Containerfile | 1 + modules/README.md | 5 ++ modules/bling/README.md | 20 +++++++ modules/bling/bling.sh | 19 ++++++ .../bling/installers/dconf-update-service.sh | 7 +++ modules/bling/installers/devpod.sh | 6 ++ modules/bling/installers/fonts.sh | 6 ++ modules/bling/installers/justfiles.sh | 6 ++ modules/bling/installers/nix-installer.sh | 7 +++ .../bling/installers/ublue-os-wallpapers.sh | 6 ++ modules/bling/installers/ublue-update.sh | 20 +++++++ modules/files/README.md | 16 +++++ modules/files/files.sh | 33 +++++++++++ modules/rpm-ostree/README.md | 33 +++++++++++ modules/rpm-ostree/rpm-ostree.sh | 58 +++++++++++++++++++ modules/script/README.md | 26 +++++++++ modules/script/script.sh | 16 +++++ modules/systemd/README.md | 41 +++++++++++++ modules/systemd/systemd.sh | 35 +++++++++++ modules/yafti/README.md | 16 +++++ modules/yafti/yafti.sh | 31 ++++++++++ 21 files changed, 408 insertions(+) create mode 100644 modules/README.md create mode 100644 modules/bling/README.md create mode 100644 modules/bling/bling.sh create mode 100644 modules/bling/installers/dconf-update-service.sh create mode 100644 modules/bling/installers/devpod.sh create mode 100644 modules/bling/installers/fonts.sh create mode 100644 modules/bling/installers/justfiles.sh create mode 100644 modules/bling/installers/nix-installer.sh create mode 100644 modules/bling/installers/ublue-os-wallpapers.sh create mode 100644 modules/bling/installers/ublue-update.sh create mode 100644 modules/files/README.md create mode 100644 modules/files/files.sh create mode 100644 modules/rpm-ostree/README.md create mode 100644 modules/rpm-ostree/rpm-ostree.sh create mode 100644 modules/script/README.md create mode 100644 modules/script/script.sh create mode 100644 modules/systemd/README.md create mode 100644 modules/systemd/systemd.sh create mode 100644 modules/yafti/README.md create mode 100644 modules/yafti/yafti.sh diff --git a/Containerfile b/Containerfile index 9634a02..3b432f1 100644 --- a/Containerfile +++ b/Containerfile @@ -18,3 +18,4 @@ FROM scratch COPY --from=builder /tmp/ublue-os/files /files COPY --from=builder /tmp/ublue-os/rpms /rpms COPY --from=ghcr.io/ublue-os/ublue-update:latest /rpms/ublue-update.noarch.rpm /rpms +COPY modules /modules \ No newline at end of file diff --git a/modules/README.md b/modules/README.md new file mode 100644 index 0000000..3f0a9a1 --- /dev/null +++ b/modules/README.md @@ -0,0 +1,5 @@ +# Modules for Startingpoint + +Here (check the sidebar if you're on the website) is documentation for every default module for [Startingpoint](https://github.com/ublue-os/startingpoint/). Source code is inside the [bling](https://github.com/ublue-os/bling/) repository, which is intended for hosting more static and shared parts of custom images. + +For more information about Startingpoint and modules, refer to the README inside the `config/` directory. \ No newline at end of file diff --git a/modules/bling/README.md b/modules/bling/README.md new file mode 100644 index 0000000..c76fa71 --- /dev/null +++ b/modules/bling/README.md @@ -0,0 +1,20 @@ +# [`bling`](https://github.com/ublue-os/bling) Module for Startingpoint + +The `bling` module allows you to easily declare which general parts of `ublue-os/bling` to pull in to your custom image. It requires the `rpms` and `files` directories from the `bling` container to already exist inside `/tmp/bling/` (pulled inside the Containerfile by default). + +The blingbling to pull in is declared under `install:`, and the code for installing them is all in simple named scripts under the `installers/` directory. The basic code for the `bling` module is very similar to the code of the `script` module. + +## Example configuration: + +```yml +type: bling # configure what to pull in from ublue-os/bling +install: + - fonts # selection of common good free fonts + - justfiles # add "!include /usr/share/ublue-os/just/bling.just" + # in your custom.just (added by default) or local justfile + - nix-installer # these are the silverblue nix installer scripts from dnkmmr69420 + - ublue-os-wallpapers + # - ublue-update # https://github.com/ublue-os/ublue-update + # - dconf-update-service # a service unit that updates the dconf db on boot + # - devpod # https://devpod.sh/ as an rpm +``` diff --git a/modules/bling/bling.sh b/modules/bling/bling.sh new file mode 100644 index 0000000..053a0e2 --- /dev/null +++ b/modules/bling/bling.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +get_yaml_array INSTALL '.install[]' "$1" + +export BLING_DIRECTORY="/tmp/bling" + +cd "/tmp/modules/bling/installers" + +# Make every bling installer executable +find "$PWD" -type f -exec chmod +x {} \; + +for ITEM in "${INSTALL[@]}"; do + echo "Pulling from bling: $ITEM" + # The trainling newline from $ITEM is removed + eval "$PWD/${ITEM%$'\n'}.sh" +done \ No newline at end of file diff --git a/modules/bling/installers/dconf-update-service.sh b/modules/bling/installers/dconf-update-service.sh new file mode 100644 index 0000000..d03e299 --- /dev/null +++ b/modules/bling/installers/dconf-update-service.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +cp -r "$BLING_DIRECTORY/files/usr/etc/systemd/system/dconf-update.service" "/usr/etc/systemd/system/dconf-update.service" +systemctl enable dconf-update.services \ No newline at end of file diff --git a/modules/bling/installers/devpod.sh b/modules/bling/installers/devpod.sh new file mode 100644 index 0000000..9bb8699 --- /dev/null +++ b/modules/bling/installers/devpod.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +rpm-ostree install "$BLING_DIRECTORY"/rpms/devpod*.rpm \ No newline at end of file diff --git a/modules/bling/installers/fonts.sh b/modules/bling/installers/fonts.sh new file mode 100644 index 0000000..dda91f7 --- /dev/null +++ b/modules/bling/installers/fonts.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +cp -r "$BLING_DIRECTORY"/files/usr/share/fonts/* "/usr/share/fonts" \ No newline at end of file diff --git a/modules/bling/installers/justfiles.sh b/modules/bling/installers/justfiles.sh new file mode 100644 index 0000000..d976305 --- /dev/null +++ b/modules/bling/installers/justfiles.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +cp -r "$BLING_DIRECTORY"/files/usr/share/ublue-os/just/* "/usr/share/ublue-os/just" \ No newline at end of file diff --git a/modules/bling/installers/nix-installer.sh b/modules/bling/installers/nix-installer.sh new file mode 100644 index 0000000..9f678ac --- /dev/null +++ b/modules/bling/installers/nix-installer.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +cp "$BLING_DIRECTORY/files/usr/bin/ublue-nix-install" "/usr/bin/ublue-nix-install" +cp "$BLING_DIRECTORY/files/usr/bin/ublue-nix-uninstall" "/usr/bin/ublue-nix-uninstall" \ No newline at end of file diff --git a/modules/bling/installers/ublue-os-wallpapers.sh b/modules/bling/installers/ublue-os-wallpapers.sh new file mode 100644 index 0000000..6598bb7 --- /dev/null +++ b/modules/bling/installers/ublue-os-wallpapers.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +rpm-ostree install "$BLING_DIRECTORY"/rpms/ublue-os-wallpapers*.rpm \ No newline at end of file diff --git a/modules/bling/installers/ublue-update.sh b/modules/bling/installers/ublue-update.sh new file mode 100644 index 0000000..33a1831 --- /dev/null +++ b/modules/bling/installers/ublue-update.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +# Check if ublue-os-update-services rpm is installed, these services conflict with ublue-update +if rpm -q ublue-os-update-services > /dev/null; then + rpm-ostree override remove ublue-os-update-services +fi + +# Change the conflicting update policy for rpm-ostreed +RPM_OSTREE_CONFIG="/usr/etc/rpm-ostreed.conf" + +if [[ -f $RPM_OSTREE_CONFIG ]]; then + if [[ "$(get_config_value AutomaticUpdatePolicy $RPM_OSTREE_CONFIG)" == "stage" ]]; then + set_config_value AutomaticUpdatePolicy none $RPM_OSTREE_CONFIG + fi +fi + +rpm-ostree install "$BLING_DIRECTORY"/rpms/ublue-update*.rpm diff --git a/modules/files/README.md b/modules/files/README.md new file mode 100644 index 0000000..20cf75d --- /dev/null +++ b/modules/files/README.md @@ -0,0 +1,16 @@ +# `files` Module for Startingpoint + +The `files` module simplifies the process of copying files to the image during the build time. These files are sourced from the `config/files` directory, which is located at `/tmp/config/files` inside the image. + +> **Warning** +> If you want to place anything in `/etc` of the final image, you MUST place them in `/usr/etc` in your repo, so that they're written to `/usr/etc` on the final system. That is the proper directory for "system" configuration templates on immutable Fedora distros, whereas the normal `/etc` is meant for manual overrides and editing by the machine's admin AFTER installation! See issue https://github.com/ublue-os/startingpoint/issues/28. + +## Example Configuration: + +```yaml +type: files +files: + usr: /usr +``` + +In the example above, `usr` represents the directory located inside the `config/files` in the repository, while `/usr` designates the corresponding destination within the image. diff --git a/modules/files/files.sh b/modules/files/files.sh new file mode 100644 index 0000000..8320dbc --- /dev/null +++ b/modules/files/files.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +get_yaml_array FILES '.files[]' "$1" + +cd "$CONFIG_DIRECTORY/files" + +if [[ ${#FILES[@]} -gt 0 ]]; then + echo "Adding files to image" + for pair in "${FILES[@]}"; do + FILE="$PWD/$(echo $pair | yq 'to_entries | .[0].key')" + DEST=$(echo $pair | yq 'to_entries | .[0].value') + if [ -d "$FILE" ]; then + if [ ! -d "$DEST" ]; then + mkdir -p "$DEST" + fi + echo "Copying $FILE to $DEST" + cp -r "$FILE"/* $DEST + elif [ -f "$FILE" ]; then + DEST_DIR=$(dirname "$DEST") + if [ ! -d "$DEST_DIR" ]; then + mkdir -p "$DEST_DIR" + fi + echo "Copying $FILE to $DEST" + cp $FILE $DEST + else + echo "File or Directory $FILE Does Not Exist in $CONFIG_DIRECTORY/files" + exit 1 + fi + done +fi diff --git a/modules/rpm-ostree/README.md b/modules/rpm-ostree/README.md new file mode 100644 index 0000000..fd51263 --- /dev/null +++ b/modules/rpm-ostree/README.md @@ -0,0 +1,33 @@ +# [`rpm-ostree`](https://coreos.github.io/rpm-ostree/) Module for Startingpoint + +The `rpm-ostree` module offers pseudo-declarative package and repository management using `rpm-ostree`. + +The module first downloads the repository files from repositories declared under `repos:` into `/etc/yum.repos.d/`. The magic string `%OS_VERSION%` is substituted with the current VERSION_ID (major Fedora version), which can be used, for example, for pulling correct versions of repositories from [Fedora's Copr](https://copr.fedorainfracloud.org/). + +Then the module installs the packages declared under `install:` using `rpm-ostree install`, it removes the packages declared under `remove:` using `rpm-ostree override remove`. If there are packages declared under both `install:` and `remove:` a hybrid command `rpm-ostree remove --install ` is used, which should allow you to switch required packages for other ones. + +Additionally, the `rpm-ostree` module supports a temporary (waiting for `rpm-ostree` issue [#233](https://github.com/coreos/rpm-ostree/issues/233)) fix for packages that install into `/opt/`. Installation for packages that install into folder names declared under `optfix:` are fixed using some symlinks. + +## Example Configuration: + +```yml +type: rpm-ostree +repos: + - https://copr.fedorainfracloud.org/coprs/atim/starship/repo/fedora-%OS_VERSION%/atim-starship-fedora-%OS_VERSION%.repo +install: + - python3-pip + - libadwaita +remove: + - firefox + - firefox-langpacks +``` + + +## Known issues + +When removing certain packages, some problem probably in upstream `rpm-ostree` causes a `depsolve` issue similar to below. [Removed packages are still present in the underlying ostree repository](https://coreos.github.io/rpm-ostree/administrator-handbook/#removing-a-base-package), what `remove` does is "hide" them from the system, it doesn't reclaim disk space. +``` +Resolving dependencies...done +error: Could not depsolve transaction; 1 problem detected: +Problem: conflicting requests +``` \ No newline at end of file diff --git a/modules/rpm-ostree/rpm-ostree.sh b/modules/rpm-ostree/rpm-ostree.sh new file mode 100644 index 0000000..995904f --- /dev/null +++ b/modules/rpm-ostree/rpm-ostree.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +# Pull in repos +get_yaml_array REPOS '.repos[]' "$1" +if [[ ${#REPOS[@]} -gt 0 ]]; then + echo "Adding repositories" + for REPO in "${REPOS[@]}"; do + REPO="${REPO//%OS_VERSION%/${OS_VERSION}}" + wget "${REPO//[$'\t\r\n ']}" -P "/etc/yum.repos.d/" + done +fi + +# Create symlinks to fix packages that create directories in /opt +get_yaml_array OPTFIX '.optfix[]' "$1" +if [[ ${#OPTFIX[@]} -gt 0 ]]; then + echo "Creating symlinks to fix packages that install to /opt" + # Create symlink for /opt to /var/opt since it is not created in the image yet + mkdir -p "/var/opt" + ln -s "/var/opt" "/opt" + # Create symlinks for each directory specified in recipe.yml + for OPTPKG in "${OPTFIX[@]}"; do + OPTPKG="${OPTPKG%\"}" + OPTPKG="${OPTPKG#\"}" + OPTPKG=$(printf "$OPTPKG") + mkdir -p "/usr/lib/opt/${OPTPKG}" + ln -s "../../usr/lib/opt/${OPTPKG}" "/var/opt/${OPTPKG}" + echo "Created symlinks for ${OPTPKG}" + done +fi + +get_yaml_array INSTALL '.install[]' "$1" +get_yaml_array REMOVE '.remove[]' "$1" + +# The installation is done with some wordsplitting hacks +# because of errors when doing array destructuring at the installation step. +# This is different from other ublue projects and could be investigated further. +INSTALL_STR=$(echo "${INSTALL[*]}" | tr -d '\n') +REMOVE_STR=$(echo "${REMOVE[*]}" | tr -d '\n') + +# Install and remove RPM packages +if [[ ${#INSTALL[@]} -gt 0 && ${#REMOVE[@]} -gt 0 ]]; then + echo "Installing & Removing RPMs" + echo "Installing: ${INSTALL_STR[*]}" + echo "Removing: ${REMOVE_STR[*]}" + # Doing both actions in one command allows for replacing required packages with alternatives + rpm-ostree override remove $REMOVE_STR $(printf -- "--install=%s " $INSTALL_STR) +elif [[ ${#INSTALL[@]} -gt 0 ]]; then + echo "Installing RPMs" + echo "Installing: ${INSTALL_STR[*]}" + rpm-ostree install $INSTALL_STR +elif [[ ${#INSTALL[@]} -gt 0 ]]; then + echo "Removing RPMs" + echo "Removing: ${REMOVE_STR[*]}" + rpm-ostree override remove $REMOVE_STR +fi diff --git a/modules/script/README.md b/modules/script/README.md new file mode 100644 index 0000000..b2419c5 --- /dev/null +++ b/modules/script/README.md @@ -0,0 +1,26 @@ +# `script` Module for Startingpoint + +The `script` module can be used to run arbitrary scripts at image build time that take no or minimal external configuration (in the form of command line arguments). +The scripts, which are run from the `config/scripts` directory, are declared under `scripts:`. + +## Example Configuration + +```yml +type: script +scripts: + - signing.sh +``` + +## Creating a Script + +Look at `example.sh` for an example shell script. You can rename and copy the file for your own purposes. In order for the script to be executed, declare it in the recipe + +When creating a script, please make sure + +- ...its filename ends with `.sh`. + - This follows convention for (especially bash) shell scripts. + - `autorun.sh` only executes files that match `*.sh`. +- ...it starts with a [shebang]() like `#!/usr/bin/env bash`. + - This ensures the script is ran with the correct interpreter / shell. +- ...it contains the command `set -oue pipefail` near the start. + - This will make the image build fail if your script fails. If you do not care if your script works or not, you can omit this line. diff --git a/modules/script/script.sh b/modules/script/script.sh new file mode 100644 index 0000000..fe63e0f --- /dev/null +++ b/modules/script/script.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +get_yaml_array SCRIPTS '.scripts[]' "$1" + +cd "$CONFIG_DIRECTORY/scripts" + +# Make every script executable +find "$PWD" -type f -exec chmod +x {} \; + +for SCRIPT in "${SCRIPTS[@]}"; do + echo "Running script $SCRIPT" + eval "$PWD/$SCRIPT" +done \ No newline at end of file diff --git a/modules/systemd/README.md b/modules/systemd/README.md new file mode 100644 index 0000000..4b122b8 --- /dev/null +++ b/modules/systemd/README.md @@ -0,0 +1,41 @@ +# `systemd` Module for Startingpoint + +The `systemd` module streamlines the management of systemd units during image building. Units are divided into `system` and `user` categories, with `system` units managed directly using `systemctl` and `user` units using `systemctl --user`. You can specify which units to enable or disable under each category. + +## Example Configuration: + +```yaml +type: systemd +system: + enable: + - example.service + disable: + - example.target +user: + enable: + - example.timer + disable: + - example.service +``` + +In this example: + +### System Units +- `example.service`: Enabled (runs on system boot) +- `example.target`: Disabled (does not run on system boot) + +### User Units +- `example.timer`: Enabled (runs for the user) +- `example.service`: Disabled (does not run for the user) + +This configuration achieves the same results as the following commands: + +```sh +# System Units +systemctl enable example.service +systemctl disable example.target + +# User Units +systemctl --user enable example.timer +systemctl --user disable example.service +``` diff --git a/modules/systemd/systemd.sh b/modules/systemd/systemd.sh new file mode 100644 index 0000000..a9aeb5e --- /dev/null +++ b/modules/systemd/systemd.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +get_yaml_array ENABLED '.system.enabled[]' "$1" +get_yaml_array DISABLED '.system.disabled[]' "$1" +get_yaml_array USER_ENABLED '.user.enabled[]' "$1" +get_yaml_array USER_DISABLED '.user.disabled[]' "$1" + + +if [[ ${#ENABLED[@]} -gt 0 ]]; then + for unit in "${ENABLED[@]}"; do + unit=$(printf "$unit") + systemctl enable $unit + done +fi +if [[ ${#DISABLED[@]} -gt 0 ]]; then + for unit in "${DISABLED[@]}"; do + unit=$(printf "$unit") + systemctl disable $unit + done +fi +if [[ ${#USER_ENABLED[@]} -gt 0 ]]; then + for unit in "${ENABLED[@]}"; do + unit=$(printf "$unit") + systemctl --user enable $unit + done +fi +if [[ ${#USER_DISABLED[@]} -gt 0 ]]; then + for unit in "${DISABLED[@]}"; do + unit=$(printf "$unit") + systemctl --user disable $unit + done +fi diff --git a/modules/yafti/README.md b/modules/yafti/README.md new file mode 100644 index 0000000..af81b57 --- /dev/null +++ b/modules/yafti/README.md @@ -0,0 +1,16 @@ +# [`yafti`](https://github.com/ublue-os/yafti) Module for Startingpoint + +If included, the `yafti` module will install `yafti` and set it up to run on first boot. Also `yafti`'s dependencies, `python3-pip` and `libadwaita` are installed + +Optionally, a list of Flatpak names and IDs can be included under `custom-flatpaks:`. These will be enabled by default under their own section on the Flatpak installation screen of `yafti`. + +The main `yafti` configuration file, `yafti.yml`, is in `/usr/share/ublue-os/firstboot/yafti.yml` and can be edited for a more custom first-boot experience. + +## Example configuration: + +```yml +type: yafti +custom-flatpaks: + - Celluloid: io.github.celluloid_player.Celluloid + - Krita: org.kde.krita +``` diff --git a/modules/yafti/yafti.sh b/modules/yafti/yafti.sh new file mode 100644 index 0000000..4625120 --- /dev/null +++ b/modules/yafti/yafti.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# Tell build process to exit if there are any errors. +set -oue pipefail + +FIRSTBOOT_DATA="/usr/share/ublue-os/firstboot" +FIRSTBOOT_LINK="/usr/etc/profile.d/ublue-firstboot.sh" + +echo "Installing python3-pip and libadwaita" +rpm-ostree install python3-pip libadwaita + +echo "Installing and enabling yafti" +pip install --prefix=/usr yafti + +# Create symlink to our profile script, which creates the per-user "autorun yafti" links. +mkdir -p "$(dirname "${FIRSTBOOT_LINK}")" +ln -s "${FIRSTBOOT_DATA}/launcher/login-profile.sh" "${FIRSTBOOT_LINK}" + +YAFTI_FILE="$FIRSTBOOT_DATA/yafti.yml" + +get_yaml_array FLATPAKS '.custom-flatpaks[]' "$1" +if [[ ${#FLATPAKS[@]} -gt 0 ]]; then + echo "Adding Flatpaks to yafti.yml" + yq -i '.screens.applications.values.groups.Custom.description = "Flatpaks suggested by the image maintainer."' "${YAFTI_FILE}" + yq -i '.screens.applications.values.groups.Custom.default = true' "${YAFTI_FILE}" + + for pkg in "${FLATPAKS[@]}"; do + echo "Adding to yafti: ${pkg}" + yq -i ".screens.applications.values.groups.Custom.packages += [$pkg]" "${YAFTI_FILE}" + done +fi \ No newline at end of file