howto

Eigene CI für Radicle: vom Ref-Event zum überprüfbaren Release

Eine praktische Fortsetzung zum CI-Broker: eigene Radicle-Repositories bauen, Images und Helm-Charts veröffentlichen, mit Syft und Trivy prüfen und Releases mit überprüfbaren Digests beschreiben. Mit Konfigurationsbeispielen, den Gründen für cosign-legacy und den Grenzen des nativen Runners.

Der erste grüne Build ist ein gutes Gefühl. Für eine eigene CI ist er trotzdem erst die halbe Strecke. Danach kommen die Fragen, die bei einer gehosteten Forge oft hinter einem fertigen Produkt verschwinden: Wer darf Code ausführen? Welches Image gehört zu welchem Commit? Wie prüfe ich beide Architekturen? Und was genau bedeutet „Release“, wenn Git-Tag, Registry-Artefakt und Radicle-Veröffentlichung drei verschiedene Dinge sind?

Mein erster CI-Broker-Beitrag war ein Reisebericht durch die Probleme beim Aufbau. Diese Fortsetzung ist die geordnete Variante für Menschen, die Radicle bereits verwenden und ihre eigene CI betreiben möchten. Der Broker ist inzwischen bei v1.5.0 angekommen: mit gemischtem Image-/Chart-Publishing, signierten Artefakten, Werkzeugen für SBOMs und Schwachstellenscans und einer besseren Behandlung von Release-Ereignissen.

Das Ziel ist nicht, mein komplettes Lab zu kopieren. Es ist ein nachvollziehbarer Weg vom replizierten Commit bis zu einem Artefakt, dessen Herkunft und Prüfergebnisse ein anderer Mensch kontrollieren kann.

Paperless-ngx im Lab: vom Scan zum brauchbaren Archiv

Ein Dokumentenarchiv ist mehr als OCR hinter einer Weboberfläche. Wie ich Scanner, Mailimport, PostgreSQL, kontrollierte KI-Klassifikation und Off-site-Backups zusammenführe — und warum Eigentümer, Upload-Grenzen und Restore-Zeitpunkte dabei wichtiger sind als der Modellname.

Ein Scanner löst das Papierproblem nur zur Hälfte. Danach liegt die Rechnung nicht mehr auf dem Schreibtisch, sondern als scan_0042.pdf in einem Verzeichnis. Man kann sie öffnen, aber noch lange nicht zuverlässig wiederfinden. Bei E-Mails ist es ähnlich: Der Anhang ist irgendwo vorhanden, der Zusammenhang steckt im Postfach, und ob beides wirklich gesichert ist, bleibt eine andere Frage.

Paperless-ngx soll in meinem Lab genau diese Lücke schließen: Dokumente aufnehmen, durchsuchbar machen und mit brauchbaren Metadaten versehen. Die interessante Arbeit begann allerdings erst nach dem ersten erfolgreichen Upload. Wie landet ein Scan vollständig im Archiv? Was darf ein Sprachmodell entscheiden? Und wie stelle ich Dateien und Datenbank so wieder her, dass sie auch zusammenpassen?

Tor als CRD: ein eigener Operator statt Sidecar-Bastelei

Warum ich den inoffiziellen tor-controller durch einen eigenen, in Rust geschriebenen Operator ersetzt habe — ein gemeinsamer Tor-Daemon pro Namespace, Onion-Services und Onion-Proxies dynamisch über den Control-Port, plus kuratierte obfs4-Bridges

Tor-Konnektivität im Cluster hatte ich bisher zusammengesteckt: pro Pod ein client-only tor plus ein oder zwei socat-Sidecars, die lokale TCP-Ports in Onion-Services übersetzten — genau das Setup, das ich im IRC-Bouncer-Beitrag beschrieben habe. Das funktioniert, skaliert aber nicht als Muster: Jeder Workload, der eine .onion erreichen oder selbst eine anbieten wollte, brachte seinen eigenen Tor-Prozess und seine eigene Klebeschicht mit. Also habe ich das Ganze zu dem gemacht, was es im Lab sein sollte: einer Custom Resource. tor-operator ist ein eigener, in Rust geschriebener Kubernetes-Operator, der Tor-Konnektivität in beide Richtungen als CRD anbietet.

Von Makefiles zu task: Das Cluster über Anweisungen bedienen

Warum ich die operativen Anweisungen meines Labs von Makefiles auf go-task migriert habe — mit Namespaces, Preconditions, Prompts und einem Überblick, was sich damit alles steuern lässt

Ein Follow-up zum GitOps-Aufbau meines Labs: Wenn das Repository den Zustand beschreibt, brauche ich trotzdem eine Handvoll Anweisungen, um den Cluster zu bedienen — bootstrappen, Secrets rotieren, Backups zurückspielen, Zertifikate erneuern. Lange lebten diese Anweisungen in Makefiles. Heute steckt jede davon in einem go-task -Taskfile, und der Umstieg war eine der besseren kleinen Entscheidungen.

WeeChat als IRC-Client: Nicht-Standard ~/.config/weechat

Wie ich WeeChat mit ZNC und dem Lab-IRC-Stack betreibe — Bars, Buffer, Trigger, Secrets und Scripts

Ich nutze WeeChat als IRC-Frontend im Zusammenspiel mit dem ZNC + InspIRCd-Setup im Lab.

WeeChat im Lab — buflist links, grau/orange Transcript, Nicklist rechts, Tab **highmon**.

Setup#

Für die deklarative Konfiguration und den Rollout verwende ich Home-Manager — wie WeeChat dabei als reproduzierbares Nix-Artefakt entsteht und sich am Bouncer einklinkt, habe ich separat beschrieben . Hier geht es um die Konfiguration selbst. Mein Flake zur Verwaltung aller Systeme findest du hier ; einen ausführlicheren Blogpost dazu schreibe ich bei Gelegenheit.

Netzwerke und ZNC#

Vier IRC-Server stehen in irc.conf — drei laufen über den Bouncer, einer (Quakenet, mehr Gewohnheit als Vernunft) direkt:

  • libera, hackint und local — den cluster-internen IRCd — erreiche ich über den ZNC-Bouncer, der unter bnc.this-is-fine.social/+6697 via TLS hängt. Für ZNC aktiviere ich zusätzliche IRC-Capabilities (znc.in/server-time-iso, znc.in/self-message, …).
flowchart LR WC[WeeChat] ZNC[ZNC TLS SASL] LAB[bnc.this-is-fine.social] INSP[InspIRCd hydra] QN[irc.quakenet.org plain] WC --> ZNC WC --> LAB LAB --> INSP WC --> QN
Die Serverpasswörter liegen verschlüsselt in ${sec.data} und die Passphrase hierfür wird beim Startup von WeeChat über pass mit passphrase_command = "pass show apps/weechat/passphrase" entschlüsselt.

Layout: Bars und Buffer#

weechat.conf definiert ein eigenes Bar-Set — die Statuszeile unten ist absichtlich weg; Kontext steckt in der Title-Bar: