<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>KDE Linux on KDE Blogs</title><link>https://blogs.kde.org/categories/kde-linux/</link><description>Recent content in KDE Linux on KDE Blogs</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Mon, 31 Aug 2026 17:23:03 -0400</lastBuildDate><atom:link href="https://blogs.kde.org/categories/kde-linux/index.xml" rel="self" type="application/rss+xml"/><item><title>I Just Wanted to Print a Sandwich</title><link>https://blogs.kde.org/2026/09/01/i-just-wanted-to-print-a-sandwich/</link><pubDate>Tue, 01 Sep 2026 00:00:01 +0000</pubDate><author>Silverhadch</author><guid>https://blogs.kde.org/2026/09/01/i-just-wanted-to-print-a-sandwich/</guid><description>&lt;p&gt;&lt;em&gt;Or: how I ended up developing KDE Linux.&lt;/em&gt;&lt;/p&gt;



&lt;section class="swiper d-flex mb-5" aria-label="Screenshots" role="list"&gt;
 &lt;div class="swiper-wrapper d-flex my-3" role="listitem"&gt;
 &lt;div class="swiper-slide swiper-slide-active"&gt;
 &lt;img src="https://blogs.kde.org/2026/09/01/i-just-wanted-to-print-a-sandwich/kde-linux-now.webp" alt="Now" lazy class="rounded"&gt;
 &lt;span class="d-block text-center mt-2"&gt;Now&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="swiper-slide"&gt;
 &lt;img src="https://blogs.kde.org/2026/09/01/i-just-wanted-to-print-a-sandwich/kde-linux-then.webp" alt="Then" lazy class="rounded"&gt;
 &lt;span class="d-block text-center mt-2"&gt;Then&lt;/span&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;div class="swiper-pagination" style="bottom: 0"&gt;&lt;/div&gt;
 &lt;div class="swiper-button-prev"&gt;&lt;/div&gt;
 &lt;div class="swiper-button-next"&gt;&lt;/div&gt;
&lt;/section&gt;


&lt;p&gt;Most of the people who work on KDE Linux arrived the same way. They were KDE developers first, and then either helped start the project or wandered over to it once it existed. I went the other direction entirely. I was a user. Then a user who filed bugs. Then a user who fixed them. Somewhere in there I became one of the more active contributors, and only after all of that did I become a KDE developer.&lt;/p&gt;
&lt;p&gt;So my start in KDE was not really KDE at all. It was KDE Linux.&lt;/p&gt;
&lt;p&gt;I was searching for a distro, a very particular one. I wanted the latest KDE, rolling enough, atomic, and flicker-free with systemd-boot. After a lot of searching I stumbled over KDE Linux and started using it.&lt;/p&gt;
&lt;p&gt;Oh boy. Young pre-alpha KDE Linux was definitely &lt;em&gt;something&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If I gave you a current KDE Linux image and one of the old ones, you would believe them to be completely separate projects. Stuff broke so comically often back then that I eventually hit the stage of grief where you stop filing bug reports and start fixing things yourself.&lt;/p&gt;
&lt;p&gt;So I made myself an Invent account and just started fixing the issues I ran into. From systemd-boot spitting out error messages because the UKI had the wrong permissions, to roughly thirty commits to get network printers working properly, because I wanted to print a picture of a sandwich.&lt;/p&gt;
&lt;p&gt;Don't ask why. That will remain a secret you'll have to ask me about in person if we ever meet at Akademy.&lt;/p&gt;
&lt;p&gt;That printer saga taught me the first real lesson: unlike my personal projects, here you will get a lot of pushback if something is wrong, and you will go back and forth until it's good enough. If you want to collaborate in a team with actual people, and not just with your friend where the two of you scream at each other over regressions, you need to learn patience.&lt;/p&gt;
&lt;p&gt;Patience is the key to everything. You'll see it come up here again. And again.&lt;/p&gt;
&lt;h2 id="pre-alpha-mostly-plumbing"&gt;Pre-Alpha: mostly plumbing&lt;/h2&gt;
&lt;p&gt;After a while of fixing the distro I was daily driving, it stopped feeling like everything was constantly collapsing. That's when I got invested in seeing this project succeed and started making frequent fixes, to the point where I went from being a random non-KDE contributor to someone the rest of the community started trusting with real work.&lt;/p&gt;
&lt;p&gt;A lot of my early work was stabilisation, because as I said, KDE Linux back then was not very stable. And one problem guided us then and still guides us today, hopefully not for much longer: the choice of base distro.&lt;/p&gt;
&lt;p&gt;You see, KDE Linux is not a traditional mutable distro. It's an image-based system. Writes to &lt;code&gt;/usr&lt;/code&gt; are taboo and there is no pre-installed package manager to install software with.&lt;/p&gt;
&lt;p&gt;Now you might have spotted a small problem. Where the heck does &lt;code&gt;/usr&lt;/code&gt; come from?&lt;/p&gt;
&lt;p&gt;Well, that sentence isn't quite true. There &lt;em&gt;is&lt;/em&gt; a package manager that gets used to populate &lt;code&gt;/usr&lt;/code&gt;, and then afterwards we rip it out and close the door behind it. KDE Linux currently uses pacman and the Arch Linux repos to build its images. Which means any problem Arch has, KDE Linux inherits. And as far as most Linux users know… Arch is not famously known for being stable.&lt;/p&gt;
&lt;p&gt;So KDE Linux had a small problem. The KDE stack we build ourselves in a separate packages pipeline relies on the ABI and versions of certain non-KDE libraries provided by pacman, and therefore by Arch. It is not uncommon for the Arch base to move too fast and brick the KDE stack. We were chasing a target we couldn't possibly catch up with often enough, and we got bricked images out of it.&lt;/p&gt;
&lt;p&gt;So it was decided to rely on Arch's infrastructure (that later turned out to be a mistake) and pin to a snapshot. Working together with Harald, we got the packages pipeline to dedicate a repo snapshot for the main image pipeline, so our stack wouldn't die because of our base distro. And since KDE Linux was designed as an image-based system, swapping the base distro shouldn't be disruptive to users should the need ever arise. But let's not get ahead of ourselves.&lt;/p&gt;
&lt;p&gt;Now, another thing Arch is known for is the AUR, a public index of build scripts anyone can submit to. That openness is the entire point and it is why the AUR is so useful, but it also means nobody reviews a package on your behalf before it runs on your machine.&lt;/p&gt;
&lt;p&gt;For the past year or longer Arch Linux and the AUR have been the victim of repeated DDoS and malware attacks, and KDE Linux got caught in between, because we were using the AUR to a degree. Which meant we had to get the hell out of the crossfire and start removing our AUR dependency bit by bit.&lt;/p&gt;
&lt;p&gt;Before KDE Linux I was an AUR packager, and I still package for a couple of distros, so I took over maintainership for some of it and then started helping remove our AUR dependency altogether. And since some of my own AUR packages were now being pulled into KDE Linux, meaning I was now part of a KDE project's supply chain, I started thinking that maybe I should just do it and become a KDE developer.&lt;/p&gt;
&lt;p&gt;Throughout the pre-alpha I got some guidance from KDE devs like Nate and Harald, and the KDE community started to grow on me. So I asked Harald to sponsor my KDE developer application.&lt;/p&gt;
&lt;h2 id="a-short-detour-about-growing-up"&gt;A short detour about growing up&lt;/h2&gt;
&lt;p&gt;Before I get to what happened next, I should stop and say something about the person who filed that application.&lt;/p&gt;
&lt;p&gt;KDE helped me grow as a developer and as a person.&lt;/p&gt;
&lt;p&gt;Because, as some of you might know, I was not that old. I was basically seventeen, almost eighteen, and somewhat immature, and therefore early on I was, let's put it gently, a bit overwhelmed and abrasive in my language towards others. I repeatedly got into conflict with people because of my poor choice of words and insulting behaviour, because I was severely lacking in the social skills department. I've got to admit that.&lt;/p&gt;
&lt;p&gt;However, after a while, and after having gotten employ**ed, my social skills improved and I started being cringy instead of abrasive. Depending on who you ask, that might be a downgrade, not gonna lie.&lt;/p&gt;
&lt;p&gt;I would say I've grown as a person through interacting with the rest of the KDE community. So it wouldn't be too far-fetched to say that KDE Linux had a positive effect on my life.&lt;/p&gt;
&lt;h2 id="the-alpha-announcement-and-the-four-day-pipeline-curse"&gt;The alpha announcement, and the four-day pipeline curse&lt;/h2&gt;
&lt;p&gt;Eventually KDE Linux reached a certain level of maturity and stability. The pipelines, however, still weren't very happy.&lt;/p&gt;
&lt;p&gt;We were approaching the end of the pre-alpha era and preparing a release and an announcement, but the pipelines had a tendency to fall in on themselves every four days. So for a while it wasn't uncommon for the majority of KDE Linux dev work to be plumbing.&lt;/p&gt;
&lt;p&gt;Eventually the pipelines started to get along with us too, and the KDE Linux alpha release was announced at Akademy, where I looted a crap ton of stickers that my younger sister then proceeded to take from me because she liked Katie.&lt;/p&gt;
&lt;h2 id="how-i-develop-a-distro-i-dont-run"&gt;How I develop a distro I don't run&lt;/h2&gt;
&lt;p&gt;Not long after that, the way I worked on the project had to change completely.&lt;/p&gt;
&lt;p&gt;Until then, my development process basically amounted to doing sysexts on my daily driver, which was KDE Linux. But getting employ**ed meant I couldn't just stay on an alpha distro, even though KDE Linux was nowhere near as unstable by then as it had been in its early life.&lt;/p&gt;
&lt;p&gt;So I moved into the ublue custom images scene and started doing a &amp;quot;KDE Linux but at home&amp;quot; thing, which accidentally turned into a small competition between the two despite me developing both. Ironic. That project eventually died off because the COPR for KDE master builds went unmaintained, so I switched to NixOS, which has been my daily driver ever since.&lt;/p&gt;
&lt;p&gt;Which raises a fair question: isn't the alpha stage the part where I made massive changes, features and improvements? How did I do that on NixOS, where building anything outside the Nix way means fighting the fact that nothing lives where a normal build expects it to?&lt;/p&gt;
&lt;p&gt;Two things. CI-built images, and the built-in Docker script and QEMU.&lt;/p&gt;
&lt;p&gt;(That was three things, but never mind, I'm too tired to move my mouse cursor back and delete it, because I've been writing this in a flow state for two hours.)&lt;/p&gt;
&lt;p&gt;Our CI builds images of every MR and pushes them to Harald's server, so you can download an image and boot and test it in QEMU. That is how I develop KDE Linux to this day. There's also the Docker script which builds MR images locally, in case you have a faster machine than the CI, which most people probably do. I also have a second machine that I use to test some images on real hardware.&lt;/p&gt;
&lt;figure&gt;
 &lt;img class="img-fluid" alt="A KDE Linux MR image booting in QEMU" src="https://blogs.kde.org/2026/09/01/i-just-wanted-to-print-a-sandwich/qemu-test-image.png"
 style="max-width: 100%; height: auto"
 /&gt;
