7 minute read

This is a guide covering how to work on applications on Fedora Silverblue and Fedora Kinoite. Depending on the case, it may be easier to work with Flatpak, with RPM packages or directly from the source repository thus I will cover all three options.

Note that while this guide focuses on Fedora Silverblue and Fedora Kinoite, it also applies to all rpm-ostree based Fedora variants and in a lesser form to all distributions that feature Flatpak and toolbox.

As always, make sure to backup your data before attempting system wide changes that could result in the loss of your personal cat picture collection.

If you encounter issues with this guide, reach out to me in one of the following Matrix rooms: Flatpak, KDE Flatpaks, Fedora Silverblue, Fedora KDE.

Try to avoid contacting me privately as there is a high chance that other people from those rooms will also be able to help you with your issue.

If you want to work on building images of Fedora Silverblue, Fedora Kinoite or other desktop variants, you should follow the steps from the README in the workstation-ostree-config repo.

Initial setup

As we will be working on Fedora Silverblue or Fedora Kinoite, we will install all of the needed development tools inside of a toolbx.

[host]$ toolbox create
[host]$ toolbox enter
[toolbox]$ sudo dnf update -y
[toolbox]$ sudo dnf install -y git <shell> <editor> <tools> <etc.>

All the following commands in this guide will then be executed from this toolbox. Commands that should be executed on the host will be prefixed with [host] and I will omit the [toolbox] prefix.

$ make -j8
[host]$ rpm-ostree ...

Development using Flatpak

This method is particularly usefull if the application is already packaged as a Flatpak or if it is a good fit for Flatpak. With this method, you can directly work on the source code, re-build the application and see the result.

For this example, we will use Kcalc.

Install tools to build Flatpaks

Enter your toolbx as explained above and install flatpak-builder with:

$ sudo dnf install flatpak-builder

Get the source

Clone the application sources from the upstream repo and optionaly checkout the branch you want to work on:

$ git clone https://invent.kde.org/utilities/kcalc
$ cd kcalc
$ git checkout release/21.12

Create or copy a Flatpak manifest

Kcalc is already published on Flathub thus we can get the Flatpak manifest from there:

$ git clone https://github.com/flathub/org.kde.kcalc

You can find a lot of applications on Flathub or in the KDE Flatpak repo for nightly builds.

If your application does not already have a manifest, consider making one and submitting it to FlatHub. See the Flatpak documentation and the FlatHub submission guide.

Build the application source using Flatpak

Copy the Flatpak manifest into the application source folder:

$ cp org.kde.kcalc/org.kde.kcalc.json .

