Border Cyber Group — April 2, 2026


There's a particular kind of hubris that comes from building a Linux distribution from scratch. You've compiled your own kernel. You've built glibc by hand. You've stared into the abyss of merged-usr and survived. You start to think you're invincible.

You are not invincible.

This is the story of two very productive days, one catastrophic evening, and a backup that may or may not restore correctly. Artemis II is currently in lunar orbit and doing better than I am.


Act I: The Glorious Two Days

What We Actually Built

Coming off a vacation, SableLinux was sitting at a clean Sway 1.10 Wayland desktop — fully operational, security stack complete, Metasploit running, WireGuard tunneling, everything working. The to-do list had two major items: KDE Plasma as a full desktop environment, and the ROCm/AI inference stack.

We tackled KDE first. Here's what that entailed.

Kernel rebuilds #3 and #4 — WireGuard and netfilter support baked into the kernel as built-ins (CONFIG_WIREGUARD=y, CONFIG_TUN=y), followed by KVM virtualization support (CONFIG_KVM_INTEL=y, CONFIG_KVM_AMD=y, bridge networking). This gave us a working WireGuard VPN to our Linode exit node and a functional /dev/kvm for future virtualization work.

QEMU 9.2.2 — built from source with KVM and virtfs support. VMs are now possible.

XWayland 24.1.6 — the X compatibility layer that unlocks Ghidra's GUI, Burp Suite, and eventually Wine/Steam. Ghidra's graphical interface confirmed working.

Then the big push: KDE Plasma 6.3.4.

The dependency chain for a full KDE Plasma install from source is, to put it charitably, ambitious. The build order went roughly like this:

  1. XCB libraries — six of them (xcb-util, xcb-util-image, xcb-util-renderutil, xcb-util-wm, xcb-util-keysyms, xcb-util-cursor), because Qt6's xcb platform plugin requires all of them and we hadn't built them during the original Sway stack work.
  2. Qt6 — thirteen modules — qtbase (rebuilt with xcb support after the above), qtshadertools (required a GCC 15 fix: -include cstdint for the bundled glslang), qtdeclarative (QML engine), qtwayland, qtsvg, qttools, qt5compat, qtimageformats, qtmultimedia, qtspeech (for accessibility — TTS is a first-class feature on SableLinux), qtsensors, qtpositioning, qtwebsockets.
  3. Extra CMake Modules (ECM) — the build system foundation for all of KDE.
  4. KDE Frameworks 6.11.0 — roughly 40 libraries — kcoreaddons, kconfig, karchive, kdbusaddons, kwindowsystem, kcrash, kguiaddons, ki18n, kitemviews, kcompletion, kcodecs, kwidgetsaddons, kcolorscheme, kconfigwidgets, kservice, kiconthemes, breeze-icons, knotifications, kglobalaccel, kpackage, kdeclarative, solid, kbookmarks, kjobwidgets, kauth, kio, attica, knewstuff, kxmlgui, kparts, kitemmodels, krunner, sonnet (with hunspell), ktextwidgets, kstatusnotifieritem, baloo (with LMDB), kidletime, kfilemetadata, ksvg, kirigami, kcmutils, ktexteditor (with syntax-highlighting), kunitconversion, kwallet (daemon disabled to avoid GPG/QCA deps), knotifyconfig, kded, kholidays, kuserfeedback, kdoctools (which required DocBook XML DTD, DocBook XSL stylesheets, libxslt, and a Perl module via cpan). Prison (the barcode library) required qrencode built with -fPIC and shared libs. KRunner required libqalculate (which required ICU 76.1 — a multi-hour build).
  5. Supporting cast — libcanberra (with libogg + libvorbis), hunspell, LMDB, Boost headers, lcms2, libei, libgudev, libwacom, lm-sensors, libpulse-mainloop-glib (manually extracted from a secondary pulseaudio build), Phonon 4.12.0 (Qt6 build), QCoro 0.12.0, qrencode, duktape, polkit 126, polkit-qt-1 (from git — the release version is Qt5 only), plasma-wayland-protocols.
  6. Plasma packages — kdecoration, libkscreen, libksysguard, kglobalacceld, kwayland, layer-shell-qt, plasma-activities, plasma-activities-stats, plasma5support, libplasma, kscreenlocker, KWin 6.3.4, plasma-workspace 6.3.4, plasma-desktop 6.3.4.
  7. SDDM — the display manager. Version 0.20.0 has a D-Bus XML parsing bug with Qt6; had to build from git master. The correct cmake flag is BUILD_WITH_QT6=ON (not QT_MAJOR_VERSION=6).

All told: approximately 80+ packages built from source, in order, on a system with no package manager. Two solid days of work. The build scripts were written, BUILDLOG updated, everything committed to GitHub.


Act II: The Disaster

How It Started

SDDM wouldn't show a login screen. The system booted fine to TTY, reached graphical.target, started SDDM — and then nothing. Black screen.