&lt;/figure&gt;
&lt;h2 id="alpha-the-people-who-wear-cool-hats"&gt;Alpha: the people who wear cool hats&lt;/h2&gt;
&lt;p&gt;With the tooling sorted, I could get back to what I actually wanted KDE Linux to be.&lt;/p&gt;
&lt;p&gt;Do you know that distro where people wear cool hats? Yes, Fedora.&lt;/p&gt;
&lt;p&gt;They're quite known for pushing the Linux desktop into the future and showing off the latest and greatest of Linux. And in case you know what KDE Linux's goal is… it's pretty much that, for KDE. Showing off the latest of KDE. But how can you do that if the latest and greatest of Linux is missing?&lt;/p&gt;
&lt;p&gt;So I started joining Fedora Matrix rooms, doing some drive-by contributions and lurking. The change proposals especially caught my eye, along with the fact that both Fedora and KDE Linux want to push Btrfs forward. So I started implementing changes even before Fedora got a chance to do them, like KMSCON.&lt;/p&gt;
&lt;p&gt;And one thing Btrfs is known for is snapshots. Small problem, though: Linux distros don't usually create good Btrfs layouts by default. We didn't either, so Harald moved our layout to RootFSv2.&lt;/p&gt;
&lt;p&gt;The specific issue is having &lt;code&gt;/home&lt;/code&gt; and all its users be one single subvolume. That means, firstly, that only root can take snapshots, because &lt;code&gt;/home&lt;/code&gt; is owned by root. And secondly, that every user's data gets rolled back to a given point &lt;em&gt;together&lt;/em&gt;, so users can &amp;quot;lose&amp;quot; their data so that another user can recover theirs.&lt;/p&gt;
&lt;p&gt;That has some pretty nasty &lt;a href="https://en.wikipedia.org/wiki/Wheel_%28computing%29#Wheel_war"&gt;wheel war&lt;/a&gt; potential.&lt;/p&gt;
&lt;p&gt;So we needed to separate user data from each other. But how? KDE doesn't do &lt;code&gt;useradd&lt;/code&gt; and friends. That falls way, way, way, way lower in the shared stack between almost all Linux distros. That's shadow-utils.&lt;/p&gt;
&lt;h2 id="living-in-the-shadows"&gt;Living in the shadows&lt;/h2&gt;
&lt;p&gt;The work here you won't find in the kde-linux repo, and for a time it looked like I was on hiatus. In reality I had been living in the shadows (pun intended), working behind the scenes to push the Btrfs experience of Linux distros forward, not just for KDE Linux or Fedora, who were also very interested in this approach.&lt;/p&gt;
&lt;p&gt;So I worked on &lt;a href="https://github.com/shadow-maint/shadow/commits/master/?author=silverhadch"&gt;shadow-utils&lt;/a&gt; for months, from bugfixing the Btrfs backend to adding new features to revamping the whole CI. I've been kind of stuck there, to be honest. Though in a good way. I like the project, and C is my favourite language (shocker, treacherous!).&lt;/p&gt;
&lt;p&gt;Eventually the work landed in KDE Linux as RootFSv3 plus snapper for kio-snapshot, which added everything needed for users to be in charge of their own home snapshots, instead of members of the wheel group getting into a wheel war over rolling back all of &lt;code&gt;/home&lt;/code&gt; rather than just their own subvolume.&lt;/p&gt;
&lt;figure&gt;
 &lt;img class="img-fluid" alt="The RootFSv3 subvolume layout" src="https://blogs.kde.org/2026/09/01/i-just-wanted-to-print-a-sandwich/rootfsv3-layout.png"
 style="max-width: 100%; height: auto"
 /&gt;