Tweak the manifest to directly use the sources from the Git repository:

            "name": "kcalc",
            "buildsystem": "cmake-ninja",
            "config-opts": ["-DINSTALL_ICONS=ON"],
            "sources": [
                    "type": "dir",
                    "path": "./"

Add the Flathub remote to get access to all SDK, Runtimes and extensions from there:

$ flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

Install the SDK needed to build the application (see the top of the manifest):

$ flatpak install org.kde.Sdk//5.15-21.08

Note: The // is intentional here. You can skip the version specification and Flatpak will ask you which version to use.

Build the application with Flatpak:

$ flatpak-builder --repo=repo --jobs=8 --force-clean flatpak-build org.kde.kcalc.json

Test the resulting Flatpak

You can then test your application with:

$ flatpak-builder --run flatpak-build org.kde.kcalc.json kcalc

Sometimes you will have to install the application to get special permissions to work:

$ flatpak --user remote-add --no-gpg-verify local-testing-repo repo
$ flatpak --user install local-testing-repo org.kde.kcalc
$ flatpak --user run org.kde.kcalc

Restore the original version

You may uninstall the Flatpak with:

$ flatpak --user remove org.kde.kcalc

Development using RPM packages

This method is particularly usefull if you are working on the kernel or an application that is involved in the boot process and thus requires a reboot for testing.

For this example, we will use systemd.

Install tools to build RPMs

Enter your toolbx as explained at the beginning and install fedpkg with:

$ sudo dnf install fedpkg

Get the RPM spec file

Clone the repository with the sources needed to build the RPM package and switch to the branch for the release you are working on:

$ git clone https://src.fedoraproject.org/rpms/systemd.git systemd-rpm
$ cd systemd-rpm
$ git checkout f35
$ cd ..

Get the source

Clone the application sources from the upstream repo and checkout the release tag corresponding to the release you are working on:

$ git clone https://github.com/systemd/systemd.git
$ cd systemd
$ git checkout release/21.12

Create a patch and use it in the spec file

Make the change that you need in the sources and create a patch:

$ $EDITOR ...
$ git diff > ../systemd-rpm/fix.patch

Edit the spec file to add the patch:

$ cd ../systemd-rpm
$ $EDITOR systemd.spec
Patch0007:      https://github.com/systemd/systemd/commit/2da7d0bc92.patch
# Add your patch here
Patch0008:      fix.patch

# Make sure the patch is applied here
# Usually it is if there are already other PathXYZ entries

Rebuild the RPM locally

Install the build dependencies:

$ sudo dnf builddep systemd

Then we can rebuild the package locally:

$ fedpkg local

You should now have RPM packages in a subfolder ./x86_64/systemd-*.rpm.

Install the RPM on the host

We can now install the RPM with rpm-ostree:

[host]$ rpm-ostree install ./systemd-xyz.rpm

But in this case as the package you want to install is already available in the host, you will have to override it:

[host]$ rpm-ostree override replace ./systemd-xyz.rpm

Test the change

We can then reboot to test the new deployment with the replaced package.

If we want the changes to apply directly on the running system without a reboot, we can also use --apply-live:

[host]$ rpm-ostree install --apply-live ./systemd-xyz.rpm

or for overrides (still experimental, command line subject to change):

[host]$ rpm-ostree override replace ./systemd-xyz.rpm
[host]$ rpm-ostree ex apply-live

This will also be preserved if we reboot.

Restore the default state

You can remove your package with:

$ sudo rpm-ostree remove package-name.rpm

or reset your override with:

$ sudo rpm-ostree override reset package-name.rpm

and then reboot.

Development from the source repository

This method is particularly useful when it does not make sense to package your application as a Flatpak (for example because it is part of the base image already) or if you need to have full control over the build process, configuration flags, etc. without having to extensively modify the RPM spec file.

For this example we will use Discover.

Get the source

Clone the application sources from the upstream repo and optionaly checkout the branch you want to work on:

$ git clone https://invent.kde.org/plasma/discover.git
$ cd discover
$ git checkout Plasma/5.23

Install build dependencies

Install the build dependencies using dnf (using the name as packaged on Fedora):

$ sudo dnf builddep plasma-discover

If your application is not yet packaged, you will have to figure out the dependencies and install them manually.

Configure and build the application

Use either upstream instructions, configuration options or re-use the ones from the RPM package (if available). For example:

$ mkdir -p build
$ cd build
$ cmake -GNinja -DBUILD_SnapBackend=OFF ..
$ ninja

Install to a temporary folder

To make sure that we will not negatively impact our running system, we will install the application in a temporary folder and then sync to our live system only the parts strictly needed:

$ rm -rf ./tmp-install-dir && mkdir -p tmp-install-dir
$ DESTDIR=./tmp-install-dir ninja install

Unlock your local deployment

We then use rpm-ostree to create an ephemeral (lost on reboot) and writable overlay on top of /usr:

[host]$ sudo rpm-ostree usroverlay

Note that we run that command on the host.

Sync to your local deploypment

Finally we can use rsync to install our application to our running system:

[host]$ sudo rsync --archive --verbose --human-readable tmp-install-dir/usr/ /usr/

Note that we run that command on the host.


We can now test our application as if it had always been part of the OS image:

[host]$ plasma-discover

Note that we run that command on the host.

Restore the default state

The simplest option is to reboot. You will get back to the latest deployment available without any local changes.


Those steps might feel unfamiliar to those used to development on classic Linux distributions. However, development on Fedora Silverblue and Fedora Kinoite is made safer by the use of Flatpak and rpm-ostree, without sacrifying speed. Both projects make it easy to try changes while making sure that you can always go back to a working state should anything unexpected happen.



Comments are disabled on this blog but feel free to start a discussion with me on Mastodon.
You can also contact me directly if you have feedback.