Dropping to TTY2 (Ctrl+Alt+F2) and running sddm manually revealed the first problem: SDDM was trying to launch X11. We have no Xorg. The fix was straightforward — create /etc/sddm.conf.d/wayland.conf telling SDDM to use its Wayland greeter with KWin as the compositor.

That fixed the X11 problem. Next boot, SDDM got further — display server started, greeter started, then PAM authentication failure. Added /etc/pam.d/sddm and /etc/pam.d/sddm-greeter.

All reasonable, all sensible. Nothing catastrophic yet.

How It Got Worse

Here's where impatience became the enemy.

The system was hanging at "Stopping Virtual Console Setup" on some boots, taking a long time to get through USB enumeration. This is a known USB SSD quirk — the drive sometimes takes 30-60 seconds to enumerate before the kernel is fully happy. It was annoying, but it was not a real problem.

I treated it like a real problem.

The sequence of errors:

  1. Added usbcore.autosuspend=-1 to grub.cfg via sed. The system hung at a blinking cursor — worse than before.
  2. Reverted the parameter via sed. System still hung at blinking cursor. Something had changed.
  3. Tried changing set gfxmode=auto to set gfxmode=text in grub.cfg. Still black screen.
  4. Reverted that. Still broken.
  5. Ran grub-install to refresh the EFI binary. Slightly improved but still not booting.
  6. Changed terminal_output gfxterm to terminal_output console. Complete failure — not even a cursor.
  7. Reverted. Still broken.

At this point the system would not boot at all. Just a black screen after selecting SableLinux from the UEFI boot menu.

What actually caused it: After reverting all the grub changes (which were correct — the grub.cfg was identical to the working original), I found the real culprit in /etc/vconsole.conf:

FONT=Lat2-Terminus16

That font doesn't exist on SableLinux. It had been set at some point during the build process, and systemd-vconsole-setup was hanging trying to load a nonexistent console font. This was the original "Stopping Virtual Console Setup" hang. It was never a USB issue. It was never a GRUB issue. It was a missing font file causing systemd to stall in early boot.

The fix is one line:

sed -i '/^FONT=/d' /etc/vconsole.conf

Unfortunately, by the time this was found, multiple grub.cfg modifications had been made and reverted, and the system still wasn't booting. The real cause may have been a combination of the vconsole font issue plus something in the grub gfxterm changes that didn't fully revert cleanly.

The Score

  • Work lost: approximately two days of KDE Plasma build work — all 80+ packages, SDDM configuration, everything.
  • Git commits: safe. Build scripts: safe. BUILDLOG: safe. The knowledge is preserved.
  • The actual system: needs restoration from backup.
  • Lesson: when something is annoying but not broken, leave it alone.

Act III: The Backup Problem

Here's the current situation.

The restoration backup (sable-root-pre-kernel-rebuild.img.gz, March 10, 22GB compressed) is failing to restore at 63%. The likely cause: Ubuntu was installed on the same USB SSD at some point during the vacation, which repartitioned the drive. The restored partition geometry no longer matches what partclone recorded. The -C flag (disable size checking) gets past the initial check, but the underlying partition structure mismatch causes the restore to fail partway through.

This is being investigated. Options include:

  1. Try restoring from an older backup with matching partition geometry
  2. Rebuild the partition table to match the backup's recorded geometry
  3. Accept that the March 10 backup is unrestorable and rebuild from the March 8/9 backups (security stack era), then re-apply all subsequent work using the git log and build scripts

The build scripts exist precisely for this scenario. Everything is documented. The recovery path is clear, if tedious.


Lessons Learned

1. The vconsole.conf font problem was the only real problem. Everything else was chasing a ghost.

2. When something is working, stop touching it. The system was booting. SDDM was progressively getting closer to working. The USB "hang" was cosmetic. Three GRUB modifications later, nothing booted at all.

3. Backups need to be taken more frequently, and their restorability needs to be verified. A backup that fails at 63% is not a backup.

4. Build scripts are not optional. Having the kde-plasma-build.sh script means that even if we have to restore to March 8 and rebuild everything from there, it's a matter of running one script and walking away. The two days of interactive work have been distilled into something reproducible.

5. The system is not as fragile as it feels in the moment. grub.cfg can be restored. vconsole.conf can be fixed. PAM configs can be written. None of this was unrecoverable — it just felt that way at 1 AM.


What's Next

Once the restore situation is resolved:

  1. Verify the system boots cleanly (vconsole.conf fix applied)
  2. Check package state against BUILDLOG — audit what survived from the vacation work
  3. Fill any gaps manually
  4. Run kde-plasma-build.sh — the full Qt6 → ECM → KF6 → Plasma → SDDM chain, unattended
  5. Fix the SDDM PAM configuration properly this time
  6. Get KDE Plasma on screen

And then, finally, take a proper backup before touching anything else.


SableLinux is a custom Linux distribution built from source, targeting security research, AI inference, and high-performance computing. Build logs, scripts, and documentation at github.com/black-vajra/sablelinux.