I went through hell so you don't have to.
There are three things you need to know about me. I’m blind, I get paid to work on Plasma accessibility, and I use NixOS. In this article, I’m going to explain how I went from developing KDE on Arch Linux to developing KDE on NixOS. Hopefully, so that other people don’t run into the same annoying headaches I did.
Why I Switched to Nix
If Arch was working fine for me, then why did I switch?
Arch worked well for me when it worked well. Assuming my system boots successfully and nothing in the Linux accessibility stack is broken, and assuming I do successfully get to a Plasma session, everything is great. The problem is any time I break something. If my system doesn’t boot, I can’t read the error message. If I don’t happen to have a live USB handy, I probably don’t know where it is and won’t be able to find it. Since my system isn’t booting, I can’t exactly make a new one. And even if I could, it would need to be a Plasma environment otherwise I can’t see what I’m doing.
I switched to Nix so that I could set up the perfect accessible environment for my vision loss, with all the apps and tools I need, once. Should I ever accidentally break my system, all I need to do is reboot, blindly hit the Down arrow key when the blurry boot menu shows up, hit Enter, and I’m back to a working system. This is assuming the broken system ever actually gets installed, since Nix is atomic. (If there’s a configuration error, the system won’t rebuild in the first place)
I’m not saying it was easy to set things up the first time around. I needed help. I am saying it’s something I no longer need to think about - because I’ve written the code already.
How I Develop KDE
Developing Plasma and KDE apps involves doing two things. Building them from source, and actually being able to program.
To build KDE apps from source, I use a tool called KDE Builder. If you work on KDE as well, you’re likely already familiar with it. It allows me to automatically download and build any KDE project I happen to want to work on, with one command. The project will then be available in ~/kde/src/<project name> where I can open it in my editor. For example, to build KWin, I can just run:
kde-builder kwin
It will then build everything KWin needs as a dependency, and then build KWin, and then I can work on KWin.
To actually write code, I use CLion. I use it because I’ve customized it specifically for my vision loss and wrote my own text-to-speech plugin for it. You can get KDE Builder to generate CLion projects for you, that won’t be covered here. I will, however, cover how to get CLion to load properly.
KDE Builder on NixOS
I’ll save you the headache - it’s not going to work.
NixOS, from KDE Builder’s perspective, is impossible to work with. This is because its install script expects a traditional Linux filesystem and package manager, which isn’t available to you on a Nix system. If you can somehow make it work, then great, you’re better at this than me. But since I’m just a Ritchie that has to get work done, …let’s…not do that.
Using Distrobox to build KDE
The trick to KDE Builder is to just use a Distrobox. If you’re not familiar with Distrobox, then I’m surprised. Either way, it allows you to create a containerized environment based on a Linux distribution other than the one you have installed on your system. In other words, Distrobox lets me install Arch Linux (or any other distribution) inside my Nix system, without needing to use another computer or a virtual machine. My home directory gets shared between the two operating systems, and that means the KDE codebase is as well.
Installing Distrobox
If you don’t already have Distrobox installed, you should go do that. You can add it to your NixOS configuration.
environment = {
# ...
systemPackages = with pkgs; [
# ...
distrobox
];
};
You will also want to add support for Docker/Podman to your Nix environment, otherwise Distrobox is useless.
virtualisation.podman = {
enable = true;
dockerCompat = true;
};
After a rebuild, and likely a reboot, you should be good to go.
IMPORTANT: Avoiding a future Qt plugin headache
When KDE Builder builds a project, it’ll also build documentation and Qt help files for that project. This is helpful for hopefully obvious reasons, but if you miss this part of the guide, you’ll fail builds because of documentation. This is because building documentation requires Qt’s SQLite plugin.
Normally, on a regular Linux system, Qt expects plugins to be stored in /usr/lib/qt/plugins. On Nix, Qt plugins are stored in the Nix store. Because of this, NixOS will set the QT_PLUGIN_PATH environment variable to point at the Nix store, if you happen to ver use Qt apps or KDE on Nix. This environment variable will bleed into the Distrobox environment, and that causes problems.
If you use Nix Home Manager, this is easy to fix. Just add this to your Home Manager configuration, to unset that environment variable in any Distrobox container you enter.
programs.distrobox = {
enable = true;
settings.QT_PLUGIN_PATH = "";
};
If you don’t use Home Manager, you’re on your own - please let me know how to do this and I’ll edit the article. You can submit an issue here.
Creating the KDE development environment
Now that we have Distrobox installed, and configured to unset QT_PLUGIN_PATH, we can now create our KDE development environment.
Creating the container
Start by creating an Arch Linux container. You can use any distro you like, I’m just familiar with Arch and usually have the best time with it. Name your container something memorable, like kde-dev - you’ll need that name later.
distrobox create --image archlinux:latest kde-dev
Answer yes to any questions it asks, and wait for the container to be created. When it prompts you to do so, run the following command to enter the Arch environment. The first time you do so, it’ll take a while - it’s installing Arch packages in the background.
distrobox enter kde-dev
Preparing Arch Linux
Once inside the container, check that QT_PLUGIN_PATH is empty by trying to print it.
echo $QT_PLUGIN_PATH
If it prints a blank line, then great. We can continue. You will want to start by installing base-devel, since we’ll need an AUR helper and some AUR packages later on.
sudo pacman -S base-devel
Next, download a snapshot of yay (or your preferred other AUR helper). Extract it, and install the package.
tar -zxvf yay.tar.gz
cd yay
makepkg -sri
Afterward, run yay for good measure to ensure the system is up to date. It probably will be, so it will likely say there’s nothing to do. If not, let it update the ssystem, and we can continue.
Installing some annoying dependencies
For the most part, KDE Builder can install dependencies automatically for you. On Arch, in a Distrobox, there are two packages this won’t work for.
Flatpak By default, KDE Builder expects Flatpak to be installed. Distrobox will create a stub Flatpak binary that allows you to run Flatpak apps from within the container, but have them actually execute on the host. You’ll need to do something scary to deal with this, but just trust me.
sudo rm /usr/bin/flatpak
What you’re doing is deleting a symlink that Distrobox created. If you don’t do this, Arch will refuse to install the flatpak package during KDE Builder initial setup.
Older KDE apps: Qt5 websockets
If you plan on working on older KDE apps that still target Qt 5, and those apps rely on qt5-websockets, this package is now in the AUR.
If you need it, or you don’t want to be annoyed by error messages later on, you can install it with yay.
yay -S qt5-websockets
Unlike Flatpak however, this is optional.
A note about $PATH
KDE Builder expects ~/.local/bin to be in your $PATH environment variable, otherwise the kde-builder command won’t be visible to your shell. Since I don’t know what shell you’re using, I can’t give a full guide on how to set that. I trust you know how to fix that yourself.
Installing KDE Builder
Now we’re ready. Start by downloading the install script from KDE.
curl 'https://invent.kde.org/sdk/kde-builder/-/raw/master/scripts/initial_setup.sh?ref_type=heads' > initial_setup.sh
Then, run that script using Bash.
bash initial_setup.sh
This will install KDE Builder itself, and some mandatory dependencies to the Arch system.
Once that’s done, run the following command to finish initial setup.
kde-builder --initial-setup
This will generate a default KDE Builder configuration in ~/.config/kde-builder.yml, and install even more dependencies needed by most KDE apps.
Once this is all done, try building your first app:
kde-builder kcalc
If you see a smiley face at the end, everything worked. If you don’t, you forgot to:
- unset
QT_PLUGIN_PATH - run
kde-builder --initial-setup - actually be inside the distrobox
You must stay inside the Distrobox when using KDE Builder.
CLion problems
If you made it this far, and KDE Builder is working, then awesome. If you use CLion, and have it installed through Nix or through JetBrains Toolbox, it’s not going to work.
If you’ve installed CLion through Nix itself, don’t. Please remove it. Instead, install JetBrains Toolbox through Nix, and install CLion through Toolbox. This is because we need to do Distrobox jank.
If you’re using CLion through Toolbox, carry on.
Why it doesn’t work
CLion itself will launch and function perfectly fine with its built-in C/C++ toolchain. However, you’ll be unable to build KDE apps in this environment.
The problem is, CLion needs to be running within the Distrobox for the KDE Builder toolchain to function. Furthermore, if you ever need to attach CLion’s debugger to a running KDE process within the Distrobox, you’ll run into kernel security policy issues and it’s not going to work.
We’ll fix both issues.
Getting CLion to run inside Distrobox
When Toolbox installed CLion, it generated a desktop entry fr your launcher.
It gets placed in ~/.local/share/applications/jetbrains-clion-fdc921d5-08c7-4db7-a9f4-61f3ab297cc9.desktop (or something similar). This file is managed by Toolbox and will be overwritten when Toolbox launches.
You’ll need to make a copy of this desktop entry, because we need to edit it. I called mine kde-jetbrains-clion-fdc921d5-08c7-4db7-a9f4-61f3ab297cc9.desktop. You’ll want to edit it.
You’ll see a line similar to:
Exec=/home/ritchie/.local/share/JetBrains/Toolbox/apps/clion/bin/clion %u
Replace that with:
Exec=distrobox-enter kde-dev -- bash -c '/home/ritchie/.local/share/JetBrains/Toolbox/apps/clion/bin/clion %u'
You’ll want to also change the Name value so you can tell the two versions of CLion apart. I set mine to KDE Clion 2025.2.2.
Note: Most desktop environments, including Plasma, have a GUI tool for doing this. You can use that if you’d prefer. These tools are especially helpful since they will refresh the menu for you. If you don’t immediately see the new KDE Clion app available, you may need to log out and log back in.
Dealing with Distrobox sandboxing when debugging KDE apps
If CLion itself launches a KDE app, debugging will work fine. Often times, you won’t be able to use that. For example, if you’re working on KWin, you may want to attach to the Plasma workspace process running inside it. If you try, CLion will complain about permission being denied.
This is because, by default, you’re not allowed to use ptrace within a Distrobox container. To fix this, add this to your Nix configuration and reboot.
boot.kernel.sysctl = {
"kernel.yama.ptrace_scope" = 0;
};
Note: Shortly after publishing, I was told this may not be a Distrobox-specific thing. When I used Arch, I didn’t need to change the kernel ptrace scope. It’s possible this may have changed in the time I’ve been using Nix. Nonetheless, you still need to do it.
This is hell
I just taught you guys how I do it. But this is not how you Nix. So here’s what you should keep in mind.
Remember, it’s still Arch.
My host operating system is Nix, and that’s great. The KDE environment is still an Arch system, which means you get none of the benefits of using Nix. If you break it, it’s broken.
You should make backups. Furthermore, you’ll need to repeat all of this hell any time you set up a new computer or reinstall Nix.
About the ptrace thing…
It’s great that I can attach to processes now, but… keep in mind, that security policy was set by default for a reason. I’m not sure what that reason is, and I personally don’t care, because it’s more important to me that I’m able to debug things. Just…keep that in mind.
We (KDE) can’t always help you
If you run into issues with this setup, most KDE contributors won’t be able to help you figure out what broke. It’s not that we don’t want to help, it’s that most of us aren’t using Nix or Distrobox to work on Plasma. This is a very non-standard setup, so if it breaks beyond what I’ve run into in this article, you are on your own. And that’s okay, because… so am I.
You’ll want to be good at troubleshooting and you’ll want to be extremely patient. I suggest purchasing a plushie and/or stress ball.
Updating CLion
If you update CLion to a new version, you may need to re-create the desktop entry.
In Conclusion…
…I still have a headache. But…at least I can develop Plasma.