#cosign

fabric: Eine Machbarkeitsstudie für ein selbstheilendes P2P-Mesh

Wie finden sich Knoten, wenn Adressen wechseln, Verbindungen abbrechen und kein zentraler Dienst die Topologie kennt? fabric ist meine Forschungsplattform für Peer-Discovery, Route-Healing, mehrstufige Transportwege und klar begrenztes Vertrauen. Dieser Beitrag beschreibt, was bereits funktioniert, wo die Selbstheilung heute endet und warum gerade diese Grenze interessant ist.

Ein Mesh ist auf dem Whiteboard immer gesund. Ein paar Kreise, einige Linien dazwischen, vielleicht noch eine Wolke für „das Internet“ — fertig ist das dezentrale Netz. Interessant wird es erst, wenn man eine Linie wegradiert. Oder drei. Wenn ein Knoten umzieht, eine Adresse nur aus einem privaten Netz erreichbar ist, UDP plötzlich verschwindet und niemand mehr zuverlässig sagen kann, welcher Weg zum Ziel noch existiert.

Genau dort beginnt fabric. Das Projekt untersucht, ob sich aus wenigen, bewusst begrenzten Bausteinen ein Peer-to-Peer-Netz zusammensetzen lässt, das neue Teilnehmer sicher aufnimmt, seine Nachbarn selbst entdeckt, indirekte Wege lernt und veraltete Routen wieder überprüft. Nicht als fertiges Produkt und nicht als Versprechen, jedes kaputte Netz magisch zu reparieren, sondern als Machbarkeitsstudie für Discovery und Auto-Healing: ausführbar, testbar und offen genug, dass auch die Lücken sichtbar bleiben.

Ein CI-Broker für Radicle, der wirklich baut — die Reise durch jede Wand

Vor zwei Wochen stand der Plan: ein CI-Broker, der auf Patch-Events meiner Radicle-Seed-Node hört, in-cluster baut und signiert. Das Diagramm war sauber. Die Realität war ein wochenlanger Kampf mit cib-Entrypoints, Flux, das meine Shell-Variablen auffraß, stale :latest-Tags, rootless buildah, das in Kubernetes prinzipiell nicht geht, und einem binfmt_misc-Handler, der auf Kernel 6.x immer wieder verschwand. Hier ist jede Wand, gegen die ich gelaufen bin — und wie der Broker am Ende doch baut.

In Radicle CI — eine Pipeline, die auf Patches reagiert habe ich den Plan beschrieben: Meine Seed-Node läuft in-cluster und führt einen Event-Stream — jede neue Patch-Ref, jedes COB-Update wird sichtbar. Ein CI-Broker abonniert diesen Stream, übersetzt ein Patch-Event in einen Build und schreibt das Ergebnis zurück auf den Patch. Sauberes Diagramm, klare Idee, ein offenes Trust-Problem, das ich für lösbar hielt.

Was dieser Beitrag erzählt, ist die Lücke zwischen dem Diagramm und einem grünen Häkchen. Sie war größer, als mir lieb war. Zwischen „der Broker ist deployt" und „der Broker baut wirklich ein signiertes Image" lagen rund zwei Dutzend Commits, die fast alle fix: heißen — und jeder davon steht für eine Wand, gegen die ich gelaufen bin. Kein Architektur-Pitch, sondern ein Reisebericht durch Entrypoints, die nicht stimmen, durch Flux, das meine Shell-Variablen frisst, durch rootless buildah, das in Kubernetes prinzipiell nicht funktioniert, und durch einen Kernel, der meinen QEMU-Handler immer wieder vergaß.

Radicle CI — eine Pipeline, die auf Patches reagiert

Der Code des Labs liegt in einer P2P-Forge, die CI aber noch nicht: Builds laufen post-merge auf einer externen .build.yml. Wie ein Radicle-CI-Broker das schließt — er hört auf die Patch-Events der eigenen Seed-Node, baut und signiert in-cluster und schreibt das Ergebnis zurück auf den Patch. Plus das eigentlich harte Problem: Vertrauen in einer Forge ohne Owner.
Stand: Design/Roadmap. Issue 7f834f9 : „Wire Radicle CI once the lab repo is published (patches already wired)." Die Seed-Node läuft in-cluster, der Patch-Workflow steht — der CI-Broker ist das letzte fehlende Stück. Dieser Beitrag beschreibt, wie er andocken soll.

In Von SourceHut zu Radicle ist der Lab-Code in eine Peer-to-Peer-Forge umgezogen: keine zentrale Instanz mehr, Patches und Issues leben als signierte Collaborative Objects (COBs), Flux deployt vom kanonischen main. Ein Faden blieb dort offen — und genau um den geht es hier: Radicle ist eine Forge, kein CI-System. Der Code liegt P2P, der Build aber noch nicht.

Das OCI-Format und der Wechsel von Harbor zu Zot

Warum OCI mehr ist als nur Docker-Images, weshalb mein Build daemonlos mit Skopeo und Crane statt docker push arbeitet — und wie Zot mein schwergewichtiges Harbor abgelöst hat

„Container-Image“ ist im Sprachgebrauch fast zum Synonym für „Docker“ geworden — dabei ist das Format längst von Docker entkoppelt und in der Open Container Initiative (OCI) standardisiert. Dieser Beitrag erklärt, was das konkret bringt, warum meine Build-Pipeline deshalb mit Skopeo und Crane statt docker push arbeitet, und wie ich meine bisherige Harbor-Registry gegen das deutlich schlankere Zot getauscht habe.

Signierte Images erzwingen: Cosign in der Pipeline, Kyverno im Cluster

Wie selbstgebaute OCI-Images in der CI mit cosign signiert und im Cluster von Kyverno-Policies im Enforce-Modus verifiziert werden

Wer eigene Container-Images baut und in einer eigenen Registry hält, hat ein Vertrauensproblem in petto: Woher weiß der Cluster, dass ein Image wirklich aus meiner Pipeline stammt und nicht unterwegs manipuliert wurde? Meine Antwort ist eine geschlossene Kette aus zwei Hälften — cosign signiert in der CI, Kyverno verifiziert im Cluster und lässt nichts Unsigniertes durch.