<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rootless on 0xMax42 - Flatfile-Purist. Autodidakt. Systemdenker.</title><link>https://0xMax42.io/tags/rootless/</link><description>Recent content in Rootless on 0xMax42 - Flatfile-Purist. Autodidakt. Systemdenker.</description><generator>Hugo -- gohugo.io</generator><language>de-de</language><lastBuildDate>Thu, 18 Dec 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://0xMax42.io/tags/rootless/index.xml" rel="self" type="application/rss+xml"/><item><title>Reaktive lokale Dienste mit systemd, UNIX-Sockets und rootlosen Containern</title><link>https://0xMax42.io/p/reaktive-lokale-dienste-mit-systemd-unix-sockets-und-rootlosen-containern/</link><pubDate>Thu, 18 Dec 2025 00:00:00 +0000</pubDate><guid>https://0xMax42.io/p/reaktive-lokale-dienste-mit-systemd-unix-sockets-und-rootlosen-containern/</guid><description>&lt;img src="https://0xMax42.io/p/reaktive-lokale-dienste-mit-systemd-unix-sockets-und-rootlosen-containern/reactive-services.webp" alt="Featured image of post Reaktive lokale Dienste mit systemd, UNIX-Sockets und rootlosen Containern" /&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Status:&lt;/strong&gt; Informelles Referenzdokument / Pattern-Beschreibung&lt;br&gt;
&lt;strong&gt;Zielgruppe:&lt;/strong&gt; Linux-Administratoren, DevOps-/Platform-Engineers, systemd- und Podman-Anwender&lt;br&gt;
&lt;strong&gt;Beispiel-Implementierung:&lt;/strong&gt; &lt;a class="link" href="https://github.com/0xMax42/Reactive-PlantUML" target="_blank" rel="noopener"
&gt;Reactive-PlantUML auf GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="motivation"&gt;Motivation
&lt;/h2&gt;&lt;p&gt;Moderne Entwickler- und Administrationsumgebungen benötigen zunehmend lokale Dienste, die:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reproduzierbar konfiguriert sind,&lt;/li&gt;
&lt;li&gt;keine permanent laufenden Hintergrundprozesse erfordern,&lt;/li&gt;
&lt;li&gt;ohne Root-Rechte betrieben werden können,&lt;/li&gt;
&lt;li&gt;und dennoch sauber in bestehende Systemmechanismen integriert sind.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typische Beispiele sind lokale Vorschau‑Server, Dokumentationsdienste oder Hilfsdienste für IDEs.&lt;/p&gt;
&lt;p&gt;Reactive-PlantUML entstand aus der Beobachtung, dass &lt;strong&gt;systemd&lt;/strong&gt;, &lt;strong&gt;UNIX-Domain-Sockets&lt;/strong&gt; und &lt;strong&gt;rootlose Container&lt;/strong&gt; bereits alle notwendigen Bausteine bereitstellen, um solche Dienste &lt;em&gt;reaktiv&lt;/em&gt; und &lt;em&gt;bedarfsorientiert&lt;/em&gt; zu betreiben – ohne zusätzliche Infrastruktur oder Spezialframeworks.&lt;/p&gt;
&lt;p&gt;Dieses Dokument beschreibt das daraus abgeleitete &lt;strong&gt;Betriebsmuster&lt;/strong&gt;, nicht die konkrete PlantUML-Implementierung.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="grundprinzipien-des-musters"&gt;Grundprinzipien des Musters
&lt;/h2&gt;&lt;p&gt;Das hier beschriebene Muster basiert auf folgenden Invarianten:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rootless by default&lt;/strong&gt;
Alle Komponenten laufen als &lt;em&gt;systemd user services&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Socket-Aktivierung statt Daemons&lt;/strong&gt;
Dienste starten ausschließlich bei tatsächlicher Nutzung.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Explizite Port-Verantwortung&lt;/strong&gt;
Die Zuordnung von TCP-Ports erfolgt bewusst durch den Benutzer.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Keine internen TCP-Ports&lt;/strong&gt;
Interne Kommunikation erfolgt ausschließlich über UNIX-Domain-Sockets.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Automatisches Idle-Shutdown&lt;/strong&gt;
Dienste beenden sich nach Inaktivität selbstständig.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reproduzierbarkeit vor Magie&lt;/strong&gt;
Alle Abhängigkeiten und Artefakte sind versioniert und überprüfbar.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="architekturüberblick"&gt;Architekturüberblick
&lt;/h2&gt;&lt;p&gt;Der Datenfluss folgt einem strikt linearen Modell:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client (Browser, IDE, CLI)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ TCP (lokaler, benutzerdefinierter Port)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemd .socket (User-Unit)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemd-socket-proxyd
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ UNIX-Domain-Socket (%t/plantuml/&amp;lt;port&amp;gt;.sock)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rootloser Podman-Container
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Applikation (z. B. PlantUML HTTP-Server)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Wesentliche Beobachtung:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Kein Bestandteil kennt mehr Kontext als notwendig.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="rolle-der-einzelnen-komponenten"&gt;Rolle der einzelnen Komponenten
&lt;/h2&gt;&lt;h3 id="systemd-socket-units-user"&gt;systemd Socket Units (User)
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Definieren ausschließlich den extern sichtbaren TCP-Port&lt;/li&gt;
&lt;li&gt;Starten keinerlei Logik&lt;/li&gt;
&lt;li&gt;Der Instanzname entspricht direkt dem Port (&lt;code&gt;plantuml@8080.socket&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dies erzwingt eine explizite, konfliktfreie Portwahl durch den Benutzer.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="systemd-socket-proxyd"&gt;systemd-socket-proxyd
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Übernimmt die Brückenfunktion zwischen TCP und UNIX-Socket&lt;/li&gt;
&lt;li&gt;Wartet implizit auf die Verfügbarkeit des Ziel-Sockets&lt;/li&gt;
&lt;li&gt;Beendet sich automatisch nach Inaktivität (&lt;code&gt;--exit-idle-time&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wichtig:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;systemd-socket-proxyd&lt;/code&gt; ist zustandslos und enthält keinerlei Anwendungslogik.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id="podman-container-quadlet"&gt;Podman-Container (Quadlet)
&lt;/h3&gt;&lt;p&gt;Der Container:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;läuft rootlos&lt;/li&gt;
&lt;li&gt;besitzt &lt;strong&gt;keinen exponierten TCP-Port&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;erzeugt und verwaltet ausschließlich einen UNIX-Domain-Socket&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Der Socket wird über ein &lt;code&gt;RuntimeDirectory&lt;/code&gt; bereitgestellt und per Volume in den Container gemountet.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="interne-socket-brücke-socat"&gt;Interne Socket-Brücke (socat)
&lt;/h3&gt;&lt;p&gt;Innerhalb des Containers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;stellt die Applikation lokal einen TCP-Port bereit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;socat&lt;/code&gt; bridged diesen Port zu einem UNIX-Socket&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dieses Detail ist austauschbar und &lt;strong&gt;kein Bestandteil des Musters&lt;/strong&gt; – entscheidend ist lediglich, dass:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;die Container-Grenze ausschließlich über einen UNIX-Socket überschritten wird.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="health-checks-und-zustandsmodell"&gt;Health Checks und Zustandsmodell
&lt;/h2&gt;&lt;p&gt;Health Checks erfolgen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;über den UNIX-Socket&lt;/li&gt;
&lt;li&gt;ohne Nutzung externer Ports&lt;/li&gt;
&lt;li&gt;sowohl während des Starts als auch im laufenden Betrieb&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Der Container meldet seine Bereitschaft explizit an systemd (&lt;code&gt;Notify=healthy&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Damit entsteht ein klares Zustandsmodell:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Socket offen&lt;/em&gt; → Anfrage möglich&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Container healthy&lt;/em&gt; → Dienst verfügbar&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Idle&lt;/em&gt; → automatisches Herunterfahren&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="installation-und-betrieb"&gt;Installation und Betrieb
&lt;/h2&gt;&lt;p&gt;Das Muster ist distributionsneutral, lässt sich aber besonders gut über Debian-Pakete ausrollen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;systemd-User-Units&lt;/li&gt;
&lt;li&gt;Podman-Quadlets&lt;/li&gt;
&lt;li&gt;Container-Build-Dateien&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nach Installation ist &lt;strong&gt;keine Aktivität erforderlich&lt;/strong&gt;, bis der Benutzer bewusst einen Socket aktiviert:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemctl --user &lt;span class="nb"&gt;enable&lt;/span&gt; --now plantuml@8080.socket
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="abgrenzung-und-bewusste-nicht-ziele"&gt;Abgrenzung und bewusste Nicht-Ziele
&lt;/h2&gt;&lt;p&gt;Dieses Muster versucht ausdrücklich &lt;strong&gt;nicht&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;klassische Service-Orchestrierung zu ersetzen&lt;/li&gt;
&lt;li&gt;Netzwerk-Namensräume zu abstrahieren&lt;/li&gt;
&lt;li&gt;bestehende Init-Systeme zu umgehen&lt;/li&gt;
&lt;li&gt;neue Sicherheitsmodelle einzuführen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Es nutzt ausschließlich:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bestehende systemd-Mechanismen&lt;/li&gt;
&lt;li&gt;etablierte UNIX-Prinzipien&lt;/li&gt;
&lt;li&gt;klar definierte Verantwortlichkeiten&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="übertragbarkeit-des-musters"&gt;Übertragbarkeit des Musters
&lt;/h2&gt;&lt;p&gt;Obwohl Reactive-PlantUML der konkrete Anwendungsfall ist, eignet sich das Muster u. a. für:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lokale Preview-Server&lt;/li&gt;
&lt;li&gt;Dokumentationsdienste&lt;/li&gt;
&lt;li&gt;Entwicklungs-Backends&lt;/li&gt;
&lt;li&gt;Hilfsdienste für IDEs&lt;/li&gt;
&lt;li&gt;kurzlebige Werkzeuge mit Netzwerkbedarf&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Die konkrete Applikation ist austauschbar.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="fazit"&gt;Fazit
&lt;/h2&gt;&lt;p&gt;Reactive-PlantUML zeigt kein neues Werkzeug, sondern ein &lt;strong&gt;ruhiges Zusammenspiel bestehender Mechanismen&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Das Muster ist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;transparent&lt;/li&gt;
&lt;li&gt;reproduzierbar&lt;/li&gt;
&lt;li&gt;wartbar&lt;/li&gt;
&lt;li&gt;und bewusst unspektakulär&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oder anders formuliert:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Es passiert nur genau das, was passieren muss – und nichts darüber hinaus.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description></item></channel></rss>