&lt;/figure&gt;
&lt;p&gt;That was a hell of a lot of work, and it showed how patient one has to be. It took a dozen months of mostly waiting.&lt;/p&gt;
&lt;p&gt;So always remember: Rome wasn't built in a day. Patience is the key to success.&lt;/p&gt;
&lt;h2 id="modularity-and-not-reinventing-the-wheel"&gt;Modularity, and not reinventing the wheel&lt;/h2&gt;
&lt;p&gt;You also need to learn modularity, because throwing everything into the main repo is a bad idea for maintainability.&lt;/p&gt;
&lt;p&gt;In the early alpha stage I wrote a small helper that improves UX in an interactive zsh session when you try to run a file without the executable bit set. (I got tired of &lt;code&gt;chmod +x&lt;/code&gt;-ing things constantly after adding Java support and running &lt;code&gt;.jar&lt;/code&gt; files straight from the terminal.)&lt;/p&gt;
&lt;p&gt;We also started slowly populating the kde-linux group with a lot of repos over time, since a lot of that work can actually be shared with other distros and eventually landed in the system group. Which also shows: please don't reinvent the wheel. We eventually realised that throwing distro engineering into the kde-linux namespace might not be that great an idea, and that collaboration might be the better thing.&lt;/p&gt;
&lt;h2 id="escaping-arch"&gt;Escaping Arch&lt;/h2&gt;
&lt;p&gt;Now, remember when I was ranting about Arch up top? It kind of got worse, with our needs slowly not being fulfilled. The attacks on the AUR got worse, stability deteriorated, and the archive infrastructure we depended on turned out to be fragile, which is fair enough, since keeping old snapshots around is not what a rolling release is built for.&lt;/p&gt;
&lt;p&gt;So I started the not-so-uncontroversial discussion of finally biting the bullet and fleeing Arch. We and even non-KDE contributors started discussing what we should do.&lt;/p&gt;
&lt;p&gt;Because of the shared history with Fedora mentioned above, I was of the opinion that rebasing on Fedora might not be a bad idea, since Fedora and KDE are actually good buddies and our goals align better than with Arch. However, some pointed out that in a way we'd just be exchanging Arch for Fedora, introducing other problems, and still be at the mercy of a base distro.&lt;/p&gt;
&lt;p&gt;So a third, more radical approach was suggested by GNOME people, who are also making their own atomic distro, and by the ublue crew (remember the custom images stuff): BuildStream, and taking complete control of the whole stack, so we're the ones in total control rather than our base distro. Which carries the risk of what Uncle Ben warned Peter about. With great power comes great responsibility.&lt;/p&gt;
&lt;p&gt;This was around the middle of the alpha. So I started working on a Fedora version of KDE Linux, which later became the foundation for culling our Arch repos. Because up to that point the base-distro agnosticism wasn't entirely true: our stack came from our own self-made Arch repos. So instead I decided to port it to kde-builder-based tarballs, since that only relies on the base distro in one place, defining build dependencies.&lt;/p&gt;
&lt;p&gt;We later of course decided to go with the BuildStream approach, and my Fedora work became &lt;a href="https://github.com/silverhadch/fedora-plasma-canary"&gt;fedora-plasma-canary&lt;/a&gt;, which again comes full circle back to ublue. Lol.&lt;/p&gt;
&lt;p&gt;Fun fact: I was actually &lt;em&gt;re&lt;/em&gt;-introducing kde-builder-based building of our stack, because the very earliest builds of KDE Linux, before I even took part in it, used kde-builder and didn't build Arch packages. So we basically reverted back to kde-builder, our upstream tooling that we also use for regular KDE development, on and outside of KDE Linux.&lt;/p&gt;
&lt;p&gt;Around this time we worked out how decisions actually get made in the project. The running joke is that we are a semi-constitutional monarchy, with Harald as supreme banana emperor and the more active contributors as the magic council of elders. In practice it is a handful of people who talk a lot, usually agree, and sit entirely within KDE's actual governance like everyone else. We had like only one vote so far.&lt;/p&gt;
&lt;h2 id="late-alpha-iso-hell"&gt;Late alpha: ISO hell&lt;/h2&gt;
&lt;p&gt;Governance turned out to be the easy problem of that period. The hard one was a file format.&lt;/p&gt;
&lt;p&gt;And there is one thing we had to hear an unbearable number of times.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Where .iso???&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In case you don't know, KDE Linux was distributed as a raw GPT disk. Basically as if your SSD right now were a file. That could be burned onto a USB stick or imported as a hard disk in QEMU. The VM use case was slightly more complicated, because you then need to add another hard disk image to the VM to actually install onto. The old &lt;code&gt;.raw&lt;/code&gt; file is a hard drive in file form that you insert into your &amp;quot;PC.&amp;quot;&lt;/p&gt;
&lt;p&gt;For real installs it didn't matter, because firmware can boot off a hard disk of any kind — which is presumably how the machine you're reading this on got started. So you burn the hard disk file onto a portable hard disk (a USB stick, or a floppy — though it won't fit on a floppy, believe me, I tried, it was 7 GB and 435 MB too large) or a real SSD, if for some reason you have two lying around and are allergic to USB sticks.&lt;/p&gt;
&lt;p&gt;Now, GPT hard disks are very flexible. You can do a lot of software gore with them, like putting them on the 9.4 billion terabyte drives that get invented in 2413. And doing cursed things with partitions. Making an image of one is very easy and you don't need to do anything other than have a properly working hard drive for it to work. (Technically you can also image a broken hard drive, but the intention of the KDE Linux live media is to be able to install, and booting is kind of required for that.)&lt;/p&gt;
&lt;p&gt;However, ISO 9660 (the filesystem) and El Torito (the requirements for making an ISO 9660 filesystem bootable) are incredibly awful. They are a nightmare to deal with and unbelievably outdated.&lt;/p&gt;
&lt;p&gt;Unlike firmware, which will treat a file as a hard disk, please and thank you, these want you to throw everything into an outdated filesystem and insert certain metadata and files in certain places. And then things like &lt;code&gt;systemd-gpt-auto-generator&lt;/code&gt;, which rely on GPT byte sectors and which we use to boot, have to be fixed up in the initrd to go from ISO 9660 byte sectors to GPT byte sectors and then boot them. Working around the thing in the first place.&lt;/p&gt;
&lt;p&gt;Absolute nightmare. I spent weeks reading specs and source code and more source code to only slightly understand what the hell the &lt;code&gt;.iso&lt;/code&gt; wanted from me to be El Torito compatible. After a while I learned systemd had taken a huge part of that work and integrated it. From this day on, I shall fight and die for you, systemd.&lt;/p&gt;
&lt;p&gt;And do you know who thought up these horrible ideas, which were never intended to be used outside of optical discs? ISO 9660 came out of a 1985 industry meeting at a hotel in Lake Tahoe and became a standard in 1988. El Torito arrived a decade later, in 1995, as a joint proposal from Phoenix Technologies and IBM, named, so the story goes, after the restaurant in Irvine where it was designed. Its idea of booting is to make the disc pretend to be a floppy, which tells you roughly everything about the era it comes from. The same IBM that gave us the ThinkPad, which is the only reason I didn't throw mine out of the window over this.&lt;/p&gt;
&lt;p&gt;Of course this is a gross oversimplification, and don't expect me to explain in detail what these specs said, because I'm trying my hardest to forget the experience. And once again patience saved the day — just the day, mind you, my sanity fell victim to specs older than I am — since I also had to wait until ISO 9660 and El Torito support landed in a systemd release.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Lasciate ogne speranza, voi ch'intrate.&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;
 &lt;img class="img-fluid" alt="A page of the El Torito specification" src="https://blogs.kde.org/2026/09/01/i-just-wanted-to-print-a-sandwich/el-torito.png"
 style="max-width: 100%; height: auto"
 /&gt;
&lt;/figure&gt;
&lt;p&gt;And you know what for? Basically nothing.&lt;/p&gt;
&lt;p&gt;It slightly improved the VM install experience, which could also have been solved on the VM software side. Because nobody burns a Linux ISO onto a CD or a DVD anymore in the big 26, and that was the only thing actually gained by complying with El Torito and ISO 9660.&lt;/p&gt;
&lt;p&gt;So if you manage to cram the over-7-gigabyte ISO onto a floppy disk, please let me know.&lt;/p&gt;
&lt;h2 id="late-alpha-an-april-fools-joke-that-got-away-from-me"&gt;Late alpha: an April Fools joke that got away from me&lt;/h2&gt;
&lt;p&gt;And since we were just talking about floppy emulation: do you know DOS?&lt;/p&gt;
&lt;p&gt;It was quite popular back then, before Microsoft won the DOS wars. How fairly it won is a question people are still arguing about on the internet, and I am not opening that door. Either way, DOS was on its way out once NT got good enough for home use, and the good old days of talking to hardware directly in real mode with clever hyper-optimisations are long over.&lt;/p&gt;
&lt;p&gt;However, you can still experience it yourself in KDE Linux. Because as an April Fools joke, I wanted to add DOS support to KDE Linux.&lt;/p&gt;
&lt;p&gt;It seems like nobody realised it was a joke. All the other devs thought I was dead serious.&lt;/p&gt;
&lt;p&gt;Too awkward to now reveal that it was a joke, I instead decided to extend the Package Compatibility Helper to install certain software on demand via a so-called integration tree. It hooks into mimetypes for opening things by right-clicking, into binfmt (asking the kernel to hand a file off to PCH when it's executed), and into stub binaries in &lt;code&gt;/usr/bin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For DOS and Windows, PCH first checks against clear mimetypes, and then, if it's still unclear whether you need Wine or DOSBox, we inspect the binary. Because Microsoft was obsessed with throwing stuff into the DOS header. You can tell something is a Win16 program because the DOS header is a subtle ad telling you to go buy Microsoft Windows, or Win32 because the DOS header reminds you that, in case you try to run the Windows version of Kate under DOS, this program cannot be run in DOS mode.&lt;/p&gt;
&lt;p&gt;Quite a fun rabbit hole to go down.&lt;/p&gt;

 


&lt;figure class="text-center ratio ratio-16x9" style=""&gt;
 &lt;video controls&gt;&lt;source src="https://blogs.kde.org/2026/09/01/i-just-wanted-to-print-a-sandwich/doom-dos.mp4" type="video/mp4" /&gt;&lt;/video&gt;&lt;/figure&gt;

&lt;h2 id="where-we-are-now"&gt;Where we are now&lt;/h2&gt;
&lt;p&gt;If I had to define my work and everyone else's in the late alpha stage, it's finishing the stabilisation, starting the polish, and fulfilling long-standing project goals.&lt;/p&gt;
&lt;p&gt;For being an alpha, and soon a beta, this distro has become unrecognisable compared to its pre-alpha state. It's more polished and stable than most &lt;em&gt;released&lt;/em&gt; distros I've tried, and I do mean that. Of course I might just be biased, but I can't wait to see where this journey goes, and whether this project will finally give KDE its deserved world domination.&lt;/p&gt;
&lt;h2 id="closing"&gt;Closing&lt;/h2&gt;
&lt;p&gt;So, I've been rambling about the important steps and my experiences developing KDE Linux and watching the project grow alongside myself. But all blogs have to end somewhere, and my hands are starting to hurt.&lt;/p&gt;
&lt;p&gt;If I have any tips for new contributors who are interested in helping this ship sail, and it's the thing that has been guiding me through this whole journey: cooperation and patience. Not just between KDE devs, but with the entire Linux stack.&lt;/p&gt;
&lt;p&gt;The day you plant the seed is not the day you eat the fruit.&lt;/p&gt;</description></item><item><title>This Month in KDE Linux: August 2026</title><link>https://blogs.kde.org/2026/08/31/this-month-in-kde-linux-august-2026/</link><pubDate>Mon, 31 Aug 2026 21:15:01 +0000</pubDate><author>Nate Graham and John Veness</author><guid>https://blogs.kde.org/2026/08/31/this-month-in-kde-linux-august-2026/</guid><description>&lt;!-- Example wording for a change, MR version. (Developer Name, [repo-name MR #xxx](https://invent.kde.org/plasma/repo-name/-/merge_requests/xxx)) --&gt;
&lt;!-- Example wording for a change, Bugzilla version. (Developer Name, [KDE Bugzilla #xxx](https://bugs.kde.org/show_bug.cgi?id=xxx)) --&gt;
&lt;!-- ![](thumbnail.png) --&gt;
&lt;!-- 


&lt;section class="swiper d-flex mb-5" aria-label="Screenshots" role="list"&gt;
 &lt;div class="swiper-wrapper d-flex my-3" role="listitem"&gt;
 &lt;/div&gt;
 &lt;div class="swiper-pagination" style="bottom: 0"&gt;&lt;/div&gt;
 &lt;div class="swiper-button-prev"&gt;&lt;/div&gt;
 &lt;div class="swiper-button-next"&gt;&lt;/div&gt;
&lt;/section&gt;

 --&gt;
&lt;!-- 
 


&lt;figure class="text-center ratio ratio-16x9" style=""&gt;
 &lt;video controls&gt;&lt;source src="%25!s%28%3cnil%3e%29something.mp4" type="video/mp4" /&gt;&lt;/video&gt;&lt;/figure&gt;
 --&gt;
&lt;p&gt;Welcome to this edition of &lt;em&gt;This Month in KDE Linux&lt;/em&gt;, dedicated to &lt;a href="https://linux.kde.org/"&gt;KDE’s next-generation operating system&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here’s how KDE Linux evolved in August:&lt;/p&gt;
&lt;h2 id="data-safety"&gt;Data safety&lt;/h2&gt;
&lt;p&gt;A major data safety project reached a state of usability!&lt;/p&gt;
&lt;p&gt;First, Hadi Chokr transformed users’ home folders into &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/475"&gt;Btrfs sub-volumes&lt;/a&gt; and turned on &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/613"&gt;automatic Btrfs snapshots&lt;/a&gt; for all user files.&lt;/p&gt;
&lt;p&gt;Then, Bharadwaj Raju integrated the new &lt;a href="https://invent.kde.org/system/kio-snapshot"&gt;kio-snapshot&lt;/a&gt; system &lt;a href="https://bharadwajraju.com/posts/btrfs-snapshots-in-kde/"&gt;he’s been working on&lt;/a&gt; and &lt;a href="https://invent.kde.org/system/dolphin/-/merge_requests/1347"&gt;added support in Dolphin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now you can easily view and roll back to older versions of your files, even without an off-device backup:&lt;/p&gt;
&lt;figure&gt;
 &lt;img class="img-fluid" alt="Three snapshots of a file named “Family trip ideas.md” from different points in time" src="https://blogs.kde.org/2026/08/31/this-month-in-kde-linux-august-2026/snapshots.webp"
 style="max-width: 100%; height: auto"
 /&gt;
&lt;/figure&gt;
&lt;p&gt;This doesn’t replace a backup, of course! But it does amount to a sort of homedir-level undo feature that can keep your data safe from accidental deletions, or other destructive changes that are less catastrophic than a disk failure or having the device lost or stolen. And these snapshots will be useful to use as backup sources, so you’re not trying to back up a moving target.&lt;/p&gt;
&lt;p&gt;Another few layers in the data safety onion, shall we say!&lt;/p&gt;
&lt;h2 id="cjkv-input-support-by-default"&gt;CJKV input support by default&lt;/h2&gt;
&lt;p&gt;Nate Graham finished the project to &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/329"&gt;make Chinese, Japanese, Korean, and Vietnamese text input work out of the box&lt;/a&gt;. Now everything needed to type in these languages is pre-installed, and all you have to do is &lt;a href="https://linux.kde.org/docs/cjkv-input/"&gt;turn it on&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="qa--testing"&gt;QA &amp;amp; testing&lt;/h2&gt;
&lt;p&gt;Thomas Duckworth and Bhushan Shah continued to develop, refine, and maintain &lt;a href="https://blogs.kde.org/2026/07/13/openqa-testing-in-kde-linux/"&gt;KDE Linux’s automatic QA system&lt;/a&gt;, which continued to pay dividends this month. The system caught multiple complex integration issues introduced accidentally in commits made to KDE software — all of which are now fixed, so users of other operating systems will never have to experience them.&lt;/p&gt;
&lt;h2 id="security"&gt;Security&lt;/h2&gt;
&lt;p&gt;Yago Raña Gayoso &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/602"&gt;removed an unnecessary override&lt;/a&gt; that gave everyone in the &lt;code&gt;wheel&lt;/code&gt; group default access to the Docker daemon’s socket.&lt;/p&gt;
&lt;p&gt;Nate Graham &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/606"&gt;fixed an oversight&lt;/a&gt; that let blacklisted kernel modules into the unified kernel images.&lt;/p&gt;
&lt;h2 id="bugs-fixed"&gt;Bugs fixed&lt;/h2&gt;
&lt;p&gt;Harald Sitter &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/304#note_1568184"&gt;fixed an issue that could make updates fail&lt;/a&gt; right after the update was published, or when run on machines with weak CPUs or slow network connections.&lt;/p&gt;
&lt;p&gt;Hadi Chokr &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/761"&gt;fixed an issue with user-visible version numbers&lt;/a&gt; of KDE Linux builds not including the intended level of precision.&lt;/p&gt;
&lt;h2 id="documentation"&gt;Documentation&lt;/h2&gt;
&lt;p&gt;Nate Graham &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/626"&gt;added quick links to KDE Linux’s official documentation&lt;/a&gt; right there in the launcher menu’s “Help” section.&lt;/p&gt;
&lt;figure&gt;
 &lt;img class="img-fluid" alt="Kickoff widget’s “Help” category showing entries for “Documentation” and “Help &amp;amp; Support”" src="https://blogs.kde.org/2026/08/31/this-month-in-kde-linux-august-2026/links_to_help_and_docs.webp"
 style="max-width: 100%; height: auto"
 /&gt;
&lt;/figure&gt;
&lt;p&gt;Nate Graham also documented &lt;a href="https://linux.kde.org/docs/free-space/"&gt;how to free up disk space&lt;/a&gt;, added a dedicated “&lt;a href="https://linux.kde.org/help/"&gt;Help &amp;amp; Support&lt;/a&gt;” page to the website, and added a link to the &lt;a href="https://blogs.kde.org/categories/kde-linux/"&gt;project’s news feed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Philip Grant refined and documented a way to &lt;a href="https://linux.kde.org/docs/password-managers/#keepassxc"&gt;integrate KeePassXC with the Flatpak packaging of Firefox and Chromium&lt;/a&gt; (and their derivative browsers).&lt;/p&gt;
&lt;p&gt;Julius Künzel &lt;a href="https://invent.kde.org/websites/hugo-kde/-/commit/e76b739ad7bf535d140bc8be98d6bdb9a21e64b1"&gt;fixed the styling of the standard Hugo alert bubbles&lt;/a&gt;, and Nate Graham &lt;a href="https://invent.kde.org/websites/linux-kde-org/-/commit/9f72ba476f60eaeb750d66a4944534b8714ac649"&gt;ported the docs to use them&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="grab-bag"&gt;Grab bag&lt;/h2&gt;
&lt;p&gt;Paul Brown added a neat feature to the &lt;code&gt;set-up-systemd-extension&lt;/code&gt; tool that lets you &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/593"&gt;create new extensions at different locations and with different names&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hadi made the installer &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/710"&gt;report its progress in a more granular way&lt;/a&gt;, so there’s less waiting around and wondering if the installation process got stuck.&lt;/p&gt;
&lt;p&gt;Bhushan Shah &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/611"&gt;removed the “UEFI shell” entry from the bootloader menu&lt;/a&gt;, since it was useless for practically everyone, and now the menu is less cluttered.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="how-you-can-help"&gt;How you can help&lt;/h2&gt;
&lt;p&gt;KDE Linux is making steady progress towards its &lt;a href="https://invent.kde.org/groups/kde-linux/-/milestones/2#tab-issues"&gt;Beta milestone&lt;/a&gt;, and is now 85% of the way there.&lt;/p&gt;
&lt;p&gt;There’s lots to do! If you’re a fan of the project, please help out; there are many ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User support:&lt;/strong&gt; &lt;a href="https://discuss.kde.org/tag/kde-linux/450"&gt;help support people on discuss.kde.org using KDE Linux&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Issue reporting:&lt;/strong&gt; &lt;a href="https://linux.kde.org/docs/install"&gt;install KDE Linux&lt;/a&gt; and &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/issues"&gt;report issues&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation:&lt;/strong&gt; improve &lt;a href="https://linux.kde.org/docs"&gt;the docs&lt;/a&gt; by submitting &lt;a href="https://invent.kde.org/websites/linux-kde-org/-/merge_requests/"&gt;merge requests&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flatpak:&lt;/strong&gt; fix &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/issues/71"&gt;packaging or code issues in Flatpak-packaged apps&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OS development:&lt;/strong&gt; help &lt;a href="https://linux.kde.org/docs/kde-linux-dev"&gt;build KDE Linux&lt;/a&gt;! There’s &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/?sort=created_date&amp;amp;state=opened&amp;amp;milestone_title=Beta&amp;amp;first_page_size=100"&gt;plenty to do&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>This Month in KDE Linux: July 2026</title><link>https://blogs.kde.org/2026/08/03/this-month-in-kde-linux-july-2026/</link><pubDate>Mon, 03 Aug 2026 00:00:01 +0000</pubDate><author>Nate Graham and John Veness</author><guid>https://blogs.kde.org/2026/08/03/this-month-in-kde-linux-july-2026/</guid><description>&lt;!-- Example wording for a change, MR version. (Developer Name, [repo-name MR #xxx](https://invent.kde.org/plasma/repo-name/-/merge_requests/xxx)) --&gt;
&lt;!-- Example wording for a change, Bugzilla version. (Developer Name, [KDE Bugzilla #xxx](https://bugs.kde.org/show_bug.cgi?id=xxx)) --&gt;
&lt;!-- ![](thumbnail.png) --&gt;
&lt;!-- 


&lt;section class="swiper d-flex mb-5" aria-label="Screenshots" role="list"&gt;
 &lt;div class="swiper-wrapper d-flex my-3" role="listitem"&gt;
 &lt;/div&gt;
 &lt;div class="swiper-pagination" style="bottom: 0"&gt;&lt;/div&gt;
 &lt;div class="swiper-button-prev"&gt;&lt;/div&gt;
 &lt;div class="swiper-button-next"&gt;&lt;/div&gt;
&lt;/section&gt;

 --&gt;
&lt;!-- 
 


&lt;figure class="text-center ratio ratio-16x9" style=""&gt;
 &lt;video controls&gt;&lt;source src="%25!s%28%3cnil%3e%29something.mp4" type="video/mp4" /&gt;&lt;/video&gt;&lt;/figure&gt;
 --&gt;
&lt;p&gt;Welcome to the inaugural edition of &lt;em&gt;This Month in KDE Linux&lt;/em&gt; hosted on &lt;a href="https://blogs.kde.org"&gt;blogs.kde.org&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Previously, these posts lived on &lt;a href="https://pointieststick.com/category/kde-linux/"&gt;Nate Graham’s personal blog&lt;/a&gt;. But KDE Linux is growing up and becoming a more important part of KDE, larger than its individual contributors! So it’s time to move the public communication to KDE infrastructure, and that’s where you’ll be able to read these posts going forward.&lt;/p&gt;
&lt;p&gt;Without further ado, here’s how KDE Linux evolved in July:&lt;/p&gt;
&lt;h2 id="qa--testing"&gt;QA &amp;amp; testing&lt;/h2&gt;
&lt;p&gt;This month, Thomas Duckworth and Bhushan Shah integrated the next-gen QA system they’ve been building!&lt;/p&gt;
&lt;p&gt;It’s now testing tons of conditions to make sure KDE Linux continues to work as expected, and it also acts as a full-stack integration test suite. To illustrate the utility of such a thing, it’s already identified and protected users from two significant issues:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/merge_requests/18"&gt;A login-breaking KWin crash caused by a regression in &lt;code&gt;gcc&lt;/code&gt; from Arch Linux&lt;/a&gt; (already fixed).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://invent.kde.org/frameworks/kwallet/-/merge_requests/157#note_1564783"&gt;A regression in automatically unlocking your wallet at login&lt;/a&gt; (also already fixed).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These tricky problems could only have been caught by the kind of full-stack integration test suite that KDE Linux has now.&lt;/p&gt;
&lt;p&gt;If you’re interested in the details, &lt;a href="https://blogs.kde.org/2026/07/13/openqa-testing-in-kde-linux/"&gt;Thomas Duckworth’s blog post on how the system works&lt;/a&gt; is worth a read. Thanks very much to Thomas and Bhushan for building this lovely system!&lt;/p&gt;
&lt;h2 id="security"&gt;Security&lt;/h2&gt;
&lt;p&gt;Hadi Chokr &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/561"&gt;implemented some kernel-hardening tweaks&lt;/a&gt; we learned about from the &lt;a href="https://secureblue.dev/features"&gt;SecureBlue&lt;/a&gt; project that were relevant to KDE Linux and wouldn’t noticeably burden users.&lt;/p&gt;
&lt;h2 id="efficiency--performance"&gt;Efficiency &amp;amp; performance&lt;/h2&gt;
&lt;p&gt;Nate Graham &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/577"&gt;removed the kernel modules for various hardware watchdogs&lt;/a&gt; that aren’t relevant for desktop use, which slightly reduces CPU usage and improves boot times.&lt;/p&gt;
&lt;p&gt;Thomas Duckworth &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/578"&gt;switched the CUPS printing system to use socket activation&lt;/a&gt;, which allows its services to only run when needed.&lt;/p&gt;
&lt;h2 id="software-support-package-downloader--support-for-java-and-dos-apps"&gt;Software support package downloader + support for Java and DOS apps&lt;/h2&gt;
&lt;p&gt;Hadi Chokr &lt;a href="https://invent.kde.org/kde-linux/package-compatibility-helper/-/merge_requests/2"&gt;implemented a major improvement to the “Package Compatibility Helper” tool&lt;/a&gt; that now allows it to — with the user’s consent — download software from Flathub to handle files that the user tries to open, but that nothing on the system can currently open.&lt;/p&gt;
&lt;p&gt;Hadi then &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/447"&gt;made this work for Java apps&lt;/a&gt;; the first time you try to launch one, the tool will ask you if you want to download a Java Runtime Environment (JRE). If you approve, it will do so and then launch the app using the JRE:&lt;/p&gt;

 


&lt;figure class="text-center ratio ratio-16x9" style=""&gt;
 &lt;video controls&gt;&lt;source src="https://blogs.kde.org/2026/08/03/this-month-in-kde-linux-july-2026/java-support.webm" type="video/mp4" /&gt;&lt;/video&gt;&lt;/figure&gt;

&lt;p&gt;After that, Hadi &lt;a href="https://invent.kde.org/kde-linux/package-compatibility-helper/-/merge_requests/3"&gt;implemented support for DOS apps&lt;/a&gt;; trying to launch one will offer up DOSBox. Now you can have that authentic 1993 Doom experience:&lt;/p&gt;

 


&lt;figure class="text-center ratio ratio-16x9" style=""&gt;
 &lt;video controls&gt;&lt;source src="https://blogs.kde.org/2026/08/03/this-month-in-kde-linux-july-2026/doom-dos.mp4" type="video/mp4" /&gt;&lt;/video&gt;&lt;/figure&gt;

&lt;p&gt;This system can be extended to support even more things in the future! And it’s been written in a generic enough way that it would be useful for any other image-based OS using Flatpak, as well.&lt;/p&gt;
&lt;h2 id="bugs-fixed"&gt;Bugs fixed&lt;/h2&gt;
&lt;p&gt;Philip Grant fixed the mechanism that ensures that &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/553"&gt;existing KDE Linux systems have the same Flatpaks installed as are pre-loaded on new systems&lt;/a&gt;, as it had various bugs that prevented it from working properly.&lt;/p&gt;
&lt;p&gt;David Fundament &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/568"&gt;fixed the script that disables USB auto-suspend for input devices&lt;/a&gt; so that it works with devices lacking a product name.&lt;/p&gt;
&lt;p&gt;WenChao Zhang &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/579"&gt;restored the &lt;code&gt;esp4&lt;/code&gt; and &lt;code&gt;esp6&lt;/code&gt; kernel modules&lt;/a&gt; that had been removed to mitigate the “DirtyFrag” vulnerability. The vulnerability has been fixed now, and missing those modules had broken IPsec VPNs, so they’re back now.&lt;/p&gt;
&lt;p&gt;Hadi Chokr &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/725"&gt;made WWAN modems work out of the box&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="documentation"&gt;Documentation&lt;/h2&gt;
&lt;p&gt;Thomas Duckworth documented how to &lt;a href="https://linux.kde.org/docs/openqa/"&gt;use and extend the new QA system&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nate Graham documented how to make the Fcitx 5 input method (for CJKV input) &lt;a href="https://linux.kde.org/docs/cjkv-input/#fixing-compatibility-issues"&gt;work with apps still using the XWayland compatibility layer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hadi Chokr documented &lt;a href="https://linux.kde.org/docs/dual-boot"&gt;how to set up bootloader menus&lt;/a&gt; so you can choose between booting KDE Linux or another OS on the same computer. However, setting up such a system is left as a manual exercise for the reader, as currently the KDE Linux installer does not yet formally support complex disk setups. This will come later.&lt;/p&gt;
&lt;h2 id="grab-bag"&gt;Grab bag&lt;/h2&gt;
&lt;p&gt;Prajna Sariputra &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/566"&gt;pre-installed &lt;code&gt;vulkan-virtio&lt;/code&gt;&lt;/a&gt;, improving performance in VMs whose graphics drivers support Vulkan.&lt;/p&gt;
&lt;p&gt;Thomas Duckworth made the &lt;code&gt;set-up-systemd-extension&lt;/code&gt; and &lt;code&gt;toggle-developer-mode&lt;/code&gt; tools &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/merge_requests/574"&gt;only prompt for authentication once&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nate Graham &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/706"&gt;removed the “Push Services” library and System Settings page&lt;/a&gt;, because it’s not mature enough for shipping yet.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="how-you-can-help"&gt;How you can help&lt;/h2&gt;
&lt;p&gt;KDE Linux is making steady progress towards its &lt;a href="https://invent.kde.org/groups/kde-linux/-/milestones/2#tab-issues"&gt;Beta milestone&lt;/a&gt;, and is now 83% of the way there.&lt;/p&gt;
&lt;p&gt;There’s lots to do! If you’re a fan of the project, please help out; there are many ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User support:&lt;/strong&gt; &lt;a href="https://discuss.kde.org/tag/kde-linux/450"&gt;help support people on discuss.kde.org using KDE Linux&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Issue reporting:&lt;/strong&gt; &lt;a href="https://linux.kde.org/docs/install"&gt;install KDE Linux&lt;/a&gt; and &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/issues"&gt;report issues&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation:&lt;/strong&gt; improve &lt;a href="https://linux.kde.org/docs"&gt;the docs&lt;/a&gt; by submitting &lt;a href="https://invent.kde.org/websites/linux-kde-org/-/merge_requests/"&gt;merge requests&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flatpak:&lt;/strong&gt; fix &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/issues/71"&gt;packaging or code issues in Flatpak-packaged apps&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OS development:&lt;/strong&gt; help &lt;a href="https://linux.kde.org/docs/kde-linux-dev"&gt;build KDE Linux&lt;/a&gt;! There’s &lt;a href="https://invent.kde.org/kde-linux/kde-linux/-/work_items/?sort=created_date&amp;amp;state=opened&amp;amp;milestone_title=Beta&amp;amp;first_page_size=100"&gt;plenty to do&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>openQA Testing in KDE Linux</title><link>https://blogs.kde.org/2026/07/13/openqa-testing-in-kde-linux/</link><pubDate>Mon, 13 Jul 2026 00:00:00 +0000</pubDate><author>Thomas Duckworth</author><guid>https://blogs.kde.org/2026/07/13/openqa-testing-in-kde-linux/</guid><description>&lt;p&gt;The openQA-based testing system has recently been integrated into KDE Linux
(hooray!), and I thought it was about time I did a little write-up.&lt;/p&gt;
&lt;p&gt;The nature of KDE Linux, in which the whole system ships as a single signed
image rather than a pile of packages, is (in theory) wonderful for reliability.
However, this raises an uncomfortable question: how do we make sure that image
actually &lt;em&gt;works&lt;/em&gt; before we ship it to people? OpenQA is the answer!&lt;/p&gt;
&lt;p&gt;TL;DR: we boot each build in a virtual machine, run tests that interact with it
to ensure the system installs and upgrades properly and that desktop
functionality works. Once the tests pass, the user gets an end-to-end
tested image. This replaces the rather rudimentary basic-test machinery, which
simply booted up the live image and checked if the boot was blessed and if any
units failed.&lt;/p&gt;
&lt;h2 id="the-test-flow"&gt;The test flow&lt;/h2&gt;
&lt;p&gt;A single build goes through three stages.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;install-system&lt;/code&gt; takes the live ISO, boots it in a VM, and runs a real
installation onto an empty virtual disk, just like a real user would.
&lt;code&gt;sanity-test&lt;/code&gt; then boots that freshly installed disk and verifies the system
actually comes up and behaves. In between, while we're testing the upgrade path
in parallel, an &lt;code&gt;upgrade-system&lt;/code&gt; stage installs the previous release and upgrades
it to the current build to check whether the previous release can actually be
upgraded to the new build. Each stage hands its disk to the next.&lt;/p&gt;
&lt;p&gt;They're wired together as a dependency chain, so in the openQA web interface
the whole run shows up as a single connected graph. If installation fails, the
later stages don't bother running, as there's nothing to test.&lt;/p&gt;
&lt;p&gt;Our CI pipelines now approximately look like this:&lt;/p&gt;
&lt;img src="ci-flowchart.png" alt="CI flowchart. Imaging failures upload to CI artifacts, while successful images run parallel openQA test and upgrade jobs before gated publishing." width="100%"&gt;
&lt;h2 id="interesting-architectural-tidbits"&gt;Interesting architectural tidbits&lt;/h2&gt;
&lt;p&gt;We do a few things differently compared to your stock-standard openSUSE or
Fedora openQA instances.&lt;/p&gt;
&lt;h3 id="selenium-testing-instead-of-needle-testing"&gt;Selenium testing instead of needle testing&lt;/h3&gt;
&lt;p&gt;Normal openQA tests operate through &amp;quot;needles&amp;quot;. These aren't sewing needles;
rather, they're screenshots of the virtual machine in some desired state with
some JSON metadata attached. This metadata defines certain areas to match or
ignore, and the test code can click matched areas. While needles are certainly
effective at interacting with the system exactly how a user would, they have
drawbacks. It's quite annoying to make and constantly update needles, as well
as keep them from breaking every time there are slight changes in user
interfaces.&lt;/p&gt;
&lt;p&gt;Luckily for us, we already have a battle-tested way of interacting with user
interfaces for testing:
&lt;a href="https://invent.kde.org/sdk/selenium-webdriver-at-spi"&gt;selenium-webdriver-at-spi&lt;/a&gt;
. It's already widely used across unit tests in KDE projects, hence our
decision to use it affords us a lot more flexibility, maintainability, and
consistency. It also enables app developers to run their own tests on KDE Linux
with openQA down the track.&lt;/p&gt;
&lt;p&gt;Essentially, we have a Python &lt;code&gt;unittest&lt;/code&gt; script on the system that we're testing
(see the sysext section below for details), which attaches itself to an
application. It then interacts with the app by leveraging the AT-SPI2
accessibility API to send clicks and read the screen, in a similar vein to
screen-reading software such as Orca.&lt;/p&gt;
&lt;h3 id="ephemeral-workers-in-ci-jobs"&gt;Ephemeral workers in CI jobs&lt;/h3&gt;
&lt;p&gt;openQA instances usually have long-running workers that are hosted on servers.
It's a bit of a painful ordeal to get all that infrastructure up and running.
On top of that, hosted workers need to do an upload-download rigmarole
involving large assets from the server, such as the &lt;code&gt;.iso&lt;/code&gt; files and the
generated hard disk. This makes things &lt;em&gt;very slow&lt;/em&gt; for no good reason.&lt;/p&gt;
&lt;p&gt;We already have CI runners that work perfectly well for this and can be spun up
when needed, giving us effortlessly simple scaling. So, we spin up an openQA
worker container in a CI runner, which submits jobs to the openQA server. It
has its own UUID, which is shared with the job, so the worker running in CI is
always assigned the right job.&lt;/p&gt;
&lt;p&gt;This saves us from the bandwidth rigmarole because all the assets are generated
and consumed within the one container, so we can simply keep all the assets on
the worker and never upload them to the server. As a result, we save a lot of
storage space on the openQA server, so we can run it with fairly minimal
hosting requirements.&lt;/p&gt;
&lt;h3 id="the-use-of-systemd-system-extensions-to-inject-tests"&gt;The use of systemd system extensions to inject tests&lt;/h3&gt;
&lt;p&gt;How do we actually get our Selenium tests on the system, you may ask? Enter the
humble
&lt;a href="https://www.freedesktop.org/software/systemd/man/latest/systemd-sysext.html"&gt;system extension&lt;/a&gt;
, or sysext, for short.&lt;/p&gt;
&lt;p&gt;We include a few things in our sysext:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Python &lt;code&gt;unittests&lt;/code&gt; themselves.&lt;/li&gt;
&lt;li&gt;A bootstrap script with some system configuration, so we have an appropriate
environment set up for testing.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;venv&lt;/code&gt;, so we can make use of the Python ecosystem. This is created in the
bootstrap script.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of this is packaged up into an EROFS &lt;code&gt;.img&lt;/code&gt; file, which we mount to the
worker's VM. This is then automounted by an associated &lt;code&gt;udev&lt;/code&gt; rule in upstream
KDE Linux, with the bootstrapping script being triggered by an associated
service shortly afterward.&lt;/p&gt;
&lt;p&gt;Since we have the capability to inject tests and configuration into the system,
we're able to test things that would otherwise be impossible to test with
needles. For example, we test if essential desktop processes have ever crashed,
if any systemd services failed, if networking works, and if commands we ship
with KDE Linux work properly. All of these tests leverage direct access to the
innards of the system.&lt;/p&gt;
&lt;h3 id="interaction-with-the-system-through-ssh"&gt;Interaction with the system through SSH&lt;/h3&gt;
&lt;p&gt;To actually poke at the system and have the worker run these tests
sequentially, we need some way of interacting with the system. openQA provides
some facilities to interact with a serial terminal, but this proved to be very
fragile and unreliable, with buffering issues everywhere.&lt;/p&gt;
&lt;p&gt;Instead, we set up SSH with our sysext and use the facilities provided by the
Python library &lt;a href="https://www.fabfile.org/"&gt;Fabric&lt;/a&gt; to run all our tests in a
robust manner.&lt;/p&gt;
&lt;p&gt;Each test runs in a transient systemd service created by &lt;code&gt;systemd-run&lt;/code&gt;. This
runs the test as the intended user, groups its processes in a cgroup, gives it
an isolated journal stream for output, and returns its service exit status
synchronously. The harness can then collect the unit's journal even when the
test fails, and we keep everything neat and tidy.&lt;/p&gt;
&lt;h3 id="staging-images-before-we-publish-and-how-we-test-updates"&gt;Staging images before we publish, and how we test updates&lt;/h3&gt;
&lt;p&gt;To prevent users from downloading an image that still needs to be tested, we
create a staging directory on storage.kde.org, scoped to the imaging stage's
job ID, that stores the built artifacts in a directory tree. It has a layout
that mirrors the public-facing tree, so we can simply merge it in once tests
pass.&lt;/p&gt;
&lt;p&gt;However, this throws a spanner in the works when we try to test system upgrades
because we obviously can't upgrade to an image that hasn't been published yet!&lt;/p&gt;
&lt;p&gt;To fix this, the solution is simple. In the sysext, we simply point
&lt;code&gt;systemd-sysupdate&lt;/code&gt; to the staging directory we've already created. This has
some drawbacks, though. For the moment, we can't test delta updates through
&lt;code&gt;kde-linux-sysupdated&lt;/code&gt;. That shouldn't be too difficult to fix in the near
future, but we're waiting on KDE Linux to be entirely hosted on storage.kde.org
before we jump on that. The bigger issue here is that we really don't have a
good way of testing updates from the chunk store. A better story for this still
needs to be worked out, but for the time being the upgrade test is good enough.&lt;/p&gt;
&lt;h2 id="whats-to-come"&gt;What's to come&lt;/h2&gt;
&lt;p&gt;We have a few things we're aiming towards:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As mentioned above, testing delta/chunked upgrades.&lt;/li&gt;
&lt;li&gt;Leveraging openQA to allow app developers to test their own apps atop KDE
Linux.&lt;/li&gt;
&lt;li&gt;Generalizing all our openQA glue so other projects can use the architecture
we've built.&lt;/li&gt;
&lt;li&gt;By extension, porting the aforementioned glue from admittedly fragile bash
scripts to Python or some other more appropriate language.&lt;/li&gt;
&lt;li&gt;Testing installs using manual partitioning and Full Disk Encryption.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;…and probably many more things that we haven't thought of yet. Exciting times!&lt;/p&gt;</description></item></channel></rss>