Voraussetzungen
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Bekannte Coding-Tools dieser Art kommen aktuell vor allem von drei großen KI-Firmen: Anthropic mit Claude Code, OpenAI mit Codex CLI und Google mit Antigravity CLI. Alle drei funktionieren nach einem ähnlichen Grundprinzip, unterscheiden sich aber im verwendeten KI-Modell. Dieses Kapitel konzentriert sich auf Claude Code.
Installation
Bevor man eines der drei Tools benutzen kann, muss man es zuerst auf dem eigenen Computer installieren. Dafür öffnet man ein Terminal (ein Fenster, in das man Befehle als Text eingibt) und gibt einen einzigen Befehl ein, der das Programm herunterlädt und einrichtet.
Claude Code (Anthropic)
Unter macOS, Linux oder in WSL (einer Linux-Umgebung innerhalb von Windows) genügt dieser Befehl:
curl -fsSL https://claude.ai/install.sh | bash
Unter Windows in der PowerShell lautet er:
irm https://claude.ai/install.ps1 | iex
Danach startet man das Programm mit dem Befehl claude und meldet sich beim ersten Start im Browser mit einem Claude-Account an (Pro, Max, Team oder Enterprise; der kostenlose Claude.ai-Zugang reicht dafür nicht aus).
Codex CLI (OpenAI)
Codex CLI installiert man ebenfalls mit einem Befehl im Terminal:
curl -fsSL https://chatgpt.com/codex/install.sh | sh
Alternativ geht es auch über npm (ein Paketverwalter für JavaScript-Programme, der zusammen mit Node.js installiert wird):
npm install -g @openai/codex
Gestartet wird Codex CLI mit dem Befehl codex. Beim ersten Start meldet man sich entweder mit einem ChatGPT-Account (Plus, Pro, Business, Edu oder Enterprise) oder mit einem OpenAI-API-Schlüssel an.
Antigravity CLI (Google)
Unter macOS und Linux installiert man Antigravity CLI mit:
curl -fsSL https://antigravity.google/cli/install.sh | bash
Unter Windows in der PowerShell:
irm https://antigravity.google/cli/install.ps1 | iex
Gestartet wird das Programm mit dem Befehl agy. Beim ersten Start meldet man sich mit einem Google-Konto an oder benutzt stattdessen einen Gemini-API-Schlüssel.
Hinweis zur Installation
Alle drei Befehle laden ein Skript herunter und führen es direkt aus. Das ist bei allen drei großen Anbietern so üblich, setzt aber Vertrauen in die Quelle voraus. Wer das Skript vorher ansehen möchte, kann es zuerst herunterladen und öffnen, statt es sofort auszuführen.
Claude Code lässt sich außerdem auf unterschiedliche Arten benutzen. Welche davon die passende ist, hängt davon ab, wie man am liebsten arbeitet.
Direkt im Terminal
Die ursprüngliche und flexibelste Art ist, Claude Code direkt im Terminal zu benutzen (einem Fenster, in dem man Befehle als Text eingibt statt mit der Maus zu klicken). Dabei hat man die volle Kontrolle über den eigenen Code: Jeder Befehl und jede Änderung lässt sich genau nachvollziehen. Der Einstieg ist dafür etwas anspruchsvoller als bei den anderen Möglichkeiten, weil man sich zunächst an die Arbeit im Terminal gewöhnen muss.
In Visual Studio Code
Wer lieber in einer gewohnten Programmierumgebung bleibt, kann Claude Code auch über die Erweiterung für Visual Studio Code benutzen (ein weit verbreitetes, kostenloses Programm zum Schreiben von Code). Claude Code fügt sich dort gut ein und lässt sich bedienen, ohne dass man das Terminal einzeln öffnen muss. Das macht den Einstieg leichter, vor allem für alle, die Visual Studio Code bereits kennen.
Über die Claude-Desktop-App
Eine dritte Möglichkeit ist die Claude-Desktop-App, das allgemeine Chatprogramm von Anthropic. Sie eignet sich gut für allgemeine Aufgaben und Unterhaltungen mit Claude, ist für reine Programmieraufgaben aber weniger gut geeignet als Claude Code direkt im Terminal oder die Erweiterung für Visual Studio Code.
Fazit
Für den Einstieg eignet sich die Erweiterung für Visual Studio Code am besten, wenn man bereits mit diesem Programm arbeitet. Wer die volle Kontrolle über jeden einzelnen Schritt haben möchte, benutzt Claude Code direkt im Terminal. Die Claude-Desktop-App ist dagegen eher für allgemeine Aufgaben gedacht als fürs Programmieren.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Desktop-Agenten
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Ein Desktop-Agent ist ein Programm, das nicht nur im Chat antwortet, sondern selbstständig Aufgaben auf dem eigenen Computer erledigt: Dateien lesen, anlegen oder ändern, im Browser klicken oder mehrere Schritte hintereinander ausführen, ohne dass man jeden einzelnen davon selbst anstößt. Anders als bei Claude Code, Codex CLI oder Antigravity CLI (siehe Voraussetzungen) läuft ein Desktop-Agent nicht im Terminal, sondern in einer eigenen grafischen Anwendung mit Fenstern und Schaltflächen.
Drei bekannte Beispiele dafür sind aktuell:
- Claude Cowork (Anthropic)
- ChatGPT Agent (OpenAI)
- Antigravity 2.0 (Google)
Claude Cowork (Anthropic)
Claude Cowork ist ein Modus innerhalb der Claude-Desktop-App, neben den Modi Chat und Code. Man wählt einen Ordner auf dem eigenen Computer aus, und Claude arbeitet darin: Es liest vorhandene Dateien, legt neue an und ändert sie, während es eine Aufgabe abarbeitet — mit möglichst wenig Rückfragen zwischendurch. Cowork richtet sich damit vor allem an Anwender ohne Programmiererfahrung, die von den Fähigkeiten profitieren möchten, die Claude Code bisher nur Entwicklern bot. Die Claude-Desktop-App mit Cowork gibt es für macOS und Windows, ab einem bezahlten Claude-Plan.
ChatGPT Agent (OpenAI)
ChatGPT Agent ist Teil der ChatGPT-Desktop-App und bündelt dort mehrere Bereiche in einem Fenster: Chat für normale Unterhaltungen, Work für Aufgaben im Alltag und Codex für Programmieraufgaben mit lokalen Dateien. Im Work-Bereich kann der Agent über eine Funktion namens „Computer Use" den Computer im Hintergrund bedienen: klicken, tippen und Dateien verschieben, ähnlich wie ein Mensch es tun würde. Über Erweiterungen lässt sich ChatGPT Agent außerdem mit Diensten wie E-Mail, Kalender oder Cloud-Speicher verbinden, um Aufgaben über mehrere Programme hinweg zu erledigen.
Antigravity 2.0 (Google)
Antigravity 2.0 ist eine eigenständige Desktop-Anwendung von Google für macOS, Linux und Windows. Sie dient als zentrale Steuerung für mehrere KI-Agenten gleichzeitig: Man kann darin verschiedene Agenten starten, ihren Fortschritt beobachten und auch Aufgaben einplanen, die zu einem späteren Zeitpunkt automatisch laufen.
Antigravity 2.0 installieren
Auf Linux gibt es bei der Installation eine Besonderheit, die man kennen sollte: Die Anwendung bringt eine Sandbox-Komponente namens chrome-sandbox mit, die aus Sicherheitsgründen bestimmte Rechte braucht, um Browser-Funktionen nutzen zu können. Ohne diese Rechte startet Antigravity entweder gar nicht oder nur eingeschränkt.
Der Datei muss dafür der Benutzer root als Besitzer zugewiesen werden, und sie braucht die Rechte 4755 (das sogenannte Setuid-Bit, das der Datei erlaubt, kurzzeitig mit Root-Rechten zu laufen). Dazu wechselt man im Terminal in den entpackten Programmordner und führt folgende Befehle aus:
cd /home/thorsten/Downloads/Antigravity/Antigravity-x64
sudo chown root:root chrome-sandbox
sudo chmod 4755 chrome-sandbox
./antigravity
Diese Schritte sind nur unter Linux nötig. Unter macOS und Windows lässt sich Antigravity 2.0 wie gewohnt installieren und direkt starten.
Fazit
Neben diesen drei Beispielen gibt es bereits weitere Desktop-Agenten, und es werden mit großer Sicherheit noch mehr dazukommen — dieses Handbuch kann und will keine vollständige, ständig aktuelle Liste davon sein. Wichtiger als die Anzahl der verfügbaren Werkzeuge ist ein Grundsatz, der für alle gilt: Ein Desktop-Agent kann viele Schritte selbstständig ausführen, doch die Kontrolle über wichtige Entscheidungen sollte am Ende immer beim Menschen bleiben, etwa beim Aufbau einer Webseite oder einer Anwendung. Wer Ergebnisse ungeprüft übernimmt, überlässt der KI mehr, als ihr gut tut. Ein Sprachmodell wird außerdem nicht von selbst besser, nur weil man es häufiger benutzt — es hilft, die eigenen Grundlagen zu verstehen, statt sich blind auf Vorschläge zu verlassen. Die folgenden Kapitel zeigen deshalb, wie man mit einem Desktop-Agenten gezielt Wissen aufbaut und sammelt, statt ihm die Arbeit einfach vollständig zu überlassen.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Freies Wissen
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Bevor man eine Webseite oder eine Wissenssammlung aufbaut, sollte man wissen, welche Werkzeuge es dafür überhaupt gibt. „Freies Wissen" meint hier zweierlei: Wissen, das frei zugänglich ist (jeder darf es lesen und weiterverwenden), und Programme, deren Quelltext offenliegt und die man kostenlos selbst betreiben kann (sogenannte Open-Source-Software). Dieses Kapitel ist ein geordneter Überblick über solche Programme, sortiert danach, wofür man sie einsetzt: Wissen schreiben, Daten strukturieren, offene Daten und Karten verwalten, Notizen vernetzen und über den eigenen Bestand suchen.
Der Überblick soll keine vollständige, ständig aktuelle Liste sein. Er soll helfen, die Landschaft zu kennen, bevor man sich für ein Werkzeug entscheidet.
Wiki- und Wissensdatenbank-Software
Ein Wiki ist eine Webseite, deren Seiten viele Menschen gemeinsam im Browser bearbeiten können.
- MediaWiki — die Software, mit der auch die Wikipedia läuft. Sie ist auf sehr viele Seiten und viele Bearbeiter ausgelegt und speichert zu jeder Seite die komplette Änderungsgeschichte.
- XWiki — ebenfalls ein Wiki, das sich zusätzlich um feste Datenfelder und kleine Anwendungen erweitern lässt. Damit kann man nicht nur Fließtext ablegen, sondern auch strukturierte Einträge, etwa eine Liste von Geräten mit festen Angaben.
Strukturierte Daten und Linked Open Data
„Strukturierte Daten" bedeutet, dass Informationen nicht als Fließtext, sondern in festen Bausteinen gespeichert werden, die auch ein Computer auswerten kann. „Linked Open Data" heißt, dass diese Bausteine offen zugänglich sind und untereinander verknüpft werden, sodass aus vielen Quellen ein Netz an Wissen entsteht.
- Wikibase — die Software hinter Wikidata, der Datensammlung der Wikipedia. Wissen wird hier als einzelne Objekte mit Aussagen gespeichert (zum Beispiel: Objekt „Berlin", Aussage „ist Hauptstadt von" → „Deutschland").
- OpenRefine — ein Werkzeug, um unordentliche Tabellen aufzuräumen: doppelte Schreibweisen zusammenführen, Fehler finden, Spalten vereinheitlichen.
- Apache Jena — eine Sammlung von Bausteinen für Programmierer, um mit verknüpften Daten zu arbeiten.
- Fuseki — der Datenbank-Server, der zu Jena gehört. Er beantwortet Anfragen an die Daten über das Internet, in der Abfragesprache SPARQL (der üblichen Sprache, um verknüpfte Daten abzufragen).
- QLever — ein besonders schneller Server für dieselbe Art von Anfragen. Er kann sehr große Datenmengen bis hin zur kompletten Wikidata auf einem einzelnen Rechner verarbeiten.
Offene Daten und Karten
Offene Daten sind Datensätze, die jeder herunterladen und weiterverwenden darf, oft von Behörden oder aus der Forschung.
- CKAN — Software für Datenportale. Damit betreiben zum Beispiel Verwaltungen ihre offenen Datenkataloge: Jeder Datensatz bekommt eine Beschreibung, und Besucher können darin suchen.
- OpenStreetMap — eine freie Weltkarte, an der jeder mitarbeiten kann. Die Kartendaten sind offen und dürfen in eigenen Projekten benutzt werden.
- Dataverse — ein Ablageort für Forschungsdaten. Jeder Datensatz erhält einen dauerhaften Link, sodass andere ihn zitieren können.
- DataHub — eine Plattform, um Datensätze zu finden, zu veröffentlichen und miteinander zu teilen.
Docs-as-Code und statische Webseiten
„Docs as Code" bedeutet: Man schreibt Texte in einfachen Textdateien (meist im Format Markdown) und lässt daraus mit einem Werkzeug automatisch eine fertige Webseite bauen. Die Texte lassen sich so genauso versionieren und prüfen wie Programmcode.
- mdBook — das Werkzeug, mit dem auch dieses Handbuch gebaut wird. Aus einem Ordner mit Markdown-Dateien entsteht ein durchsuchbares HTML-Buch.
- MkDocs — baut aus Markdown-Dateien eine Dokumentations-Webseite. „Material" ist die verbreitetste Gestaltungsvorlage dafür und bringt Suche, Navigation und ein aufgeräumtes Aussehen mit.
Moderne Wissensdatenbanken
Neben den klassischen Wikis gibt es neuere Programme, die eher wie ein gemeinsames Notizbuch für ein Team funktionieren. Sie sind bewusst als freie Alternativen zu bekannten kommerziellen Diensten gedacht.
- BookStack — ordnet Inhalte in einer einfachen Gliederung aus Regalen, Büchern, Kapiteln und Seiten. Der Einstieg ist leicht, weil die Struktur vorgegeben ist.
- Outline — eine Wissensdatenbank für Teams mit schnellem Editor und guter Suche.
- Docmost — ähnlich wie Outline, mit Seiten, die sich beliebig verschachteln lassen, und gemeinsamem Bearbeiten in Echtzeit.
- AppFlowy — verbindet Notizen mit Tabellen und Aufgabenlisten in einem Programm.
Vernetztes Wissen und Notizen
Diese Programme sind für einzelne Personen gedacht. Ihr gemeinsamer Gedanke: Notizen werden nicht nur in Ordnern abgelegt, sondern untereinander verlinkt, sodass mit der Zeit ein persönliches Wissensnetz entsteht.
- Logseq — arbeitet mit kurzen, eingerückten Stichpunkten und Verweisen zwischen ihnen. Die Notizen bleiben als normale Dateien auf dem eigenen Rechner.
- Joplin — ordnet Notizen in Notizbüchern, schreibt sie in Markdown und kann sie zwischen mehreren Geräten abgleichen.
- TriliumNext Notes — legt Notizen in einem beliebig tiefen Baum ab und eignet sich gut für eine große persönliche Wissenssammlung. Es wird von einer Gemeinschaft weiterentwickelt, nachdem das ursprüngliche Trilium Notes nur noch gepflegt, aber nicht mehr ausgebaut wird.
- Anytype — speichert Wissen als verknüpfte Objekte mit festen Feldern und legt alle Daten verschlüsselt auf dem eigenen Gerät ab.
Suche über das eigene Wissen
Wenn eine Sammlung wächst, braucht man eine gute Suche. Die folgenden Programme sind Suchmaschinen, die man selbst betreibt und in eine eigene Webseite oder Anwendung einbaut.
- OpenSearch — eine leistungsfähige Suchmaschine für große Datenmengen. Sie ist aus der bekannten Software Elasticsearch hervorgegangen und steht unter einer freien Lizenz.
- Meilisearch — eine schlanke, schnelle Suchmaschine, die sich leicht einrichten lässt und schon während des Tippens Treffer anzeigt.
- Typesense — ähnlich wie Meilisearch: schnell, verzeiht Tippfehler und ist auf einfache Bedienung ausgelegt.
Warum überhaupt Wissen sammeln?
Wissen ist für ein Unternehmen wie für eine einzelne Person zu einem wichtigen Gut geworden. Zwei Grundfragen stehen dabei am Anfang, und beide sollte man klären, bevor man mit dem Bauen beginnt.
Die erste Frage: Wie strukturiert man die Daten, damit man sie später wiederfindet? Und wie organisiert man sie so, dass sie über Jahre nutzbar bleiben? Wer diese Frage überspringt und einfach loslegt, muss oft alles noch einmal neu aufbauen. Eine ungünstig angelegte Struktur lässt sich später nur mühsam reparieren. Deshalb lohnt es sich, hier zuerst nachzudenken und nicht sofort die erste Lösung zu nehmen.
Die zweite Frage: Wie veröffentlicht man Inhalte, ohne gegen Gesetze zu verstoßen? Besonders wichtig ist das Urheberrecht. Das deutsche Urheberrecht gilt als vergleichsweise streng; ein pauschales „fair use" wie im US-Recht gibt es hier nicht. Fremde Texte, Bilder oder Übersetzungen dürfen nicht einfach übernommen werden, auch nicht in leicht umgeschriebener Form. Man kann diese Strenge als Nachteil sehen oder als Schutz der eigenen Arbeit; in jedem Fall muss man sie einplanen.
Viele Einzelfragen bleiben am Anfang offen: unter welcher Lizenz man die eigenen Inhalte stellt, wie man Quellen kennzeichnet, wie man KI-Unterstützung transparent macht. Das ist normal. Wichtig ist die Reihenfolge: erst Wissen sammeln, dann strukturieren, dann veröffentlichen. Ohne diese Grundlage entsteht keine wirklich gute Seite.
Fazit
Für jede der genannten Aufgaben gibt es mehrere freie Programme, und es kommen laufend neue dazu. Man muss sie nicht alle kennen. Hilfreich ist vor allem, die Gruppen auseinanderzuhalten: Wiki für gemeinsam bearbeiteten Text, strukturierte Daten für maschinenlesbare Bausteine, Docs-as-Code für Text, der wie Code gepflegt wird, Notiz-Programme für das persönliche Wissensnetz und eine eigene Suchmaschine, sobald die Sammlung groß wird. Wer diese Einteilung im Kopf hat, kann für ein konkretes Vorhaben gezielt das passende Werkzeug auswählen, statt sich vom ersten bekannten Namen leiten zu lassen.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Inhalts-Software selbst betreiben
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Wer eine eigene Wissenssammlung aufbaut, kann die dafür nötigen Programme mieten oder selbst betreiben. „Selbst betreiben" (oft „Selfhosting" genannt) heißt: Die Software läuft auf einem Rechner, über den man selbst bestimmt, statt auf den Servern eines fremden Anbieters. Der Vorteil ist, dass die Inhalte im eigenen Haus bleiben und niemand sie abschalten oder verteuern kann. Der Preis dafür ist etwas mehr Arbeit bei Einrichtung und Pflege.
Dieses Kapitel beschreibt einen erprobten Satz an Programmen für eine solche Sammlung. Jedes Programm hat eine klare Aufgabe. Zusammen ergeben sie eine Wissensdatenbank, in der man Texte schreibt, schnell darin sucht und Fragen in normaler Sprache stellen kann.
Die Bausteine im Überblick
| Programm | Aufgabe |
|---|---|
| MediaWiki | Ort, an dem die Texte geschrieben und gelesen werden |
| PostgreSQL | Datenbank, die alle Inhalte dauerhaft speichert |
| Meilisearch | Volltextsuche über die Wörter in den Texten |
| pgvector | Erweiterung von PostgreSQL für die Suche nach Bedeutung |
| Ollama | führt Sprachmodelle auf dem eigenen Rechner aus |
Alle fünf sind Open-Source-Software: Ihr Quelltext liegt offen, und man darf sie kostenlos benutzen und selbst betreiben.
MediaWiki – der Ort für die Texte
MediaWiki ist die Software, mit der auch die Wikipedia läuft. Sie stellt eine Webseite bereit, deren Seiten man direkt im Browser bearbeitet. Zu jeder Seite wird die komplette Änderungsgeschichte gespeichert, sodass sich jeder frühere Stand wiederherstellen lässt. Seiten lassen sich untereinander verlinken und in Kategorien einordnen.
MediaWiki ist auf viele Seiten und viele Bearbeiter ausgelegt und seit Jahren bewährt. Für eine Wissenssammlung, die wachsen soll, ist das eine solide Grundlage. Die Software selbst kümmert sich nur um das Anzeigen und Bearbeiten der Seiten. Wo die Texte tatsächlich liegen, ist ihre Sache nicht – dafür ist die Datenbank zuständig.
PostgreSQL – die Datenbank darunter
Eine Datenbank ist ein Programm, das Daten geordnet ablegt und auf Anfrage schnell wieder herausgibt. MediaWiki speichert dort jede Seite, jede Version und jede Einstellung. Ohne Datenbank gäbe es nichts anzuzeigen.
MediaWiki kann mehrere Datenbanken verwenden. Hier fällt die Wahl auf PostgreSQL, weil es besonders zuverlässig ist und sich um zusätzliche Funktionen erweitern lässt. Eine davon – die Suche nach Bedeutung – wird weiter unten wichtig. Für den Anfang genügt der Gedanke: PostgreSQL ist der Tresor, in dem alle Inhalte liegen, und MediaWiki ist die Theke, an der man sie bekommt.
Meilisearch – die schnelle Volltextsuche
Sobald eine Sammlung ein paar Hundert Seiten hat, braucht man eine gute Suche. Die eingebaute Suche von MediaWiki ist einfach und wird bei vielen Seiten langsam. Deshalb übernimmt ein eigenes Programm diese Aufgabe: Meilisearch.
Meilisearch ist eine schlanke Suchmaschine, die man selbst betreibt. Sie führt ein eigenes Verzeichnis aller Wörter in allen Texten (einen sogenannten Index) und liefert Treffer schon während des Tippens. Auch Tippfehler verzeiht sie: Wer „Meiliserch" eingibt, findet trotzdem die richtigen Seiten. Meilisearch durchsucht dabei die Wörter selbst – es findet also genau das, wonach man buchstäblich gefragt hat.
pgvector – die Suche nach Bedeutung
Manchmal weiß man nicht das genaue Wort, das im Text steht. Man sucht „Auto reparieren", aber die passende Seite heißt „Wagen instand setzen". Eine reine Wortsuche findet sie nicht. Hier hilft die Suche nach Bedeutung, auch semantische Suche genannt.
Dafür wird jeder Text in eine lange Zahlenreihe umgerechnet, die seinen Inhalt beschreibt (fachlich: ein „Vektor" oder „Embedding"). Texte mit ähnlicher Bedeutung ergeben ähnliche Zahlenreihen. Sucht man nun etwas, wird auch die Suchanfrage in eine solche Zahlenreihe umgerechnet, und das System sucht die Texte mit den ähnlichsten Werten.
Diese Zahlenreihen müssen irgendwo gespeichert und schnell verglichen werden. Genau das leistet pgvector, eine Erweiterung für PostgreSQL. Damit wird aus der ohnehin vorhandenen Datenbank zugleich eine Vektordatenbank – ein zweites, getrenntes Programm ist dafür nicht nötig. Wer die Zahlenreihen lieber außerhalb von PostgreSQL verwalten möchte, kann stattdessen eine eigenständige Vektordatenbank einsetzen; für den hier beschriebenen Aufbau reicht pgvector.
In der Praxis kombiniert man beide Suchen: Meilisearch für die genaue Wortsuche, pgvector für die Suche nach Bedeutung. Zusammen finden sie deutlich mehr als jede für sich.
Ollama – Sprachmodelle auf dem eigenen Rechner
Zwei Dinge aus den vorigen Abschnitten brauchen ein Sprachmodell: das Umrechnen der Texte in Zahlenreihen und das Beantworten von Fragen in normaler Sprache. Man könnte dafür einen Online-Dienst benutzen, müsste dann aber jeden Text dorthin schicken. Wer die Inhalte im eigenen Haus behalten will, lässt das Modell ebenfalls selbst laufen.
Ollama ist ein Programm, das genau das einfach macht. Es lädt ein Sprachmodell herunter und stellt es auf dem eigenen Rechner bereit, ansprechbar über eine feste Schnittstelle. Andere Programme – etwa das Modul, das die Zahlenreihen für pgvector erzeugt – fragen dann bei Ollama an, statt bei einem fremden Anbieter.
Für gute Ergebnisse braucht Ollama einen leistungsfähigen Rechner, am besten mit einer starken Grafikkarte. Kleinere Modelle laufen auch auf normaler Hardware, nur langsamer.
Wie die Teile zusammenspielen
Ein typischer Ablauf sieht so aus:
- Jemand schreibt oder ändert eine Seite in MediaWiki.
- Der Text wird in PostgreSQL gespeichert.
- Im Hintergrund meldet MediaWiki die Änderung an Meilisearch, das seinen Wort-Index aktualisiert.
- Ebenfalls im Hintergrund lässt Ollama den Text in eine Zahlenreihe umrechnen, die in pgvector landet.
- Sucht später jemand etwas, fragen Wortsuche (Meilisearch) und Bedeutungssuche (pgvector) parallel, und die Treffer werden zusammengeführt.
- Für eine Frage in normaler Sprache holt sich das System die passenden Seiten aus Schritt 5 und lässt Ollama daraus eine Antwort formulieren.
Jeder Baustein lässt sich einzeln austauschen, ohne die anderen anzufassen: ein anderes Wiki, eine andere Suchmaschine, ein anderes Modell. Das ist der Vorteil klar getrennter Aufgaben.
Fazit
Für eine selbst betriebene Wissenssammlung genügt ein kleiner, überschaubarer Satz an Programmen: MediaWiki als Oberfläche, PostgreSQL als Speicher, Meilisearch für die Wortsuche, pgvector für die Bedeutungssuche und Ollama für die Sprachmodelle. Alle sind quelloffen und kostenlos. Wichtig ist weniger die konkrete Auswahl als das Prinzip dahinter: Jedes Programm macht eine Sache, die Teile sind sauber getrennt, und die Inhalte bleiben auf einem Rechner, über den man selbst bestimmt.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Urheberrecht und Duplicate Content
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Wer eine Wissenssammlung oder eine Webseite veröffentlicht, muss zwei Dinge im Blick behalten. Das erste ist das Urheberrecht: Fremde Texte, Bilder oder Übersetzungen darf man nicht einfach übernehmen, auch nicht in leicht umgeschriebener Form. Das zweite ist der sogenannte Duplicate Content: Wenn derselbe Text fast wortgleich an mehreren Stellen im Internet steht, hält eine Suchmaschine wie Google ihn für eine Dublette und zeigt die eigene Seite schlechter an.
Beide Probleme lassen sich vor der Veröffentlichung prüfen. Dieses Kapitel zeigt, welche freien (quelloffenen) Programme es dafür gibt, wo ihre Grenzen liegen, wie man sich eine eigene Prüfung baut und wie ein KI-Agent dabei hilft. „KI-Agent" meint hier ein Programm mit einem Sprachmodell, das selbstständig Texte liest, im Internet sucht und die Ergebnisse zusammenfasst.
Zwei verschiedene Probleme
Auch wenn beide Prüfungen ähnlich ablaufen, geht es um zwei getrennte Fragen.
- Urheberrecht. Hier lautet die Frage: Stammt eine Passage in Wahrheit aus einer fremden Quelle? Das kann eine wörtliche Übernahme sein, eine eng am Original entlanggeschriebene Umformulierung (eine „Paraphrase") oder eine Übersetzung aus einer anderen Sprache, etwa aus einem fremdsprachigen Wiki. Das deutsche Urheberrecht gilt als streng; ein pauschales „fair use" wie im US-Recht gibt es nicht. Ein Verstoß kann teuer werden.
- Duplicate Content. Hier lautet die Frage: Gibt es den eigenen Text schon fast genauso woanders im Netz? Das ist kein Rechtsproblem, sondern ein Problem für die Auffindbarkeit. Es entsteht auch ohne fremde Quelle, zum Beispiel wenn die eigene Seite unter mehreren Adressen erreichbar ist oder Textbausteine mehrfach verwendet werden.
Die Prüfungen überschneiden sich: Eine wörtlich übernommene Passage ist zugleich ein Urheberrechtsproblem und Duplicate Content. Trotzdem lohnt es sich, beide Ziele getrennt zu benennen, weil die Gegenmaßnahmen andere sind (eine Passage löschen oder neu schreiben gegen Urheberrechtsverstöße; Adressen und Textbausteine aufräumen gegen Duplicate Content).
Warum eine reine Web-Prüfung mit offener Software schwierig ist
Um einen Text gegen „das ganze Internet" zu prüfen, braucht man ein Verzeichnis des ganzen Internets. Ein solches Verzeichnis (einen „Index") pflegen nur die Betreiber großer Suchmaschinen. Kein quelloffenes Programm bringt einen eigenen Web-Index mit.
Daraus folgt eine klare Aufteilung:
- Freie Programme vergleichen Dokumente, die man selbst hat, oder sie vergleichen den eigenen Text gegen eine Sammlung, die man selbst mitbringt (zum Beispiel einen heruntergeladenen Wikipedia-Auszug).
- Für die Prüfung gegen das offene Web gibt es zwei Wege: einen kostenpflichtigen Dienst benutzen (etwa Copyscape) oder sich mit einer Such-Schnittstelle und einem KI-Agenten selbst eine Prüfung bauen. Der zweite Weg wird weiter unten beschrieben.
Freie Programme für den Dokumentvergleich
Diese Programme brauchen kein Internet. Sie sind stark, wenn schon ein Verdacht besteht, welche Quelle infrage kommt, oder wenn man den eigenen Bestand in sich prüfen möchte.
- WCopyfind — ein quelloffenes Programm, das eine Menge von Dokumenten durchsucht und gemeinsame Wortfolgen findet. Man gibt an, ab welcher Länge eine übereinstimmende Wortkette als Treffer gilt (zum Beispiel sechs Wörter am Stück). Das Ergebnis ist ein Bericht, in dem die übereinstimmenden Stellen farbig markiert sind. WCopyfind vergleicht nur Dateien, die man ihm gibt – es sucht nicht im Web. Nützlich zum Beispiel, um alle eigenen Seiten gegen einen heruntergeladenen Auszug eines fremden Wikis zu halten.
- Sherlock — ein Kommandozeilenprogramm, das aus Textausschnitten kurze Kennzeichen (Signaturen) berechnet und Dateien anhand dieser Kennzeichen auf Ähnlichkeit vergleicht. Es findet auch dann Übereinstimmungen, wenn einzelne Wörter geändert wurden.
- JPlag und Dolos — beide sind für Programmcode gedacht, nicht für Fließtext. Wer in seiner Sammlung auch Code-Beispiele veröffentlicht, kann damit prüfen, ob diese aus fremden Projekten stammen.
Für eng angelehnte Paraphrasen und Übersetzungen reicht der reine Wortvergleich oft nicht, weil kaum ein Wort gleich bleibt. Hier hilft die Suche nach Bedeutung: Jeder Absatz wird in eine lange Zahlenreihe umgerechnet, die seinen Inhalt beschreibt (ein „Embedding"). Absätze mit ähnlicher Bedeutung ergeben ähnliche Zahlenreihen, auch bei ganz anderem Wortlaut. Rechnet man die eigenen Absätze und die Absätze einer Vergleichssammlung in solche Zahlenreihen um und sucht die ähnlichsten Paare, findet man auch umformulierte Übernahmen. Wie man Texte lokal in solche Zahlenreihen umrechnet, steht im Kapitel [[inhalt-software-verwalten]].
Eine eigene Web-Prüfung bauen
Die Grundidee kommerzieller Plagiatsprüfer lässt sich mit freien Bausteinen nachbauen. Der Ablauf in Schritten:
- Den eigenen Text zerlegen – in Absätze und Sätze.
- Auffällige Wortfolgen herausziehen. Pro Abschnitt ein paar Ketten von fünf bis acht Wörtern, am besten solche mit seltenen oder ungewöhnlichen Begriffen. Häufige Allerweltssätze taugen nicht, weil es sie überall gibt.
- Wörtlich im Web suchen. Jede Wortkette als exakte Suche (in Anführungszeichen) an eine Such-Schnittstelle schicken. Selbst betreiben lässt sich zum Beispiel SearXNG, eine quelloffene Meta-Suchmaschine, die Anfragen an mehrere öffentliche Suchmaschinen weiterreicht und die Treffer bündelt. Alternativ gibt es kostenpflichtige Such-Schnittstellen. Bei jeder Variante gelten die Nutzungsbedingungen und Tempolimits der befragten Suchmaschinen.
- Treffer sammeln. Gibt es Seiten, auf denen genau dieser Satz steht? Tauchen dieselben Seiten bei mehreren Wortketten auf?
- Verdächtige Seiten gegenlesen. Die gefundenen Seiten laden und Absatz für Absatz gegen den eigenen Text halten.
Das ist im Kern genau das, was ein bezahlter Plagiatsprüfer tut. Der Aufwand steckt im Feinschliff: gute Wortketten auswählen, Fehlalarme aussortieren, das Ganze für viele Seiten automatisieren.
Der KI-Agent: zuerst ein Gesamtdurchgang
Der Ausgangspunkt ist ein einziger, breiter Durchgang über den kompletten Bestand. Dafür braucht der KI-Agent Zugriff auf alle Inhalte und auf eine Websuche. Die Aufgabe wird ihm in einem Prompt gestellt – ein Prompt ist die Anweisung, die man dem Sprachmodell gibt.
Überprüfe alle Inhalte dieses Wikis daraufhin, ob sie fremdes Urheberrecht verletzen – wörtliche Übernahmen, eng angelehnte Paraphrasen, übersetzte Passagen. Gib eine Liste der auffälligen Seiten mit Fundstelle, vermuteter Quelle und Schweregrad.
Das Ergebnis ist eine Liste. Wichtig: Nicht jeder Eintrag ist ein echter Verstoß. Der Agent schätzt und rät zum Teil, und er kann Quellen nennen, die es gar nicht gibt. Die Liste ist eine Prioritätenliste – sie sagt, wo man zuerst genauer hinschauen sollte, nicht, was schon feststeht.
Denselben Durchgang kann man mit anderem Schwerpunkt wiederholen, zum Beispiel gezielt für Duplicate Content:
Suche für jede Seite dieses Wikis stichprobenartig drei ungewöhnliche Sätze wörtlich im Web. Liste jede Seite auf, deren Sätze fast gleich auch anderswo vorkommen, mit Adresse der Fundstelle.
Die Treffer einzeln abarbeiten
Für jede auffällige Stelle aus der Liste folgt ein eigener, enger Durchgang. Ein paar bewährte Prompts:
Vergleiche den folgenden Absatz mit dem Text unter [Quelle]. Markiere wörtliche Übernahmen und enge Umformulierungen. Stelle die übereinstimmenden Stellen aus beiden Texten nebeneinander.
Ist der folgende Absatz eine Übersetzung aus [Sprache/Quelle]? Zeige Satzbau und Reihenfolge der Gedanken im Vergleich zum Original.
Formuliere den folgenden Absatz neu. Inhalt und Fakten sollen erhalten bleiben, aber keine Formulierung aus dem Original übernommen sein. Behalte den sachlichen Ton und erkläre Fachbegriffe.
Prüfe, ob der folgende Absatz eine eigene Leistung ist oder nur eine leicht abgewandelte Fassung einer bekannten Quelle. Begründe deine Einschätzung.
Nach einer Überarbeitung wird die betroffene Stelle noch einmal durch den Gesamtdurchgang geschickt, um zu prüfen, ob der Treffer verschwunden ist.
Prüf-Prompts zum Selbernutzen
Die folgenden Anweisungen lassen sich direkt übernehmen. Text in eckigen Klammern jeweils ersetzen.
- Gesamtprüfung Urheberrecht: „Überprüfe alle Inhalte unter [Ordner/Adresse] auf fremdes Urheberrecht: wörtliche Übernahmen, enge Paraphrasen, Übersetzungen. Gib eine Tabelle mit Seite, Fundstelle, vermuteter Quelle und Schweregrad (hoch/mittel/niedrig)."
- Gesamtprüfung Duplicate Content: „Wähle pro Seite drei seltene Sätze und suche sie wörtlich im Web. Nenne jede Seite mit einer fast gleichen Fundstelle anderswo."
- Einzelvergleich: „Vergleiche [Absatz] mit [Quelle]. Zeige übereinstimmende Wortfolgen ab fünf Wörtern nebeneinander."
- Übersetzungsverdacht: „Prüfe, ob [Absatz] eine Übersetzung aus [Sprache] ist. Vergleiche Reihenfolge und Satzbau mit [Quelle]."
- Neu schreiben: „Schreibe [Absatz] so um, dass Fakten bleiben, aber keine Formulierung übernommen ist. Sachlicher Ton, einfache Sätze."
- Gegenprüfung nach der Überarbeitung: „Suche [überarbeiteter Absatz] wörtlich und sinngemäß im Web. Gibt es noch Übereinstimmungen?"
Was die Prüfung nicht leistet
- Sie ersetzt keine Rechtsberatung. Ob eine Übernahme erlaubt ist (etwa als Zitat), ist eine juristische Frage. Im Zweifel hilft nur ein Anwalt.
- KI-Agenten übersehen Stellen und erfinden Quellenangaben. Jeder gemeldete Treffer muss von Hand nachgeprüft werden, bevor man daraus einen Schluss zieht.
- Bilder, Grafiken, Tabellen und Datensätze prüfen diese Verfahren nicht. Dafür braucht es eigene Schritte.
- Eine bestandene Prüfung heißt „nichts gefunden", nicht „garantiert sauber". Sicherheit gibt vor allem, von Anfang an selbst zu formulieren und Quellen nur als Beleg zu nennen, nicht als Textvorlage.
Fazit
Für die Prüfung auf Urheberrechtsverstöße und Duplicate Content gibt es keinen fertigen quelloffenen Rundum-Dienst, weil dafür ein eigener Web-Index fehlen würde. Was es gibt, sind freie Programme für den Vergleich von Dokumenten, die man selbst besitzt (WCopyfind, Sherlock, für Code JPlag und Dolos), und die Suche nach Bedeutung über Zahlenreihen für umformulierte Passagen. Die Prüfung gegen das offene Web baut man sich aus einer selbst betriebenen Suche wie SearXNG und einem KI-Agenten zusammen: erst ein breiter Gesamtdurchgang, der eine Prioritätenliste liefert, dann ein enger Einzeldurchgang pro Treffer. Jedes Ergebnis wird von Hand geprüft. So entsteht ein Text, der rechtlich auf der sicheren Seite ist und von Suchmaschinen als eigenständig erkannt wird.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Server mieten
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Die Programme aus dem Kapitel Inhalts-Software selbst betreiben müssen irgendwo laufen – auf einem Rechner, der ständig eingeschaltet und aus dem Internet erreichbar ist. Ein solcher Rechner heißt Server. Man kann ihn selbst hinstellen oder ihn bei einem Anbieter mieten. Dieses Kapitel vergleicht die üblichen Wege, nennt für jeden die Vor- und Nachteile und gibt am Ende eine Empfehlung samt Anbieternamen. Ein Sonderfall am Schluss betrifft reine Textsammlungen, die sich ohne echten Server veröffentlichen lassen.
Was der Server hier leisten muss
Bevor man Angebote vergleicht, sollte klar sein, was der Rechner können muss:
- Dauerbetrieb. Die Wissenssammlung soll jederzeit erreichbar sein, also läuft der Server rund um die Uhr.
- Feste Adresse. Er braucht eine gleichbleibende Adresse im Internet (eine feste IP-Adresse), damit ein Name wie
wiki.example.deimmer auf denselben Rechner zeigt. - Eigene Programme installieren. MediaWiki, PostgreSQL mit der Erweiterung pgvector, Meilisearch und Ollama sind eigenständige Programme. Der Server muss es erlauben, sie selbst einzurichten und als Hintergrunddienste laufen zu lassen.
- Genug Leistung. Rechenkerne (CPU), Arbeitsspeicher (RAM) und Festplattenplatz müssen zur Größe der Sammlung passen. Besonders Ollama braucht viel Leistung; mit einer starken Grafikkarte (GPU) antwortet es deutlich schneller.
An diesen vier Punkten entscheidet sich, welche Angebote überhaupt infrage kommen.
Die Wege im Überblick
Webhosting (Webspace)
Beim Webhosting mietet man fertigen Speicherplatz auf einem Server, den der Anbieter betreibt und wartet. Man lädt seine Dateien hoch, mehr Zugriff gibt es nicht. Üblich ist damit der Betrieb von PHP-Anwendungen wie MediaWiki – aber nur, solange der Anbieter die passende Umgebung vorgibt.
Für den hier beschriebenen Aufbau reicht das nicht: Eigene Hintergrunddienste wie Meilisearch oder Ollama lassen sich nicht installieren, und an der Datenbank kann man keine Erweiterung wie pgvector nachrüsten. Man hat keine Kontrolle über die Umgebung. Webhosting ist damit nur eine Option, wenn man sich dauerhaft auf ein reines MediaWiki ohne die Zusatzprogramme beschränkt.
Eigener Rechner zu Hause mit dynamischem DNS
Statt zu mieten, kann man einen Rechner zu Hause an den eigenen Internetanschluss hängen. Das Problem: Die meisten Anschlüsse bekommen von Zeit zu Zeit eine neue IP-Adresse zugeteilt. Ein fester Name würde dann ins Leere zeigen.
Hier hilft dynamisches DNS (auch DynDNS oder DDNS). Ein kleines Programm auf dem Rechner oder im Router merkt, wenn sich die IP-Adresse ändert, und meldet die neue Adresse sofort an einen Dienst, der den Namen verwaltet. So bleibt der Rechner unter demselben Namen erreichbar, obwohl sich seine Adresse ändert.
Trotzdem ist dieser Weg für eine Wissenssammlung im Dauerbetrieb wenig geeignet:
- Der Rechner muss ununterbrochen laufen – auch nachts, bei Gewitter und im Urlaub.
- Private Anschlüsse haben eine langsame Upload-Richtung; wenn viele Seiten oder große Antworten abgerufen werden, wird es zäh.
- Manche Anschlüsse vergeben gar keine von außen erreichbare Adresse mehr, sondern teilen eine Adresse unter vielen Kunden auf. Dann funktioniert dynamisches DNS nicht ohne Weiteres.
- Ein aus dem Internet erreichbarer Rechner im eigenen Netz ist ein Sicherheitsrisiko, wenn man ihn nicht sorgfältig abschottet.
Container-VPS (LXC)
VPS steht für „virtueller privater Server“ – ein abgetrennter Bereich auf einem großen Rechner, den man wie einen eigenen kleinen Server benutzt. Bei der Container-Variante (oft „LXC“ genannt) teilen sich alle Kunden auf demselben großen Rechner denselben Betriebssystem-Kern. Das ist günstig, bringt aber Einschränkungen: Manche systemnahen Funktionen sind gesperrt, und man ist stärker davon abhängig, wie der Anbieter den großen Rechner einstellt.
Für einfache Zwecke reicht das oft. Für einen Aufbau aus mehreren Diensten, bei dem man volle Kontrolle möchte, ist die nächste Variante die bessere Wahl.
KVM-VPS – die Empfehlung für den Anfang
Bei einem KVM-VPS bekommt man eine vollständige virtuelle Maschine mit eigenem Betriebssystem-Kern. Sie verhält sich wie ein eigener Rechner: Man wählt das Betriebssystem, installiert beliebige Programme und richtet Hintergrunddienste ein. Andere Kunden auf demselben großen Rechner sind sauber abgetrennt.
Für eine kleine bis mittlere Wissenssammlung ist ein KVM-VPS meist die richtige Größe. Er kostet monatlich einen festen, überschaubaren Betrag. Wächst die Sammlung, kann man bei den meisten Anbietern später auf ein größeres Paket wechseln oder einen zweiten Server dazunehmen.
Cloud-Server
Ein Cloud-Server ist technisch dasselbe wie ein KVM-VPS, wird aber anders abgerechnet: nach Stunden oder Minuten statt pauschal im Monat. Man kann ihn in wenigen Minuten erstellen und wieder löschen und zahlt nur für die Zeit, in der er läuft.
Das lohnt sich vor allem zum Ausprobieren: einen Server aufsetzen, den Aufbau testen, ihn wieder abschalten. Für den Dauerbetrieb ist der Preisunterschied zum festen Monatspaket meist gering.
Dedizierter Server (Root-Server)
Bei einem dedizierten Server mietet man einen ganzen physischen Rechner für sich allein. Niemand sonst teilt sich die Hardware. Man hat die volle Kontrolle und die volle Leistung – und kann alles installieren, was auch auf einem KVM-VPS läuft, nur eben mit mehr Reserven.
Das ist die richtige Wahl, wenn die Sammlung groß ist oder wenn Ollama zügig antworten soll. Server mit eingebauter Grafikkarte gibt es ebenfalls zu mieten, sie sind aber deutlich teurer. Kleinere Sprachmodelle laufen auch ohne Grafikkarte, nur langsamer. Der feste Monatspreis liegt höher als bei einem VPS.
Kurzvergleich
| Weg | Kontrolle | Eigene Dienste | Kosten | Für diesen Aufbau |
|---|---|---|---|---|
| Webhosting | gering | nein | niedrig | nur reines MediaWiki |
| Rechner zu Hause + DynDNS | hoch | ja | Stromkosten | nicht empfohlen |
| Container-VPS (LXC) | mittel | teilweise | sehr niedrig | eingeschränkt |
| KVM-VPS | hoch | ja | niedrig, fest | empfohlen für den Anfang |
| Cloud-Server | hoch | ja | nach Nutzung | gut zum Testen |
| Dedizierter Server | sehr hoch | ja | höher, fest | für große Sammlungen und schnelles Ollama |
Wo der Server stehen sollte
Eine Wissenssammlung enthält oft auch personenbezogene Daten – schon Benutzerkonten mit Namen und E-Mail-Adressen zählen dazu. Für deren Verarbeitung gilt in der Europäischen Union die Datenschutz-Grundverordnung (DSGVO). Steht der Server in der EU, ist die rechtliche Lage am einfachsten. Bei einem Standort außerhalb der EU muss man zusätzlich prüfen und vertraglich absichern, dass das Schutzniveau der DSGVO eingehalten wird.
Deshalb die Empfehlung: einen Anbieter mit Rechenzentrum in Deutschland oder in einem anderen EU-Land wählen. Zwei Dinge sollte man dabei zusätzlich beachten:
- Wo sitzt das Unternehmen? Auch ein Anbieter mit Rechenzentrum in der EU kann seinen Firmensitz außerhalb haben. Für die einfachste Rechtslage sollten beide in der EU liegen.
- Auftragsverarbeitungsvertrag. Seriöse Anbieter stellen einen solchen Vertrag bereit, der regelt, wie sie mit den Daten umgehen. Fehlt er, ist das ein schlechtes Zeichen.
Bandbreite und Traffic
Zwei Begriffe tauchen in Serverangeboten ständig auf und werden oft verwechselt:
- Bandbreite ist die Geschwindigkeit der Anbindung – wie viele Daten pro Sekunde durch die Leitung passen, angegeben in Megabit oder Gigabit pro Sekunde (Mbit/s, Gbit/s).
- Traffic ist die Datenmenge, die pro Monat insgesamt übertragen wird, angegeben in Gigabyte oder Terabyte (GB, TB).
Für eine Wissenssammlung mit wenigen Nutzern sind beide Werte selten ein Problem. Übliche VPS-Angebote nennen eine Anbindung von 1 Gbit/s (die man sich mit anderen Kunden teilt) und entweder eine großzügige Traffic-Grenze von mehreren Terabyte oder gar keine feste Grenze bei „fairer Nutzung“. Das reicht für Texte, Bilder und die Antworten des Sprachmodells bequem aus.
Hohe Bandbreiten von mehreren Hundert Mbit/s fest zugesichert oder gar mehrere Gbit/s braucht man erst, wenn viele Menschen gleichzeitig große Dateien oder Videos abrufen. Das ist bei einem privaten oder betrieblichen Wiki normalerweise nicht der Fall.
Wichtiger als große Zahlen ist ein Blick ins Kleingedruckte: Gibt es eine Traffic-Grenze, und was passiert, wenn sie überschritten wird? Manche Anbieter drosseln dann nur die Geschwindigkeit bis zum Monatsende, andere berechnen jedes zusätzliche Gigabyte. Ersteres ist harmlos, Letzteres kann teuer werden.
Anbieter
Die folgenden Anbieter haben Rechenzentren in Deutschland oder der EU und sind seit Jahren am Markt. Angebote und Preise ändern sich laufend, deshalb sollte man vor dem Abschluss die aktuelle Leistungsbeschreibung, den genauen Standort und die Vertragsbedingungen prüfen und aktuelle Erfahrungsberichte lesen.
KVM-VPS und Cloud-Server:
- Hetzner (Deutschland und Finnland) – „Hetzner Cloud“ für nach Nutzung abgerechnete Server, dazu feste VPS-Pakete.
- netcup (Deutschland und Österreich) – feste Monatspakete, oft mit viel Arbeitsspeicher zum kleinen Preis.
- IONOS (Deutschland) – VPS- und Cloud-Angebote des Anbieters, der früher 1&1 hieß.
- Contabo (Firmensitz in Deutschland, Rechenzentren auch außerhalb der EU – auf den Standort achten) – viel Leistung für wenig Geld.
- OVHcloud und Scaleway (Frankreich) – große europäische Anbieter mit breiter Auswahl.
Dedizierte Server:
- Hetzner – neben aktueller Hardware auch eine „Serverbörse“ mit gebrauchten Geräten zu deutlich niedrigeren Preisen.
- netcup und IONOS – ebenfalls dedizierte Server aus deutschen Rechenzentren.
- OVHcloud mit den günstigeren Marken Kimsufi und So you Start – preiswerte dedizierte Server, teils an Standorten in Frankreich oder Kanada (Standort prüfen).
Daneben gibt es viele kleinere Anbieter und Wiederverkäufer mit teils sehr günstigen Preisen. Bei ihnen lohnt ein besonders genauer Blick auf Firmensitz, Standort der Technik, Support und Erfahrungsberichte, bevor man dort wichtige Daten ablegt.
Sonderfall: statische Seite mit Git veröffentlichen
Nicht jede Sammlung braucht einen echten Server. Wenn die Inhalte nur aus Texten bestehen, die sich selten ändern, und niemand direkt auf der Webseite schreibt, reicht eine statische Seite: fertig gebaute HTML-Dateien ohne Datenbank und ohne laufendes Programm im Hintergrund. Dieses Handbuch selbst ist ein Beispiel – es wird aus Textdateien zu HTML gebaut und als solche Seite veröffentlicht.
Der übliche Ablauf: Man schreibt die Texte, verwaltet sie mit dem Versionsverwaltungs-Programm Git (siehe das Kapitel Inhalts-Software selbst betreiben für den Umgang mit Git) und schickt sie zu einem Dienst, der daraus die Webseite baut und ausliefert.
Fertige Dienste:
- GitHub Pages – kostenloser Webseiten-Dienst der Plattform GitHub. Weit verbreitet und zuverlässig.
- Codeberg Pages – dasselbe bei Codeberg, einem gemeinnützigen Verein mit Sitz in Deutschland. Wer Wert auf einen europäischen Anbieter legt, ist hier gut aufgehoben.
Beide liefern nur fertige Dateien aus und verarbeiten kaum personenbezogene Daten der Besucher, was die rechtliche Lage einfach hält.
Selbst betreiben:
- All-in-One: eine Git-Forge mit Pages-Funktion. Eine „Forge“ ist eine Software, die Git-Projekte im Browser verwaltet. Forgejo ist eine solche quelloffene Forge – dieselbe Software, auf der auch Codeberg läuft – und bringt mit „Forgejo Pages“ eine eingebaute Funktion zum Veröffentlichen statischer Seiten mit. Damit hat man Projektverwaltung und Webseiten-Auslieferung aus einer Hand auf dem eigenen Server.
- Minimalistisch: Webserver plus Git-Hook. Man betreibt einen schlanken Webserver wie Nginx und richtet einen „Git-Hook“ ein – ein kleines Skript, das bei jedem Hochladen neuer Texte automatisch die Seite neu baut und in das Verzeichnis legt, aus dem der Webserver ausliefert. Wenig Software, dafür etwas mehr Handarbeit bei der Einrichtung.
Beide Wege laufen problemlos auf einem der oben beschriebenen KVM-VPS.
Fazit
Für eine selbst betriebene Wissenssammlung ist ein KVM-VPS bei einem Anbieter mit Rechenzentrum in Deutschland oder der EU der beste Einstieg: volle Kontrolle über die eigenen Programme, fester und niedriger Monatspreis, später erweiterbar. Ein Cloud-Server hilft beim Ausprobieren, ein dedizierter Server lohnt sich für große Sammlungen und ein schnell antwortendes Ollama. Webhosting und ein Rechner zu Hause reichen für diesen Aufbau nicht aus. Wer nur selten geänderte Texte veröffentlicht, kommt ganz ohne Server aus und nutzt einen Pages-Dienst wie GitHub Pages oder Codeberg Pages oder betreibt eine Git-Forge wie Forgejo selbst.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Betriebssystem
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Ist der Server gemietet (siehe Server mieten), fehlt ihm noch das Wichtigste: ein Betriebssystem. Das Betriebssystem ist das Grundprogramm, das den Rechner überhaupt bedienbar macht. Es verwaltet Festplatte, Arbeitsspeicher und Netzwerk und sorgt dafür, dass andere Programme starten können. Ohne Betriebssystem läuft kein einziges der Programme aus dem Kapitel Inhalts-Software selbst betreiben.
Die meisten Anbieter lassen die Wahl bei der Bestellung oder später per Mausklick im Kundenbereich. Dieses Kapitel erklärt, welche Betriebssysteme zur Auswahl stehen, wie sie zusammenhängen, und welches sich für eine selbst betriebene Wissenssammlung eignet.
Warum fast immer Linux
Auf Servern läuft überwiegend Linux – eine Familie kostenloser, quelloffener Betriebssysteme. Dafür gibt es handfeste Gründe:
- Es kostet nichts und darf ohne Lizenzgebühren betrieben werden.
- Es läuft sparsam: Ein Linux-Server braucht keine grafische Oberfläche und kommt mit wenig Arbeitsspeicher aus.
- Fast alle Server-Programme werden zuerst für Linux entwickelt. MediaWiki, PostgreSQL, Meilisearch und Ollama sind dafür gemacht; ihre Anleitungen gehen von Linux aus.
- Es läuft über Jahre ohne Neustart und lässt sich vollständig über die Textkonsole fernsteuern.
Eine Linux-Ausgabe nennt man Distribution (kurz „Distro"). Alle Distributionen teilen denselben Kern, unterscheiden sich aber darin, wie neu ihre Programme sind, wie lange es Sicherheitsupdates gibt und wie sie bedient werden. Die folgende Übersicht ordnet die üblichen Angebote.
Die zwei großen Linux-Familien
Fast jede Server-Distribution stammt aus einer von zwei Linien. Der wichtigste sichtbare Unterschied ist der Befehl, mit dem man Programme installiert.
- Debian-Familie (Debian, Ubuntu). Programme werden mit dem Befehl
aptinstalliert. Pakete tragen die Endung.deb. - Red-Hat-Familie (CentOS, AlmaLinux, Rocky Linux, Fedora). Programme werden mit dem Befehl
dnfinstalliert. Pakete tragen die Endung.rpm.
Beide Familien sind solide. Anleitungen im Internet nennen oft nur Befehle für eine der beiden – wer die Familie seines Servers kennt, weiß dann, welche Zeile für ihn gilt.
Debian-Familie
Debian
Debian ist eine der ältesten Linux-Distributionen und wird von einer weltweiten Gemeinschaft Freiwilliger gepflegt, nicht von einer Firma. Die stabile Ausgabe erscheint etwa alle zwei Jahre. Während ihrer Laufzeit ändert sich an den Programmen nur wenig: Es kommen Sicherheitskorrekturen, aber keine großen neuen Versionen. Mit der zusätzlichen Langzeitpflege erhält jede Ausgabe rund fünf Jahre lang Updates.
Genau diese Ruhe ist auf einem Server ein Vorteil. Man richtet den Rechner einmal ein und muss sich jahrelang nur um Sicherheitsupdates kümmern. Debian gilt als sparsam, zuverlässig und gut dokumentiert.
Ubuntu Server
Ubuntu baut auf Debian auf und wird von der Firma Canonical herausgegeben. Interessant für Server sind die LTS-Ausgaben („Long Term Support", zu Deutsch Langzeitunterstützung). Sie erscheinen alle zwei Jahre im April und werden fünf Jahre lang mit Updates versorgt; kostenlos lässt sich dieser Zeitraum für wenige private Rechner auf zehn Jahre verlängern.
Ubuntu bringt in der Regel etwas neuere Programmversionen mit als Debian und hat die größte Nutzergemeinde überhaupt. Zu fast jedem Problem findet sich eine Anleitung, die ausdrücklich Ubuntu nennt. Für Einsteiger ist das ein spürbarer Vorteil. Wichtig: Nur die LTS-Ausgaben nehmen; die Zwischenversionen (etwa 25.10) werden schon nach neun Monaten nicht mehr gepflegt.
Red-Hat-Familie
Hintergrund: Die Firma Red Hat verkauft ein kostenpflichtiges Server-Linux namens „Red Hat Enterprise Linux" (RHEL) mit langer Update-Garantie. Rund um dieses Produkt sind mehrere kostenlose Distributionen entstanden.
CentOS
CentOS war jahrelang die kostenlose Version von RHEL – gleiche Software, keine Support-Verträge, keine Gebühr. Diese klassische Form („CentOS Linux") wurde jedoch eingestellt. Die letzte Ausgabe, CentOS Linux 7, erhielt Mitte 2024 ihr letztes Update.
Heute gibt es nur noch CentOS Stream. Das ist eine Vorschau auf die jeweils nächste RHEL-Version: Änderungen landen hier zuerst und wandern später nach RHEL. Für einen Server, der einfach nur ruhig laufen soll, ist das die falsche Richtung – man bekommt Neuerungen früher, aber weniger erprobt. Wer den bewährten „kostenloses RHEL"-Gedanken sucht, greift zu einer der beiden folgenden Distributionen.
AlmaLinux
AlmaLinux ist als Nachfolger des eingestellten CentOS entstanden und wird von einer gemeinnützigen Stiftung getragen, die von der Firma CloudLinux gegründet wurde. Es ist so gebaut, dass Programme, die für RHEL gedacht sind, unverändert laufen. Jede Ausgabe wird rund zehn Jahre lang mit Sicherheitsupdates versorgt – deutlich länger als bei Debian oder Ubuntu.
Rocky Linux
Rocky Linux verfolgt dasselbe Ziel wie AlmaLinux und ist ebenfalls als CentOS-Nachfolger gestartet. Gegründet hat es einer der ursprünglichen CentOS-Mitgründer; hinter dem Projekt steht eine eigene Stiftung. Auch hier gilt: Programme für RHEL laufen unverändert, und jede Ausgabe wird etwa zehn Jahre lang gepflegt.
Zwischen AlmaLinux und Rocky Linux muss man sich für diesen Aufbau nicht lange entscheiden – beide sind gleichwertige, seriöse Wahl. Sie sind vor allem dann interessant, wenn man die besonders lange Update-Dauer schätzt.
Fedora Server
Fedora ist das Feld, auf dem Red Hat neue Technik ausprobiert, bevor sie Jahre später in RHEL landet. Entsprechend neu ist die mitgelieferte Software – und entsprechend kurz die Pflege: Jede Ausgabe erhält nur etwa 13 Monate lang Updates, danach muss man auf die nächste wechseln.
Für einen Server, der lange unverändert laufen soll, bedeutet das häufige, größere Umstellungen. Fedora Server eignet sich für alle, die bewusst mit aktueller Technik arbeiten wollen und die regelmäßige Pflege einplanen. Für eine Wissenssammlung, die einfach nur verfügbar sein soll, ist es mehr Aufwand als nötig.
Weitere Angebote
Arch Linux
Arch Linux kennt keine festen Ausgaben. Es wird laufend aktualisiert („Rolling Release"): Jedes Programm ist immer auf dem neuesten Stand. Das Grundsystem wird bewusst schlank ausgeliefert, alles Weitere baut man selbst zusammen. Das Arch-Wiki ist eine der besten Linux-Anleitungssammlungen im Netz, wird aber auch von Nutzern anderer Distributionen gelesen.
Für einen Server bringt der ständige Fluss neuer Versionen ein Risiko mit: Nach einem Update kann sich das Verhalten eines Programms ändern, und man muss zeitnah nachbessern. Wer den Server nicht täglich im Blick hat, fährt mit einer Distribution mit festen Ausgaben ruhiger. Arch richtet sich an erfahrene Nutzer, die ihr System genau kennen wollen.
CloudLinux
CloudLinux ist ein kostenpflichtiges Server-Linux auf RHEL-Grundlage. Es ist für Firmen gedacht, die Webspace an viele Kunden vermieten: Es kann jedem Kunden feste Grenzen für Rechenleistung setzen und die Kunden streng voneinander abschotten, damit einer allein nicht den ganzen Server auslastet.
Für eine einzelne, selbst betriebene Wissenssammlung gibt es keine solchen Mitnutzer. Die Zusatzfunktionen und die laufenden Kosten von CloudLinux bringen hier keinen Nutzen. Diese Distribution taucht in Anbieterlisten nur auf, weil viele Anbieter selbst im Webhosting-Geschäft sind.
Proxmox VE
Proxmox VE ist ein Sonderfall. Es ist kein Betriebssystem, auf dem man MediaWiki und die anderen Programme direkt installiert, sondern ein Wirtssystem für virtuelle Maschinen. Auf einem physischen Rechner mit Proxmox legt man über eine Weboberfläche mehrere abgetrennte virtuelle Server an, jeder mit eigenem Betriebssystem.
Das ist nützlich, wenn man eigene Hardware besitzt – etwa einen Rechner zu Hause oder einen gemieteten dedizierten Server – und daraus mehrere getrennte Server machen will. Für einen bereits fertig gemieteten VPS ergibt Proxmox dagegen keinen Sinn: Der Anbieter hat die Virtualisierung schon übernommen. Man würde eine virtuelle Maschine in eine virtuelle Maschine setzen, was nur Leistung kostet. Innerhalb einer der virtuellen Maschinen von Proxmox nimmt man dann wieder eine der oben genannten Distributionen, meist Debian.
Windows Server
Windows Server ist die Server-Ausgabe von Microsoft Windows. Sie ist kostenpflichtig, und die Lizenz richtet sich nach der Zahl der Rechenkerne; für einen kleinen Server kommen so schnell mehrere Hundert Euro zusammen.
Der hier beschriebene Aufbau spricht klar gegen Windows: MediaWiki, PostgreSQL, Meilisearch und Ollama stammen alle aus der Linux-Welt. Zwar gibt es für manche davon auch Windows-Fassungen, doch die Anleitungen, Erfahrungsberichte und Hilfsprogramme gehen fast immer von Linux aus. Windows Server lohnt sich nur, wenn ohnehin andere Windows-Programme auf dem Rechner laufen müssen.
Kurzvergleich
| Distribution | Familie | Neue Software | Update-Dauer je Ausgabe | Für diesen Aufbau |
|---|---|---|---|---|
| Debian | Debian | zurückhaltend | ca. 5 Jahre | empfohlen |
| Ubuntu Server (LTS) | Debian | moderat | 5 Jahre (privat bis 10) | empfohlen |
| CentOS Stream | Red Hat | Vorschau auf RHEL | laufend | nicht empfohlen |
| AlmaLinux | Red Hat | zurückhaltend | ca. 10 Jahre | gut geeignet |
| Rocky Linux | Red Hat | zurückhaltend | ca. 10 Jahre | gut geeignet |
| Fedora Server | Red Hat | sehr neu | ca. 13 Monate | zu viel Pflege |
| Arch Linux | eigenständig | immer neu | laufend | nur für Fortgeschrittene |
| CloudLinux | Red Hat | zurückhaltend | an RHEL angelehnt | kostenpflichtig, unnötig |
| Proxmox VE | Debian | — | — | nur für eigene Hardware |
| Windows Server | Windows | — | lange, kostenpflichtig | nur bei Windows-Zwang |
Was bei dieser Wissenssammlung zählt
Drei Fragen entscheiden, welche Wahl praktisch ist:
- Wie lange läuft der Server ohne größere Umstellung? Je länger eine Ausgabe Updates bekommt, desto seltener muss man das ganze System anheben. Debian und Ubuntu LTS liegen bei rund fünf Jahren, AlmaLinux und Rocky Linux bei rund zehn. Fedora und Arch verlangen laufende Aufmerksamkeit.
- Wie leicht findet man Hilfe? Für Debian und besonders Ubuntu gibt es die meisten Anleitungen, auch für genau die Programme aus diesem Buch. Das erspart Einsteigern viel Sucherei.
- Bekommt man die nötigen Programme fertig verpackt? PostgreSQL mit der Erweiterung pgvector, Meilisearch und Ollama lassen sich auf Debian und Ubuntu mit wenigen Befehlen einrichten. Auf den Red-Hat-Distributionen geht das ebenfalls, verlangt aber gelegentlich einen zusätzlichen Handgriff.
Fazit
Für eine selbst betriebene Wissenssammlung ist Debian in der stabilen Ausgabe oder Ubuntu Server in einer LTS-Ausgabe die beste Wahl: kostenlos, sparsam, jahrelang ruhig im Betrieb und mit der größten Sammlung passender Anleitungen. Wer eine besonders lange Update-Dauer bevorzugt, nimmt AlmaLinux oder Rocky Linux – beide gleichwertig. CentOS Stream, Fedora und Arch Linux bringen neuere Technik, aber mehr Pflegeaufwand, als dieser Aufbau braucht. CloudLinux und Windows Server kosten Geld ohne Gegenwert für diesen Zweck. Proxmox VE ist nur dann sinnvoll, wenn man eigene Hardware in mehrere virtuelle Server aufteilen möchte; auf einem gemieteten VPS gehört es nicht hin.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Laufzeitumgebung
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Jedes Programm ist in einer Programmiersprache geschrieben. Manche Programme werden vor der Auslieferung in eine fertige, eigenständige Datei übersetzt und laufen dann allein – Meilisearch und Ollama aus dem Kapitel Inhalts-Software selbst betreiben sind solche Fälle. Andere Programme brauchen dagegen ein Hilfsprogramm, das ihren Code erst auf dem Server ausführt. Dieses Hilfsprogramm heißt Laufzeitumgebung.
MediaWiki zum Beispiel besteht aus vielen Dateien mit PHP-Code. Ohne ein PHP-Programm auf dem Server passiert damit nichts. Genauso braucht das Automatisierungswerkzeug n8n aus dem Kapitel KI-Agenten auf dem Server die Laufzeitumgebung Node.js, und viele kleine Zusatzwerkzeuge im KI-Umfeld sind in Python geschrieben.
Dieses Kapitel erklärt, was eine Laufzeitumgebung ist, stellt die sechs verbreitetsten vor und zeigt für jede, wie man sie auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) einrichtet. Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen.
Was eine Laufzeitumgebung ist
Ein Kochrezept ist nur ein Blatt Papier, solange niemand in der Küche steht und es umsetzt. Die Laufzeitumgebung ist diese Küche samt Koch: Sie liest die Anweisungen des Programms Zeile für Zeile und führt sie aus.
Zur Laufzeitumgebung gehören meist drei Dinge:
- Der Ausführer selbst – das Programm, das den Code liest und abarbeitet.
- Eine Sammlung fertiger Bausteine („Standardbibliothek"), damit nicht jedes Programm das Rechnen mit Datum, Text oder Netzwerk neu erfinden muss.
- Ein Paketwerkzeug, mit dem ein Programm weitere Bausteine aus dem Internet nachlädt, die es benötigt.
Wichtig ist der Unterschied zwischen der vollständigen Entwicklungsausstattung und der reinen Laufzeit. Wer selbst Software schreibt, braucht das komplette Paket (bei Java „JDK" genannt, bei .NET „SDK"). Wer eine fertige Anwendung nur betreiben will, kommt mit der abgespeckten Laufzeit aus (bei Java „JRE", bei .NET „Runtime"). Die Laufzeit ist kleiner, schneller eingerichtet und bietet weniger Angriffsfläche. Für einen Server, auf dem fremde Programme nur laufen sollen, ist sie die richtige Wahl.
Java
Java ist eine der ältesten noch weit verbreiteten Programmiersprachen für Server. Ihr Kennzeichen: Java-Code wird nicht für einen bestimmten Rechnertyp übersetzt, sondern in eine Zwischenform. Diese Zwischenform führt auf jedem Betriebssystem dieselbe Laufzeitumgebung aus, die Java Virtual Machine. Dadurch läuft dasselbe Java-Programm unverändert auf Windows, Linux und macOS.
Die freie Ausgabe von Java heißt OpenJDK. Im Umfeld einer Wissenssammlung begegnet Java vor allem bei Suchservern wie Apache Solr oder OpenSearch – Alternativen zu Meilisearch, die manche Anleitungen verwenden. Auch etliche Werkzeuge zur Datenverarbeitung setzen Java voraus.
Ubuntu 26.04 liefert OpenJDK 25 als Standardversion mit. Für den reinen Betrieb genügt die kopflose Laufzeit ohne grafische Bestandteile:
sudo apt update
# Installiert die Java-Laufzeitumgebung ohne grafische Bestandteile
sudo apt install openjdk-25-jre-headless
# Zeigt die installierte Version zur Kontrolle an
java -version
Wer Java-Software auch selbst übersetzen muss, ersetzt openjdk-25-jre-headless durch openjdk-25-jdk-headless.
Python
Python ist eine Sprache, die auf gut lesbaren Code setzt und darum oft für kurze Hilfsprogramme, Auswertungen und Automatisierung genommen wird. Im KI-Umfeld ist Python die vorherrschende Sprache: Werkzeuge, die Texte für die Bedeutungssuche aufbereiten, Modelle testen oder Daten zwischen Diensten umschaufeln, sind fast immer in Python geschrieben.
Ubuntu bringt Python 3 bereits mit, allerdings ohne die üblichen Zusatzteile. Diese werden nachinstalliert:
# Python 3 mit Paketwerkzeug (pip) und Umgebungsverwaltung (venv);
# python-is-python3 sorgt dafür, dass der Befehl "python" Python 3 startet
sudo apt install python3 python3-pip python3-venv python-is-python3
Eine Besonderheit von Python sollte man kennen: Zusätzliche Bausteine werden nicht global installiert, sondern in einer abgetrennten Umgebung je Programm, einer sogenannten virtuellen Umgebung. Das verhindert, dass zwei Programme sich mit unterschiedlichen Versionen desselben Bausteins ins Gehege kommen. Angelegt wird eine solche Umgebung mit:
python -m venv .venv
source .venv/bin/activate
Neuere Ubuntu-Ausgaben bestehen sogar darauf: Ein direktes pip install außerhalb einer virtuellen Umgebung wird abgewiesen.
ASP.NET Core Runtime
.NET (gesprochen „dot net") ist die Programmierplattform von Microsoft, seit einigen Jahren quelloffen und auch für Linux verfügbar. ASP.NET Core ist der Teil davon, mit dem Webanwendungen gebaut werden. Die ASP.NET Core Runtime ist die passende Laufzeitumgebung, um solche Webanwendungen zu betreiben; sie enthält die allgemeine .NET-Laufzeit bereits.
Im Umfeld dieses Buchs spielt .NET eine Nebenrolle, taucht aber bei einzelnen selbst betriebenen Zusatzdiensten auf – etwa bei manchen Verwaltungsoberflächen oder Schnittstellenprogrammen.
Auf Ubuntu 26.04 liegen die .NET-Pakete direkt in den Paketquellen des Systems; eine zusätzliche Paketquelle von Microsoft ist nicht mehr nötig:
sudo apt-get update
sudo apt-get install -y aspnetcore-runtime-10.0
# Zeigt die installierten Laufzeiten an
dotnet --list-runtimes
Die Zahl 10.0 benennt die Hauptversion. .NET 10 ist eine Ausgabe mit langer Pflegezusage („LTS") und darum die richtige Wahl für einen Server, der ruhig laufen soll.
Node.js
JavaScript war ursprünglich nur die Sprache im Webbrowser. Node.js löst diese Sprache vom Browser und macht sie zu einer vollwertigen Server-Laufzeitumgebung. Sehr viele moderne Werkzeuge sind darauf gebaut – im Umfeld dieses Buchs vor allem das Automatisierungswerkzeug n8n, aber auch zahlreiche Kommandozeilenhelfer.
Das zugehörige Paketwerkzeug heißt npm. Damit lädt ein Node.js-Programm die Bausteine nach, die es braucht.
Der einfache Weg: das Systempaket
Für einen einzelnen Dienst genügt die Fassung aus den Ubuntu-Paketquellen:
sudo apt install nodejs npm
node -v
Der flexible Weg: nvm
Manche Programme verlangen eine ganz bestimmte Node.js-Version, und diese Versionen wechseln schnell. Dafür gibt es den Node Version Manager (nvm). Er wird für einen einzelnen Benutzer installiert, nicht systemweit, und kann mehrere Node.js-Versionen nebeneinander vorhalten:
# Installationsskript von nvm herunterladen und ausführen
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash
# nvm in der laufenden Sitzung verfügbar machen (sonst hilft ein neues Anmelden)
\. "$HOME/.nvm/nvm.sh"
# Eine Node.js-Version installieren und benutzen
nvm install 24
nvm use 24
Hinweis: Ein Skript aus dem Internet direkt auszuführen, sollte man nur bei Quellen tun, denen man vertraut. Wer sichergehen will, lädt das Skript zuerst herunter, liest es und führt es dann aus.
Für den Server empfiehlt sich eine Version mit gerader Nummer (22, 24, …); nur diese erhalten über Jahre Sicherheitsupdates. Ungerade Nummern sind kurzlebige Zwischenausgaben.
PHP
PHP ist die Sprache, in der ein großer Teil des Webs geschrieben ist – darunter MediaWiki, die Grundlage der Wissenssammlung dieses Buchs. Ohne eine PHP-Laufzeitumgebung auf dem Server zeigt MediaWiki keine einzige Seite an.
Für den Betrieb hinter einem Webserver nimmt man die Ausführungsart PHP-FPM („FastCGI Process Manager"). Sie hält PHP als Hintergrunddienst bereit, an den der Webserver die Anfragen weiterreicht. Ubuntu 26.04 liefert PHP 8.5 mit. Die allgemeinen Paketnamen ohne Versionsnummer ziehen automatisch diese Fassung:
sudo apt install php-fpm php-cli \
php-pgsql php-xml php-mbstring php-curl php-gd php-zip php-intl php-opcache
# Zeigt die installierte Version zur Kontrolle an
php -v
Die einzelnen php-*-Pakete sind Erweiterungen: php-pgsql verbindet PHP mit der Datenbank PostgreSQL, php-mbstring behandelt Texte mit Umlauten und anderen Sonderzeichen korrekt, php-gd verkleinert hochgeladene Bilder, und so fort. MediaWiki nennt in seiner Installationsprüfung genau, welche davon es erwartet.
Composer
Zusätzliche PHP-Bausteine verwaltet das Werkzeug Composer. Es liegt zwar auch in den Paketquellen, dort aber oft veraltet. Die offizielle Anleitung lädt es darum direkt herunter und prüft dabei über eine Prüfsumme, dass die Datei unterwegs nicht verändert wurde:
# Installationsprogramm von Composer herunterladen
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
# Erwartete Prüfsumme laden und die heruntergeladene Datei damit vergleichen
EXPECTED_HASH="$(curl -sS https://composer.github.io/installer.sig)"
php -r "if (hash_file('sha384', 'composer-setup.php') === '$EXPECTED_HASH') { echo 'Installationsprogramm bestätigt' . PHP_EOL; } else { echo 'Installationsprogramm beschädigt' . PHP_EOL; unlink('composer-setup.php'); exit(1); }"
# Composer systemweit als Befehl "composer" einrichten und Installationsprogramm entfernen
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"
Lua
Lua ist eine sehr kleine, schnelle Sprache. Sie wird selten allein benutzt, sondern meist in ein größeres Programm eingebettet, um dieses erweiterbar zu machen. Der Zwischenspeicher Redis führt kleine Lua-Programme aus, um mehrere Schritte in einem Rutsch zu erledigen; der Webserver nginx lässt sich mit Lua um eigene Logik ergänzen; auch manche Konfigurationsdateien sind in Wahrheit Lua.
Für die Wissenssammlung dieses Buchs ist Lua kein Pflichtbestandteil. Wird es doch einmal gebraucht, genügt:
# Lua-Ausführer und das Paketwerkzeug luarocks
sudo apt install lua5.4 luarocks
lua5.4 -v
Kurzvergleich
| Laufzeitumgebung | Paket für den Betrieb (Ubuntu 26.04) | Paketwerkzeug | In diesem Buch |
|---|---|---|---|
| Java (OpenJDK 25) | openjdk-25-jre-headless | Maven, Gradle | nur bei Suchservern wie Solr/OpenSearch |
| Python 3 | python3 python3-pip python3-venv | pip (in virtueller Umgebung) | viele KI-Hilfswerkzeuge |
| ASP.NET Core Runtime | aspnetcore-runtime-10.0 | NuGet | einzelne Zusatzdienste |
| Node.js | nodejs npm oder nvm | npm | n8n und Kommandozeilenhelfer |
| PHP 8.5 | php-fpm php-cli + Erweiterungen | Composer | Pflicht für MediaWiki |
| Lua 5.4 | lua5.4 | luarocks | eingebettet in Redis, nginx |
Für dieses Buch
Von den sechs Laufzeitumgebungen ist für den beschriebenen Aufbau nur eine wirklich unverzichtbar: PHP für MediaWiki. Wer zusätzlich einen KI-Agenten auf dem Server betreibt, kommt um Node.js (für n8n) und meist um Python (für kleinere Helfer) nicht herum. Java, .NET und Lua braucht man nur, wenn ein bestimmtes Zusatzprogramm sie voraussetzt – dann sagt dessen Anleitung das ausdrücklich.
Ein Grundsatz gilt für alle: auf dem Server nur die Laufzeit installieren, nicht die volle Entwicklungsausstattung, und keine Version aufspielen, für die es keine Sicherheitsupdates mehr gibt. Wer Programme in Containern betreibt (siehe Containerisierung von Software), muss sich um die Laufzeitumgebungen gar nicht kümmern: Sie stecken dann bereits im jeweiligen Container.
Fazit
Eine Laufzeitumgebung ist das Hilfsprogramm, das den Code einer Anwendung auf dem Server ausführt. PHP ist für MediaWiki zwingend, Node.js und Python kommen mit KI-Agenten dazu, Java, .NET und Lua nur bei Bedarf. Auf Ubuntu 26.04 lässt sich jede davon mit einem einzigen apt-Befehl einrichten; nur bei Node.js lohnt mit nvm ein zweiter Weg, wenn ein Programm eine feste Version verlangt. Für einen Server gilt: die schlanke Laufzeit statt der vollen Entwicklungsausstattung wählen und nur gepflegte Versionen betreiben.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Tomcat 11 einrichten
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Manche Webprogramme sind in der Programmiersprache Java geschrieben. Ein Java-Webprogramm läuft nicht für sich allein – es braucht ein Trägerprogramm, das es lädt, am Laufen hält und die Anfragen aus dem Netz an es weiterreicht. Dieses Trägerprogramm heißt Anwendungsserver, und der verbreitetste ist Apache Tomcat.
Im Kapitel XWiki einrichten taucht Tomcat schon auf, dort aber versteckt: Die XWiki-Pakete bringen ihn als Beigabe mit. Dieses Kapitel zeigt Tomcat für sich – wie man Tomcat 11 auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) einrichtet, auf zwei Wegen: von Hand aus dem offiziellen Download und aus den Paketquellen von Ubuntu. Danach wird Tomcat über einen Unix-Socket an den Webserver NGINX angebunden, am Beispiel der Adresse https://tomcat11.de.
Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen.
Was Tomcat ist
Ein fertiges Java-Webprogramm wird meist als eine einzige Datei mit der Endung .war ausgeliefert – kurz für „Web Application Archive", also ein gepacktes Webprogramm. Diese Datei kann man nicht einfach starten. Sie muss in einen Servlet-Container gelegt werden: ein Programm, das sich um alles Drumherum kümmert – Netzwerk, Verbindungen, mehrere Anfragen gleichzeitig, Neustart – und das Webprogramm nur noch mit den fertig aufbereiteten Anfragen versorgt.
Man kann sich Tomcat wie einen Motorraum vorstellen: Das Java-Webprogramm ist der Motor, Tomcat das Gehäuse mit Halterungen, Anschlüssen und Anlasser darum herum.
Tomcat setzt eine Reihe von Java-Standards um – für Servlets, für JavaServer Pages (JSP) und für WebSockets. Welche Fassung dieser Standards ein Tomcat beherrscht, hängt an seiner Hauptversion:
| Tomcat-Version | Standard-Bündel | Mindest-Java | Einordnung |
|---|---|---|---|
| 9.0 | Java EE 8 | Java 8 | alt, nur noch für ältere Programme |
| 10.1 | Jakarta EE 10 | Java 11 | noch verbreitet |
| 11.0 | Jakarta EE 11 | Java 17 | aktuelle Wahl für neue Aufbauten |
Für einen neuen Server ist Tomcat 11 die richtige Wahl. Es braucht mindestens Java 17; die in diesem Buch verwendete Standard-Java-Version von Ubuntu 26.04 (OpenJDK 25, siehe Laufzeitumgebung) passt. Zum Zeitpunkt dieses Kapitels ist 11.0.25 die neueste Ausgabe.
Ein Wechsel von Java EE zu Jakarta EE hat übrigens einen praktischen Haken: Programme für Tomcat 9 und älter laufen nicht ohne Anpassung auf Tomcat 10 oder 11. Wer ein bestehendes Programm übernimmt, muss prüfen, für welche Tomcat-Reihe es gebaut ist.
Zwei Wege zur Installation
Es gibt zwei Wege, Tomcat 11 auf den Server zu bringen:
- Von Hand aus dem offiziellen Download unter https://tomcat.apache.org/download-11.cgi. Man bekommt immer die neueste Version und schreibt den Startdienst selbst. Dieser Weg gibt volle Kontrolle und eignet sich, wenn eine ganz bestimmte oder die allerneueste Version nötig ist oder mehrere Tomcats nebeneinander laufen sollen.
- Aus den Ubuntu-Paketquellen mit
apt install tomcat11. Ubuntu 26.04 bringt Tomcat 11 mit. Der Weg ist schneller, und Sicherheitsaktualisierungen kommen automatisch überapt. Dafür ist die Version an die von Ubuntu ausgelieferte Fassung gebunden.
Die folgenden Abschnitte beschreiben zuerst den Weg von Hand ausführlich (Weg A), dann kurz den Paket-Weg (Weg B). Die Anbindung an NGINX danach gilt für beide; die Pfade unterscheiden sich nur an wenigen Stellen, jeweils angegeben.
Weg A: Tomcat 11 aus dem offiziellen Download
Schritt 1: Java installieren
Tomcat 11 braucht eine Java-Laufzeitumgebung ab Version 17. Für den reinen Betrieb genügt die kopflose Fassung ohne grafische Bestandteile:
sudo apt update
sudo apt install openjdk-25-jre-headless
# Zur Kontrolle die installierte Version anzeigen
java -version
Mehr zu Java steht im Kapitel Laufzeitumgebung.
Schritt 2: Einen eigenen Benutzer anlegen
Tomcat soll nicht mit Verwaltungsrechten laufen. Sonst hätte ein Fehler im Java-Programm sofort Zugriff auf den ganzen Server. Deshalb bekommt Tomcat einen eigenen Benutzer, der sich nicht anmelden kann und dessen Zuhause das spätere Programmverzeichnis ist:
sudo useradd --system --home-dir /opt/tomcat11 --shell /usr/sbin/nologin tomcat
--systemlegt ein Dienstkonto an, kein persönliches.--shell /usr/sbin/nologinverhindert das Anmelden mit diesem Benutzer.
Schritt 3: Tomcat herunterladen und entpacken
Die aktuelle Versionsnummer steht auf der Download-Seite https://tomcat.apache.org/download-11.cgi. Hier wird sie einmal in eine Variable geschrieben, damit die folgenden Befehle unverändert bleiben:
cd /tmp
VERSION=11.0.25
# Das gepackte Programm herunterladen
wget "https://dlcdn.apache.org/tomcat/tomcat-11/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz"
# Die Prüfsumme dazu herunterladen
wget "https://downloads.apache.org/tomcat/tomcat-11/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz.sha512"
# Die heruntergeladene Datei gegen die Prüfsumme halten – muss "OK" anzeigen
sha512sum -c "apache-tomcat-${VERSION}.tar.gz.sha512"
Die Prüfsumme ist ein Fingerabdruck der Datei. Stimmt der berechnete Fingerabdruck mit dem veröffentlichten überein, ist die Datei unterwegs nicht verändert worden. Zeigt der Befehl etwas anderes als OK, wird die Datei nicht benutzt, sondern neu geladen.
Hinweis: Ältere Tomcat-Versionen werden von
dlcdn.apache.orgirgendwann entfernt und wandern nachhttps://archive.apache.org/dist/tomcat/. Wer eine ältere Version braucht, ändert die Adresse entsprechend.
Jetzt das Zielverzeichnis anlegen und das Archiv hineinentpacken:
sudo mkdir -p /opt/tomcat11
sudo tar xzf "apache-tomcat-${VERSION}.tar.gz" -C /opt/tomcat11 --strip-components=1
--strip-components=1 lässt die oberste Ordnerebene aus dem Archiv weg, sodass die Dateien direkt in /opt/tomcat11 liegen und nicht in /opt/tomcat11/apache-tomcat-11.0.25.
Anschließend gehört alles dem Benutzer tomcat:
sudo chown -R tomcat:tomcat /opt/tomcat11
Nach dem Entpacken liegen die wichtigsten Verzeichnisse an diesen Stellen:
| Verzeichnis | Inhalt |
|---|---|
/opt/tomcat11/bin/ | Start- und Stopp-Skripte |
/opt/tomcat11/conf/ | Konfiguration, vor allem server.xml |
/opt/tomcat11/webapps/ | die Webprogramme (.war-Dateien) |
/opt/tomcat11/logs/ | Protokolldateien, u. a. catalina.out |
/opt/tomcat11/lib/ | von Tomcat mitgebrachte Java-Bausteine |
Schritt 4: Tomcat als Dienst einrichten
Damit Tomcat beim Serverstart automatisch hochfährt und sich bequem starten und stoppen lässt, wird er als systemd-Dienst eingetragen. Zuerst den genauen Pfad zur Java-Installation herausfinden:
sudo update-alternatives --list java
Die Ausgabe endet auf /bin/java, zum Beispiel /usr/lib/jvm/java-25-openjdk-amd64/bin/java. Der Teil davor – hier /usr/lib/jvm/java-25-openjdk-amd64 – ist gleich als JAVA_HOME einzutragen.
Nun die Dienstdatei anlegen:
sudo nano /etc/systemd/system/tomcat.service
Mit diesem Inhalt (den JAVA_HOME-Pfad gegebenenfalls anpassen):
[Unit]
Description=Apache Tomcat 11
After=network.target
[Service]
Type=simple
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64"
Environment="CATALINA_HOME=/opt/tomcat11"
Environment="CATALINA_BASE=/opt/tomcat11"
Environment="CATALINA_PID=/opt/tomcat11/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512m -Xmx1024m -XX:+UseG1GC"
ExecStart=/opt/tomcat11/bin/catalina.sh run
ExecStop=/opt/tomcat11/bin/catalina.sh stop
Restart=on-failure
[Install]
WantedBy=multi-user.target
Die Zeile CATALINA_OPTS legt den Arbeitsspeicher fest, den sich Java nehmen darf:
-Xms512mist der Speicher, der gleich beim Start belegt wird.-Xmx1024mist die Obergrenze – hier 1024 MB, also 1 GB. Auf einem größeren Server darf dieser Wert höher liegen, aber nie an die Grenze des gesamten Arbeitsspeichers reichen; das Betriebssystem und die Datenbank brauchen ebenfalls Platz.-XX:+UseG1GCwählt ein Aufräumverfahren, das für Programme mit vielen gleichzeitigen Zugriffen gut geeignet ist.
Dann den Dienst bekannt machen, dauerhaft einschalten und starten:
sudo systemctl daemon-reload
sudo systemctl enable --now tomcat
sudo systemctl status tomcat
status sollte active (running) zeigen.
Schritt 5: Kurzer Test
curl http://localhost:8080/
Wenn HTML zurückkommt, läuft Tomcat. In diesem Zustand lauscht er allerdings auf Port 8080 und nimmt Verbindungen aus dem ganzen Netz an – das wird bei der Anbindung an NGINX weiter unten geändert.
Weg B: Tomcat 11 aus den Ubuntu-Paketquellen
Wer sich den Aufbau von Hand sparen will, nimmt das fertige Paket. Zuerst nachsehen, welche Version Ubuntu anbietet:
sudo apt update
apt-cache policy tomcat11
Dann installieren:
sudo apt install tomcat11
Das Paket zieht Java als Abhängigkeit mit und richtet den Dienst gleich ein. Er heißt tomcat11 und läuft ebenfalls unter dem Benutzer tomcat:
systemctl status tomcat11
Die Pfade sind beim Paket anders als beim Weg von Hand. Die genaue Liste zeigt dpkg -L tomcat11; die wichtigsten sind:
| Datei oder Verzeichnis | Inhalt |
|---|---|
/var/lib/tomcat11/conf/server.xml | Konfiguration, u. a. der Port |
/var/lib/tomcat11/webapps/ | die Webprogramme |
/var/lib/tomcat11/logs/ | Protokolldateien |
tomcat11.service | der systemd-Dienst |
Den Arbeitsspeicher stellt man beim Paket über eine Ergänzungsdatei des Dienstes ein:
sudo systemctl edit tomcat11
Dort im vorgesehenen Bereich eintragen:
[Service]
Environment="CATALINA_OPTS=-Xms512m -Xmx1024m -XX:+UseG1GC"
Danach neu starten:
sudo systemctl restart tomcat11
Für den Rest des Kapitels gilt: Wer den Paket-Weg gewählt hat, ersetzt in den folgenden Befehlen und Dateien /opt/tomcat11/conf durch /var/lib/tomcat11/conf, den Dienstnamen tomcat durch tomcat11 und den Socket-Pfad /opt/tomcat11/tomcat11.sock durch /var/lib/tomcat11/tomcat11.sock.
Tomcat über einen Unix-Socket an NGINX anbinden
Von Haus aus öffnet Tomcat den Port 8080 für das ganze Netz. Für einen öffentlichen Server ist das die falsche Einstellung: Davor gehört ein Webserver, der die Verbindung verschlüsselt (HTTPS) und die Anfragen an Tomcat weiterreicht. Diese Rolle heißt Reverse Proxy; in diesem Buch übernimmt sie NGINX (siehe Webserver).
Für die Verbindung zwischen NGINX und Tomcat gibt es zwei Möglichkeiten: über einen Port nur auf dem eigenen Rechner (127.0.0.1:8080) oder – sauberer – über eine Socket-Datei, den sogenannten Unix-Socket. Dann gibt es überhaupt keinen Port, der aus Versehen geöffnet werden könnte, und der Zugriff hängt allein an Dateirechten. Was ein Unix-Socket ist, erklären die Kapitel Unix-Socket und Unix-Socket bei NGINX ausführlich. Tomcat 11 kann von sich aus an einer Socket-Datei lauschen; dieser Abschnitt richtet genau das ein.
Schritt 1: Den Connector auf einen Socket umstellen
In der Datei /opt/tomcat11/conf/server.xml steht der Abschnitt, der festlegt, wo Tomcat auf Anfragen wartet. Er heißt <Connector> und sieht in etwa so aus:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxParameterCount="1000" />
Diesen Abschnitt so ersetzen:
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
unixDomainSocketPath="/opt/tomcat11/tomcat11.sock"
unixDomainSocketPathPermissions="rw-rw----"
connectionTimeout="20000"
maxParameterCount="1000" />
Was sich ändert:
- Es gibt keinen
portmehr. Stattdessen nenntunixDomainSocketPathden Pfad zur Socket-Datei. Tomcat legt sie beim Start an und entfernt sie beim Stoppen wieder. protocol="org.apache.coyote.http11.Http11NioProtocol"wählt ausdrücklich die Verarbeitungsart, die Socket-Dateien unterstützt.unixDomainSocketPathPermissions="rw-rw----"setzt die Dateirechte: Besitzer und Gruppe dürfen lesen und schreiben, alle anderen nichts. Der Besitzer ist der Benutzertomcat.
Die Socket-Datei liegt hier bewusst im Verzeichnis /opt/tomcat11, das dem Benutzer tomcat gehört und einen Neustart übersteht.
Hinweis: Stürzt Tomcat ab, bleibt die Socket-Datei manchmal liegen. Beim nächsten Start meldet das Protokoll dann, die Datei sei schon vorhanden, und Tomcat startet nicht. In dem Fall die Datei von Hand entfernen:
sudo rm /opt/tomcat11/tomcat11.sock, dannsudo systemctl start tomcat.
Schritt 2: NGINX darf die Socket-Datei benutzen
NGINX läuft unter dem Benutzer www-data. Die Socket-Datei gehört tomcat:tomcat mit den Rechten rw-rw----. Damit www-data sie benutzen darf, wird dieser Benutzer in die Gruppe tomcat aufgenommen:
sudo usermod -aG tomcat www-data
sudo systemctl restart tomcat nginx
Ein bloßes reload genügt für die neue Gruppenzugehörigkeit nicht; NGINX muss vollständig neu starten.
Schritt 3: Tomcat die echte Besucheradresse mitteilen
Hinter einem Reverse Proxy sieht Tomcat jede Anfrage so, als käme sie vom Server selbst und über unverschlüsseltes HTTP. Dann baut das Java-Programm falsche Links und hält jeden Besucher für den Server. Ein zusätzlicher Baustein in server.xml behebt das. Innerhalb des <Host>-Abschnitts – kurz vor dessen Ende </Host> – wird eingefügt:
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto" />
Dieser Baustein liest die beiden Zusatzangaben aus, die NGINX gleich mitschickt (X-Forwarded-For für die Besucheradresse, X-Forwarded-Proto für „war verschlüsselt"), und stellt sie dem Java-Programm als die wahren Werte hin.
Danach Tomcat neu starten:
sudo systemctl restart tomcat
Schritt 4: NGINX als Reverse Proxy für tomcat11.de
Zuerst das SSL-Zertifikat besorgen. Wie das mit Certbot und Let's Encrypt geht, steht ausführlich im Kapitel Webserver; für eine feste Domain genügt:
sudo certbot certonly --nginx -d tomcat11.de -d www.tomcat11.de
Dann die Konfigurationsdatei /etc/nginx/sites-available/tomcat11.de anlegen:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name tomcat11.de www.tomcat11.de;
ssl_certificate /etc/letsencrypt/live/tomcat11.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tomcat11.de/privkey.pem;
# Größere Uploads zulassen
client_max_body_size 50m;
location / {
proxy_pass http://unix:/opt/tomcat11/tomcat11.sock:/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
listen [::]:80;
server_name tomcat11.de www.tomcat11.de;
# Alle unverschlüsselten Aufrufe auf HTTPS umleiten
return 301 https://$host$request_uri;
}
Die Zeile proxy_pass http://unix:/opt/tomcat11/tomcat11.sock:/; ist der Weg zur Socket-Datei. Die Schreibweise ist etwas ungewohnt: Nach http://unix: folgt der Pfad zur Socket-Datei, dann ein Doppelpunkt und der Pfad innerhalb der Anwendung (/). Die vier proxy_set_header-Zeilen geben Tomcat weiter, wer die Anfrage gestellt hat und dass sie über HTTPS kam – sie gehören zum Baustein aus Schritt 3.
Die Datei aktiv schalten, prüfen und übernehmen:
sudo ln -s /etc/nginx/sites-available/tomcat11.de /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Jetzt ist Tomcat unter https://tomcat11.de/ erreichbar – ohne dass irgendwo Port 8080 offensteht.
Schritt 5: Firewall
Weil kein Port für Tomcat geöffnet wurde, ist nichts zusätzlich zu sperren. Es genügt, dem Webserver die Ports 80 und 443 zu erlauben:
sudo ufw allow "Nginx Full"
sudo ufw enable
sudo ufw status verbose
Wer statt des Sockets doch den Weg über 127.0.0.1:8080 gewählt hat, sperrt Port 8080 zusätzlich ausdrücklich: sudo ufw deny 8080/tcp.
Eine Anwendung einspielen
Ein Java-Webprogramm wird als .war-Datei in das Verzeichnis webapps gelegt. Der Dateiname bestimmt die Adresse: ROOT.war wird zur Startseite (https://tomcat11.de/), laden.war läge unter https://tomcat11.de/laden/.
sudo cp meineanwendung.war /opt/tomcat11/webapps/ROOT.war
sudo chown tomcat:tomcat /opt/tomcat11/webapps/ROOT.war
Tomcat bemerkt die neue Datei, entpackt sie von selbst und startet das Programm. Ob das klappt, zeigt das Protokoll:
sudo journalctl -u tomcat -f
Zusätzlich schreibt Tomcat nach /opt/tomcat11/logs/catalina.out.
Der offizielle Download bringt einige Beispielprogramme mit (docs, examples, manager, host-manager). Auf einem öffentlichen Server haben sie nichts zu suchen und werden entfernt:
sudo rm -rf /opt/tomcat11/webapps/{docs,examples,manager,host-manager}
Fehlersuche
-
502 Bad Gateway im Browser: NGINX erreicht Tomcat nicht. Grund im Protokoll suchen:
sudo tail -n 20 /var/log/nginx/error.log.Permission denied (13): Der Benutzerwww-dataist nicht in der Gruppetomcat, oder NGINX wurde nachusermodnur neu geladen statt neu gestartet.sudo systemctl restart nginx.No such file or directory (2): Tomcat läuft nicht, oder der Pfad inunixDomainSocketPathundproxy_passstimmt nicht überein.systemctl status tomcatprüfen.
-
Tomcat startet nicht, das Protokoll nennt die Socket-Datei als schon vorhanden: übrig gebliebene Datei nach einem Absturz.
sudo rm /opt/tomcat11/tomcat11.sock, dann starten. -
Die Socket-Datei direkt testen, ohne NGINX:
sudo -u www-data curl --unix-socket /opt/tomcat11/tomcat11.sock http://localhost/Kommt hier HTML zurück, liegt ein etwaiger Fehler in der NGINX-Konfiguration, nicht bei Tomcat.
-
java -versionmuss 17 oder höher anzeigen. Ältere Java-Versionen starten Tomcat 11 nicht. -
OutOfMemoryErrorincatalina.out: Die Speichergrenze-Xmxist zu niedrig. In der Dienstdatei erhöhen undsudo systemctl daemon-reload && sudo systemctl restart tomcat.
Für dieses Buch
Die Wissenssammlung dieses Buchs läuft auf MediaWiki und braucht kein Tomcat. Tomcat wird nur zum Thema, wenn ein Java-Programm dazukommt:
- XWiki als Wissenssystem: Dann folgt man dem Kapitel XWiki einrichten, das ein eigenes Sammelpaket mit Tomcat 10 verwendet und die Schritte dort im Zusammenhang beschreibt.
- Ein selbst geschriebenes Java-Programm, etwa auf Basis von Spring Boot (siehe Webframework): Dafür ist Tomcat 11 von Hand in
/opt/tomcat11der saubere Weg – eigener Benutzer, Anbindung an NGINX über einen Unix-Socket, kein offener Port.
Zwei Dinge gehören von Anfang an zum Betrieb: eine passende Speichergrenze für Java (-Xmx) und regelmäßige Sicherheitsaktualisierungen für Java und Tomcat. Beim Weg von Hand heißt das, die Tomcat-Version selbst im Blick zu behalten und bei einer neuen Ausgabe das Verzeichnis auszutauschen.
Fazit
Tomcat ist der Anwendungsserver, der ein Java-Webprogramm trägt. Tomcat 11 setzt Jakarta EE 11 um und braucht mindestens Java 17. Es lässt sich von Hand aus dem offiziellen Download einrichten – mit eigenem Benutzer, eigenem systemd-Dienst und selbst gesetzter Speichergrenze – oder mit apt install tomcat11 aus den Paketquellen von Ubuntu 26.04. Davor gehört NGINX als Reverse Proxy für HTTPS. Die Verbindung dahin läuft am besten über einen Unix-Socket: In server.xml bekommt der <Connector> statt eines Ports den Eintrag unixDomainSocketPath, NGINX erreicht die Socket-Datei über proxy_pass http://unix:/opt/tomcat11/tomcat11.sock:/;, und der Benutzer www-data wird dafür in die Gruppe tomcat aufgenommen. So steht für Tomcat kein Port offen, und der Zugriff hängt allein an Dateirechten.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Datenbank
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Im Kapitel Inhalts-Software selbst betreiben taucht die Datenbank als einer der Bausteine auf: Sie ist der Ort, an dem alle Texte, alle früheren Versionen und alle Einstellungen der Wissenssammlung dauerhaft liegen. MediaWiki selbst speichert nichts – es zeigt Seiten an und nimmt Änderungen entgegen, aber ablegen tut es sie in der Datenbank. Fällt die Datenbank aus, ist das Wiki leer.
Dieses Kapitel erklärt, was eine Datenbank ist, was es bedeutet, dass sie „robust" sein soll, und welche Programme dafür in Frage kommen. Danach zeigt es Schritt für Schritt, wie PostgreSQL auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) eingerichtet wird, und ergänzt die Suchdienste Meilisearch und Typesense sowie die Erweiterungen für die Suche nach Bedeutung. Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen.
Was eine Datenbank ist
Eine Datenbank ist ein gut sortiertes Lager mit Katalog. Man kann Dinge hineingeben, ohne sich zu merken, in welchem Regal sie landen, und man bekommt sie auf eine kurze Anfrage hin sofort wieder heraus – auch dann, wenn Millionen Dinge im Lager liegen. Das Programm, das dieses Lager verwaltet, heißt Datenbankmanagementsystem; im Alltag sagt man einfach „die Datenbank".
Die hier betrachteten Datenbanken sind relational. Das heißt: Die Daten stehen in Tabellen, ähnlich wie in einer Tabellenkalkulation. Eine Tabelle für die Seiten, eine für die Versionen, eine für die Benutzerkonten. Zwischen den Tabellen gibt es Verweise – eine Version gehört zu einer Seite, eine Änderung zu einem Konto. Abgefragt werden die Tabellen in einer eigenen Sprache namens SQL (gesprochen „Es-Ku-El" oder „Sieckwel"). MediaWiki setzt diese Abfragen selbst zusammen; man bekommt SQL im Normalbetrieb nie zu sehen.
Zwei Eigenschaften machen eine Datenbank zu mehr als einer Sammlung von Dateien:
- Sie hält Ordnung, auch bei gleichzeitigen Zugriffen. Wenn zwei Personen dieselbe Seite im selben Moment speichern, sorgt die Datenbank dafür, dass kein Mischmasch entsteht, sondern ein klares Vorher und Nachher.
- Sie lässt nichts halb Fertiges zurück. Eine Änderung wird entweder ganz gespeichert oder gar nicht. Stürzt der Server mitten im Schreiben ab, ist danach kein zerrissener Datensatz da. Fachleute nennen diese Eigenschaft ACID.
Was „robust" bei einer Datenbank bedeutet
Die Ausgangsfrage lautete: Welche Datenbank ist quelloffen, industrietauglich, sehr belastbar, verwaltet eine Million Texteinträge mit verschiedenen Inhaltstypen – und geht dabei nicht kaputt? Diese Anforderungen lassen sich einzeln beantworten.
- Eine Million Einträge sind wenig. Für eine ausgewachsene Datenbank ist das eine kleine bis mittlere Größe. Die deutschsprachige Wikipedia hat ein Vielfaches davon. Entscheidend für die Geschwindigkeit ist nicht die Menge, sondern ob die Datenbank die passenden Indizes hat – ein Index ist ein zusätzliches Verzeichnis, das das Suchen abkürzt, so wie das Stichwortverzeichnis am Ende eines Buchs.
- Verschiedene Inhaltstypen – Artikel, Bilder, Kategorien, Verweise, Kommentare – bildet man über das Datenmodell ab, also über den Zuschnitt der Tabellen. Jede der hier genannten Datenbanken kann beliebig viele solcher Typen verwalten. Die Arbeit steckt im sauberen Entwurf, nicht in der Wahl des Programms.
- „Geht nicht kaputt" heißt zweierlei: Die Daten bleiben auch bei einem Absturz unversehrt (das leistet ACID), und das Programm wird über viele Jahre gepflegt, sodass Sicherheitslücken geschlossen werden und der Umstieg auf neue Versionen geregelt ist. Genau das ist mit Reifegrad gemeint.
- „Auf dem Metall" (englisch „bare metal") bedeutet: Die Datenbank läuft direkt auf dem Server, ohne Zwischenschicht wie einen Container (siehe Containerisierung von Software). Das ist der Weg, den dieses Buch beschreibt – wenige bewegliche Teile, volle Geschwindigkeit.
- Benchmarks – vergleichende Messungen unter gleichen Bedingungen – gibt es für Datenbanken reichlich. Sie sind mit Vorsicht zu lesen; dazu weiter unten mehr.
Datenbanken und Suchdienste im Überblick
Die genannten Programme lösen unterschiedliche Aufgaben. Es hilft, sie in drei Gruppen zu ordnen.
| Programm | Gruppe | Aufgabe |
|---|---|---|
| PostgreSQL | relationale Datenbank | speichert alle Inhalte dauerhaft und geordnet |
| MariaDB | relationale Datenbank | dasselbe; MediaWikis Standard-Datenbank |
| Meilisearch | Suchdienst | schnelle Wortsuche über die Texte, verzeiht Tippfehler |
| Typesense | Suchdienst | dasselbe wie Meilisearch, anderer Anbieter |
| pgvector, pg_trgm | PostgreSQL-Erweiterungen | Suche nach Bedeutung bzw. nach ähnlicher Schreibweise |
| Qdrant | Vektordatenbank | eigenständige Datenbank nur für die Suche nach Bedeutung |
Die relationale Datenbank ist das Fundament. Sie muss vorhanden sein, sonst läuft MediaWiki nicht. Alles Übrige ist Ergänzung, die die Suche verbessert.
PostgreSQL oder MariaDB
Beide sind quelloffen, seit Jahrzehnten im Einsatz, in großen Unternehmen bewährt und werden auf absehbare Zeit gepflegt. Beide verkraften die beschriebene Wissenssammlung mühelos.
- MariaDB ist eine Abspaltung von MySQL und die Datenbank, die MediaWiki von Haus aus erwartet. Die meisten MediaWiki-Anleitungen gehen von ihr aus. Sie gilt als einfach einzurichten.
- PostgreSQL ist besonders streng bei der Datenkorrektheit und lässt sich um zusätzliche Fähigkeiten erweitern. Für dieses Buch ist das der Ausschlag: Die Suche nach Bedeutung (pgvector) und die Ähnlichkeitssuche (pg_trgm) sind solche Erweiterungen. Mit PostgreSQL wird aus der ohnehin nötigen Datenbank zugleich eine Vektordatenbank – ein zweites Programm dafür entfällt.
Dieses Kapitel richtet PostgreSQL ein. Wer MariaDB bevorzugt, folgt der offiziellen MediaWiki-Anleitung; die übrigen Kapitel bleiben davon unberührt.
Suchdienst: Meilisearch oder Typesense
Die eingebaute Suche von MediaWiki wird bei vielen Seiten langsam und ungenau. Ein eigener Suchdienst führt ein separates Wörterverzeichnis und liefert Treffer schon während des Tippens. Meilisearch und Typesense sind zwei sehr ähnliche Programme dieser Art: schlank, schnell, quelloffen, für moderne Suchfelder auf Webseiten gemacht. Meilisearch ist etwas weiter verbreitet und einfacher einzurichten; Typesense ist beim Umgang mit sehr großen Datenmengen etwas flexibler. Für die Wissenssammlung dieses Buchs genügt eines von beiden.
Suche nach Bedeutung: pgvector oder Qdrant
Manchmal steht das gesuchte Wort nicht im Text – man sucht „Auto reparieren", die Seite heißt „Wagen instand setzen". Dafür wird jeder Text in eine lange Zahlenreihe umgerechnet, die seine Bedeutung beschreibt (fachlich: ein Vektor oder Embedding). Ähnliche Texte ergeben ähnliche Zahlenreihen. Diese Zahlenreihen müssen gespeichert und schnell verglichen werden.
- pgvector ist eine Erweiterung von PostgreSQL. Die Zahlenreihen liegen dann in derselben Datenbank wie die Texte. Kein zusätzliches Programm, keine zusätzliche Sicherung.
- Qdrant ist eine eigenständige Vektordatenbank. Sie ist spezialisiert und bei sehr vielen Vektoren schneller, bringt aber ein weiteres Programm ins Spiel, das eingerichtet, überwacht und gesichert werden will.
Für den beschriebenen Umfang reicht pgvector. Qdrant lohnt sich erst, wenn die Bedeutungssuche zum Kern einer eigenen Anwendung wird.
PostgreSQL auf Ubuntu einrichten
Ubuntu 26.04 bringt PostgreSQL 18 bereits in seinen eigenen Paketquellen mit. Die folgende Anleitung fügt zusätzlich die offizielle Paketquelle des PostgreSQL-Projekts hinzu. Das hat zwei Gründe: Man bekommt die neuesten Fehlerkorrekturen früher, und die Erweiterungspakete wie postgresql-18-pgvector liegen dort verlässlich bereit.
Schritt 1: Die Paketquelle eintragen
sudo apt install -y curl ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail \
https://www.postgresql.org/media/keys/ACCC4CF8.asc
. /etc/os-release
sudo sh -c "echo 'deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $VERSION_CODENAME-pgdg main' > /etc/apt/sources.list.d/pgdg.list"
sudo apt update
Die erste Zeile lädt einen digitalen Schlüssel herunter, mit dem Ubuntu prüft, dass die Pakete echt sind. Die mittlere Zeile schreibt die Adresse der Paketquelle in eine Datei; $VERSION_CODENAME setzt dabei automatisch den Namen der Ubuntu-Ausgabe ein.
Schritt 2: PostgreSQL installieren
sudo apt install -y postgresql-18
Nach der Installation läuft PostgreSQL bereits als Hintergrunddienst und startet nach jedem Server-Neustart von selbst wieder. Zur Kontrolle:
sudo systemctl status postgresql
psql --version
Schritt 3: Benutzer und Datenbank anlegen
PostgreSQL legt bei der Installation einen Systembenutzer postgres an, der die Datenbank verwaltet. Über ihn wird ein eigener Datenbankbenutzer für das Wiki angelegt und eine leere Datenbank, die ihm gehört. Die Namen (wiki) sind frei wählbar; sie müssen später in der MediaWiki-Konfiguration genau so eingetragen werden.
# Datenbankbenutzer anlegen, dabei nach einem Passwort fragen
sudo -u postgres createuser --pwprompt wiki
# Datenbank mit UTF-8-Zeichensatz anlegen, Eigentümer ist "wiki"
sudo -u postgres createdb -E UTF8 -O wiki wiki
UTF8 ist der Zeichensatz, der alle Buchstaben und Zeichen der Welt kennt – wichtig für Umlaute, Anführungszeichen und fremdsprachige Inhalte.
Schritt 4: Erweiterungen einschalten
Erweiterungen werden als Paket installiert und danach in der jeweiligen Datenbank mit einem SQL-Befehl aktiviert.
# Pakete installieren
sudo apt install -y postgresql-18-pgvector
# Erweiterungen in der Datenbank "wiki" einschalten
sudo -u postgres psql -d wiki -c "CREATE EXTENSION IF NOT EXISTS vector;"
sudo -u postgres psql -d wiki -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
sudo -u postgres psql -d wiki -c "CREATE EXTENSION IF NOT EXISTS hstore;"
- vector (aus dem Paket
pgvector) speichert und vergleicht die Zahlenreihen für die Bedeutungssuche. - pg_trgm findet ähnlich geschriebene Wörter. Es zerlegt jedes Wort in Dreier-Gruppen von Buchstaben und vergleicht diese – so wird „Müller" auch bei der Eingabe „Mueller" gefunden.
- hstore erlaubt es, zu einem Datensatz beliebige zusätzliche Schlüssel-Wert-Paare zu speichern, ohne die Tabelle umzubauen. Einige MediaWiki-Erweiterungen und Zusatzwerkzeuge setzen das voraus.
Schritt 5: Zugriff absichern
Standardmäßig nimmt PostgreSQL nur Verbindungen vom selben Rechner an. Das ist die sichere Voreinstellung und für dieses Buch richtig: MediaWiki läuft auf demselben Server wie die Datenbank. Die Datenbank sollte nicht aus dem Internet erreichbar sein. Ob das eingehalten ist, zeigt:
sudo ss -tlnp | grep 5432
Erscheint dort 127.0.0.1:5432 (und gegebenenfalls [::1]:5432), hört die Datenbank nur lokal. Erscheint 0.0.0.0:5432, ist sie nach außen offen – dann in der Datei /etc/postgresql/18/main/postgresql.conf die Zeile listen_addresses auf 'localhost' setzen und sudo systemctl restart postgresql ausführen.
Optionales Beispiel: Geodaten aus OpenStreetMap laden
Dieser Abschnitt ist kein Pflichtteil des Wiki-Aufbaus. Er zeigt an einem konkreten Fall, wie sich PostgreSQL mit der Geo-Erweiterung PostGIS um fremde Datenbestände erweitern lässt – hier das freie Kartenmaterial von OpenStreetMap für einen kleinen Ausschnitt (das Beispiel nimmt die Stadt Ahrensburg).
Zuerst die Geo-Erweiterung installieren und in der Datenbank einschalten:
sudo apt install -y postgis postgresql-18-postgis-3
sudo -u postgres psql -d wiki -c "CREATE EXTENSION IF NOT EXISTS postgis;"
PostGIS lehrt PostgreSQL den Umgang mit Orten, Linien und Flächen: Entfernungen berechnen, prüfen, ob ein Punkt in einem Gebiet liegt, Umkreissuchen. Ohne PostGIS kennt die Datenbank nur Zahlen und Text, keine Landkarte.
Dann die Kartendaten herunterladen, auf den gewünschten Ausschnitt zuschneiden und in die Datenbank einlesen:
cd $HOME
wget https://download.geofabrik.de/europe/germany/schleswig-holstein-latest.osm.pbf
sudo apt install -y osmosis osm2pgsql
# Auf einen rechteckigen Ausschnitt zuschneiden (Längen- und Breitengrade)
osmosis --read-pbf file=schleswig-holstein-latest.osm.pbf \
--bounding-box left=10.1141 right=10.3716 top=53.7136 bottom=53.6249 \
--write-pbf file=ahrensburg.pbf
# Den Ausschnitt in die Datenbank "wiki" schreiben
osm2pgsql -d wiki -H localhost -U wiki --create -G --hstore -W ahrensburg.pbf
schleswig-holstein-latest.osm.pbfist die komprimierte Kartendatei für das gesamte Bundesland, bezogen vom Anbieter Geofabrik.osmosisschneidet daraus mit--bounding-boxein Rechteck heraus; die vier Werte sind die Grenzen in Längen- und Breitengraden.osm2pgsqlliest den Ausschnitt in die Datenbank.--createlegt die nötigen Tabellen an,-Gerzeugt einfache Geometrien,--hstoreübernimmt alle zusätzlichen Angaben (Straßennamen, Öffnungszeiten und so weiter) in ein hstore-Feld,-Wfragt nach dem Datenbankpasswort.
Danach stehen die Straßen, Gebäude und Punkte des Ausschnitts als Tabellen in der Datenbank und lassen sich mit SQL abfragen.
Suchdienst einrichten
Meilisearch
Meilisearch wird über die Paketquelle des Anbieters installiert:
echo "deb [trusted=yes] https://apt.fury.io/meilisearch/ /" \
| sudo tee /etc/apt/sources.list.d/meilisearch.list
sudo apt update
sudo apt install -y meilisearch-http
Meilisearch braucht einen Hauptschlüssel (englisch „master key"), ohne den jeder mit Zugang zum Server die Suchdaten lesen und ändern könnte. Einen zufälligen Schlüssel erzeugen und zusammen mit den übrigen Einstellungen in einer Konfigurationsdatei ablegen:
openssl rand -base64 32
Datei /etc/meilisearch.toml anlegen (der Wert bei master_key ist der eben erzeugte Schlüssel):
env = "production"
master_key = "HIER_DEN_ERZEUGTEN_SCHLUESSEL_EINSETZEN"
http_addr = "127.0.0.1:7700"
db_path = "/var/lib/meilisearch/data"
Die Adresse 127.0.0.1 sorgt dafür, dass Meilisearch nur vom selben Server aus erreichbar ist. Anschließend als Hintergrunddienst einrichten. Dazu die Datei /etc/systemd/system/meilisearch.service anlegen:
[Unit]
Description=Meilisearch
After=network.target
[Service]
ExecStart=/usr/bin/meilisearch --config-file-path /etc/meilisearch.toml
Restart=on-failure
DynamicUser=yes
StateDirectory=meilisearch
[Install]
WantedBy=multi-user.target
Starten und für den automatischen Start nach einem Neustart vormerken:
sudo systemctl daemon-reload
sudo systemctl enable --now meilisearch
Typesense
Typesense wird als fertiges Paket von der Seite des Anbieters heruntergeladen und installiert:
curl -O https://dl.typesense.org/releases/29.0/typesense-server-29.0-amd64.deb
sudo apt install -y ./typesense-server-29.0-amd64.deb
Bei der Installation fragt das Paket nach einem API-Schlüssel (dieselbe Rolle wie Meilisearchs Hauptschlüssel) und legt selbst einen Hintergrunddienst an. Die Einstellungen stehen danach in /etc/typesense/typesense-server.ini. Dort sollte api-address = 127.0.0.1 eingetragen sein, damit der Dienst nur lokal erreichbar ist. Nach einer Änderung:
sudo systemctl restart typesense-server
sudo systemctl enable typesense-server
Zur Geschwindigkeit: Was Benchmarks sagen – und was nicht
Für PostgreSQL und MariaDB gibt es zahllose Vergleichsmessungen, und je nach Testaufbau gewinnt mal die eine, mal die andere. Für den Alltag einer Wissenssammlung ist das ohne Bedeutung. Drei Punkte zählen mehr als jede Messung:
- Die richtigen Indizes. Eine Abfrage ohne passenden Index durchsucht die ganze Tabelle; mit Index springt sie sofort zum Ziel. Der Unterschied ist oft der Faktor Tausend. MediaWiki bringt seine Indizes mit; bei eigenen Zusatzprogrammen muss man selbst daran denken.
- Nur laden, was gebraucht wird. Ein Programm, das immer alle Einträge holt und dann wegwirft, was es nicht braucht, wird mit jeder Zeile langsamer. Gute Programme holen seitenweise.
- Ein Zwischenspeicher. Wird eine fertige Antwort für kurze Zeit vorgehalten (etwa mit Redis oder direkt im Webserver, siehe Webserver), spielt die Geschwindigkeit der Datenbank für diese Anfrage keine Rolle mehr.
Kurz: Die Wahl zwischen zwei ausgereiften Datenbanken entscheidet über die Geschwindigkeit weit weniger als der Umgang mit ihnen.
Für dieses Buch
Die Wissenssammlung braucht genau eine relationale Datenbank. Dieses Buch nimmt PostgreSQL, weil sich damit die Bedeutungssuche (pgvector) und die Ähnlichkeitssuche (pg_trgm) ohne ein weiteres Programm abdecken lassen. Wer nur MediaWiki betreiben und der offiziellen Anleitung folgen will, kann ebenso gut MariaDB einsetzen.
Als Suchdienst genügt Meilisearch oder Typesense – eines von beiden, nicht beide. Für die Bedeutungssuche bleibt es bei pgvector; Qdrant ist für diesen Umfang zu viel.
Die Datenbank läuft direkt auf dem Server und ist nur von dort erreichbar, nicht aus dem Internet. Gesichert werden muss vor allem ihr Inhalt: ein regelmäßiger, automatischer Export (pg_dump) an einen zweiten Ort gehört zu jedem Datenbankbetrieb dazu.
Fazit
Eine Datenbank legt die Inhalte der Wissenssammlung geordnet ab und gibt sie schnell wieder heraus, ohne bei gleichzeitigen Zugriffen oder einem Absturz Schaden zu nehmen. PostgreSQL und MariaDB sind beide quelloffen, ausgereift und für eine Million Einträge weit mehr als ausreichend; dieses Buch wählt PostgreSQL wegen seiner Erweiterungen. Auf Ubuntu 26.04 wird PostgreSQL 18 über die offizielle Paketquelle eingerichtet, danach werden Benutzer, Datenbank und die Erweiterungen vector, pg_trgm und hstore angelegt. Meilisearch oder Typesense ergänzen die schnelle Wortsuche, pgvector die Suche nach Bedeutung. Ob die Sammlung schnell bleibt, entscheidet nicht die Wahl der Datenbank, sondern die richtigen Indizes, sparsames Laden und ein Zwischenspeicher.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Tileserver
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Das Kapitel Datenbank zeigt in einem optionalen Abschnitt, wie sich das freie Kartenmaterial von OpenStreetMap mit der Geo-Erweiterung PostGIS in PostgreSQL laden lässt. Danach liegen Straßen, Gebäude und Punkte als Tabellen in der Datenbank. Was noch fehlt, ist der Schritt von diesen Tabellen zu einer Landkarte, die ein Besucher im Browser sehen, verschieben und heranzoomen kann. Diesen Schritt erledigt ein Tileserver.
Dieses Kapitel erklärt, was ein Tileserver ist und worin sich Vektorkacheln und Rasterkacheln unterscheiden. Danach stellt es die bekanntesten quelloffenen Tileserver vor und richtet zwei davon auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) ein: Martin für Vektorkacheln und die Kombination renderd + mod_tile für das klassische Kartenbild als PNG. Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen.
Was ein Tileserver ist
Eine Weltkarte in voller Auflösung wäre ein Bild von vielen Millionen Bildpunkten Kantenlänge – viel zu groß, um es an einen Browser zu schicken. Deshalb wird die Karte in kleine, quadratische Stücke zerschnitten, meist 256 Bildpunkte breit und hoch. Diese Stücke heißen Kacheln (englisch „tiles"). Der Browser lädt immer nur die paar Dutzend Kacheln, die gerade auf den Bildschirm passen.
Damit das Heranzoomen funktioniert, gibt es die Karte in mehreren Zoomstufen. Stufe 0 ist die ganze Welt in einer einzigen Kachel. Bei jeder weiteren Stufe wird jede Kachel in vier neue geteilt, die Karte also doppelt so genau. Stufe 19 zeigt einzelne Häuser. Jede Kachel hat eine feste Adresse aus drei Zahlen: Zoomstufe, Spalte und Zeile – im Web meist als .../{z}/{x}/{y}.png geschrieben. Wenn man in einer Online-Karte den Ausschnitt verschiebt, fordert der Browser einfach die Kacheln mit den neuen Nummern nach. Diese Art der beweglichen Karte nennt man Slippy Map.
Ein Tileserver ist das Programm, das auf solche Kachelanfragen antwortet. Es nimmt die drei Zahlen entgegen, sucht die passenden Geodaten aus der Datenbank, formt daraus eine Kachel und schickt sie zurück.
Vektorkacheln oder Rasterkacheln
Es gibt zwei grundsätzlich verschiedene Sorten von Kacheln.
Rasterkacheln sind fertige Bilder, meist im Format PNG. Der Server zeichnet die Karte – Farben, Linienstärken, Beschriftungen – vollständig vorab und legt das Ergebnis als Bilddatei ab. Der Browser muss die Kachel nur noch anzeigen. Das funktioniert in jedem Browser und mit einer sehr einfachen Karten-Bibliothek. Der Preis: Das Aussehen der Karte steckt fest im Bild. Für eine andere Farbe, eine andere Schrift oder eine gedrehte Ansicht muss der Server alle Kacheln neu zeichnen. Und für jede Zoomstufe, jeden Bildschirm und jede Auflösung müssen eigene Bilder vorgehalten werden, was viel Speicherplatz kostet.
Vektorkacheln enthalten keine Bilder, sondern die nackten Geometrien mitsamt ihren Eigenschaften: „hier verläuft eine Straße vom Typ Wohnstraße mit Namen Hauptstraße", „hier liegt eine Fläche vom Typ Park". Gezeichnet wird erst im Browser, von einer modernen Karten-Bibliothek wie MapLibre GL. Das hat mehrere Vorteile: Die Kacheln sind klein, das Kartenbild ist bei jeder Bildschirmauflösung gestochen scharf, die Karte lässt sich stufenlos zoomen und drehen, und das gesamte Aussehen lässt sich ändern, ohne eine einzige Kachel neu zu erzeugen. Der Nachteil: Der Browser muss mehr Arbeit leisten, und man braucht eine aktuelle Karten-Bibliothek mit JavaScript.
| Rasterkacheln | Vektorkacheln | |
|---|---|---|
| Inhalt | fertiges PNG-Bild | Geometrien und Eigenschaften |
| Gezeichnet wird | auf dem Server, vorab | im Browser, sofort |
| Aussehen ändern | alle Kacheln neu zeichnen | nur Stildatei austauschen |
| Speicherbedarf | hoch | niedrig |
| Browser-Anforderung | gering | moderne Karten-Bibliothek |
Für einen neuen Kartendienst sind Vektorkacheln heute der Normalfall. Rasterkacheln bleiben sinnvoll, wenn das vertraute OpenStreetMap-Kartenbild eins zu eins gebraucht wird oder wenn die Karte in sehr alten Browsern oder in Druckerzeugnissen funktionieren muss.
Quelloffene Tileserver im Überblick
Alle folgenden Programme sind quelloffen und können ihre Kacheln direkt aus einer PostgreSQL-Datenbank mit PostGIS erzeugen.
| Programm | Sprache | Kacheln | Kurzcharakter |
|---|---|---|---|
| Martin | Rust | Vektor | erkennt Tabellen von selbst, kaum Konfiguration, sehr schnell |
| Tegola | Go | Vektor | Ebenen einzeln in einer Textdatei beschrieben, eingebauter Zwischenspeicher |
| t-rex | Rust | Vektor | ähnlich wie Tegola, erzeugt auch Kachelpakete zum Verteilen |
| renderd + mod_tile | C | Raster | das Gespann hinter dem OpenStreetMap-Kartenbild, rendert mit Mapnik |
- Martin ist Teil des MapLibre-Projekts. Es verbindet sich mit der Datenbank und veröffentlicht jede Tabelle mit einer Geometrie-Spalte automatisch als Vektorkachel-Quelle. Für einen einfachen Dienst braucht es keine Konfigurationsdatei.
- Tegola verlangt eine Konfigurationsdatei im TOML-Format, in der jede Kartenebene mit ihrer Tabelle und ihrer SQL-Abfrage steht. Das ist mehr Arbeit, gibt aber genaue Kontrolle darüber, was in welcher Zoomstufe erscheint. Ein Zwischenspeicher für die fertigen Kacheln ist eingebaut.
- t-rex ähnelt Tegola in Aufbau und Zweck. Es kann Kacheln zusätzlich als eine einzige Paketdatei (MBTiles) ausgeben, die sich leicht auf andere Server kopieren lässt.
- renderd + mod_tile ist kein Vektor-, sondern ein Raster-Gespann. Mapnik ist die Bibliothek, die das eigentliche Kartenbild zeichnet; renderd ist ein Hintergrunddienst, der Zeichenaufträge in eine Warteschlange stellt und fertige Kacheln auf der Festplatte ablegt; mod_tile ist ein Modul für den Apache-Webserver, das Kacheln ausliefert und fehlende bei renderd nachbestellt. Dieses Gespann steckt hinter der Karte auf openstreetmap.org und ist unter switch2osm.org ausführlich dokumentiert.
Empfehlung für dieses Buch
Für einen neuen Kartendienst auf Basis der OpenStreetMap-Daten aus dem Kapitel Datenbank ist Martin die naheliegende Wahl: Die Datenbank mit PostGIS ist ohnehin vorhanden, die Einrichtung ist kurz, und Vektorkacheln lassen sich später ohne Neuberechnung umgestalten.
Wer das exakt gleiche Kartenbild wie openstreetmap.org als PNG braucht – etwa als Hintergrund für eine bestehende Anwendung, die nur Rasterkacheln versteht –, richtet stattdessen renderd + mod_tile ein. Beide Wege sind unten beschrieben; nötig ist nur einer.
Voraussetzungen
- Ein Server mit Ubuntu 26.04 und Zugang über SSH.
- PostgreSQL mit PostGIS ist eingerichtet und enthält einen OpenStreetMap-Ausschnitt (siehe Datenbank, Abschnitt „Geodaten aus OpenStreetMap laden"). PostGIS muss mindestens in Version 3.1 vorliegen; die Paketquelle aus dem Datenbank-Kapitel erfüllt das.
- Für den öffentlichen Zugang ein Webserver mit einer Domain und einem SSL-Zertifikat (siehe Webserver).
Vektorkacheln mit Martin einrichten
Schritt 1: Martin installieren
Das Projekt bietet ein fertiges Debian-Paket auf seiner Veröffentlichungsseite an. Es enthält nur eine einzige Programmdatei ohne weitere Abhängigkeiten.
cd /tmp
curl -L -O https://github.com/maplibre/martin/releases/latest/download/debian-x86_64.deb
sudo apt install -y ./debian-x86_64.deb
# Zur Kontrolle
martin --version
Schritt 2: Verbindung zur Datenbank prüfen
Martin bekommt die Zugangsdaten zur Datenbank als Verbindungszeichenkette übergeben. Sie hat die Form postgresql://BENUTZER:PASSWORT@localhost/DATENBANK. Für die Datenbank wiki aus dem Datenbank-Kapitel, in die der OpenStreetMap-Ausschnitt geladen wurde, lautet ein kurzer Test:
martin postgresql://wiki:DATENBANKPASSWORT@localhost/wiki
Beim Start durchsucht Martin die Datenbank und meldet in der Konsole, welche Tabellen es als Kachel-Quellen gefunden hat – bei einem osm2pgsql-Import sind das planet_osm_point, planet_osm_line, planet_osm_polygon und planet_osm_roads. Der Dienst hört danach auf 0.0.0.0:3000. Mit Strg+C wird er wieder beendet.
Schritt 3: Martin als Dienst einrichten
Für den Dauerbetrieb soll Martin als Hintergrunddienst laufen, nur lokal erreichbar sein und die Zugangsdaten nicht in der Prozessliste zeigen. Dazu die Zugangsdaten in eine geschützte Umgebungsdatei schreiben:
sudo install -d -m 750 /etc/martin
echo 'DATABASE_URL=postgresql://wiki:DATENBANKPASSWORT@localhost/wiki' \
| sudo tee /etc/martin/martin.env
sudo chmod 640 /etc/martin/martin.env
Dann die Dienstdatei /etc/systemd/system/martin.service anlegen:
[Unit]
Description=Martin Vektorkachel-Server
After=network.target postgresql.service
[Service]
EnvironmentFile=/etc/martin/martin.env
ExecStart=/usr/bin/martin --listen-addresses 127.0.0.1:3000
Restart=on-failure
DynamicUser=yes
[Install]
WantedBy=multi-user.target
--listen-addresses 127.0.0.1:3000 sorgt dafür, dass Martin nur vom Server selbst erreichbar ist; nach außen kommt später der Webserver davor. Starten und für den automatischen Start nach einem Neustart vormerken:
sudo systemctl daemon-reload
sudo systemctl enable --now martin
sudo systemctl status martin
Schritt 4: Testen
Martin stellt unter /catalog ein Verzeichnis aller Kachel-Quellen bereit:
curl http://127.0.0.1:3000/catalog
Für jede Quelle gibt es unter /QUELLE eine Beschreibungsdatei (TileJSON) und darunter die Kacheln selbst unter /QUELLE/{z}/{x}/{y}. Mehrere Tabellen lassen sich zu einer gemeinsamen Quelle verbinden, indem man ihre Namen mit Komma aneinanderreiht:
curl "http://127.0.0.1:3000/planet_osm_polygon,planet_osm_line,planet_osm_point"
Schritt 5: Den Webserver davorstellen
Der Zugang aus dem Internet läuft über den Webserver, der die Verbindung verschlüsselt und die Anfragen an Martin weiterreicht (siehe Webserver). Ein Block für NGINX unter /etc/nginx/sites-available/karten:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name karten.meine-domain.de;
ssl_certificate /etc/letsencrypt/live/karten.meine-domain.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/karten.meine-domain.de/privkey.pem;
# Fertige Kacheln einen Tag lang zwischenspeichern
proxy_cache_path /var/cache/nginx/karten levels=1:2
keys_zone=karten:10m max_size=2g inactive=1d;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_cache karten;
proxy_cache_valid 200 1d;
add_header X-Cache-Status $upstream_cache_status;
}
}
Der Zwischenspeicher (proxy_cache) ist bei Martin wichtig: Anders als das Raster-Gespann legt Martin fertige Kacheln nicht selbst auf der Festplatte ab, sondern erzeugt sie bei jeder Anfrage neu. Der Webserver hält die Antworten dann für kurze Zeit vor, sodass beliebte Kacheln nicht bei jedem Aufruf die Datenbank belasten.
Schritt 6: Die Karte im Browser anzeigen
Zum Anzeigen dient MapLibre GL JS, eine quelloffene Karten-Bibliothek. Eine einfache HTML-Seite, die die Umrisse aus den Vektorkacheln zeichnet:
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdnjs.cloudflare.com/ajax/libs/maplibre-gl/5.8.0/maplibre-gl.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/maplibre-gl/5.8.0/maplibre-gl.min.js"></script>
<style> body { margin: 0 } #map { height: 100vh } </style>
</head>
<body>
<div id="map"></div>
<script>
const map = new maplibregl.Map({
container: "map",
center: [10.24, 53.67],
zoom: 13,
style: {
version: 8,
sources: {
osm: {
type: "vector",
url: "https://karten.meine-domain.de/planet_osm_polygon,planet_osm_line,planet_osm_point"
}
},
layers: [
{ id: "hintergrund", type: "background", paint: { "background-color": "#f5f5f3" } },
{ id: "flaechen", type: "fill", source: "osm", "source-layer": "planet_osm_polygon",
paint: { "fill-color": "#e0e0d8" } },
{ id: "linien", type: "line", source: "osm", "source-layer": "planet_osm_line",
paint: { "line-color": "#b0b0a8" } }
]
}
});
</script>
</body>
</html>
Das ist bewusst schlicht. Ein vollständiges, hübsches Kartenbild entsteht über eine ausgearbeitete Stildatei; fertige quelloffene Stile für OpenStreetMap-Vektorkacheln gibt es beim Projekt OpenMapTiles und bei VersaTiles.
Rasterkacheln mit renderd und mod_tile einrichten
Dieser Weg erzeugt das vertraute OpenStreetMap-Kartenbild als PNG. Er ist aufwendiger als Martin, weil das Kartenaussehen aus einem umfangreichen Stilprojekt übersetzt werden muss.
Was zusammenspielt
- osm2pgsql liest die OpenStreetMap-Daten in die Datenbank (siehe Datenbank). Für dieses Kartenbild braucht der Import ein bestimmtes Tabellenschema.
- openstreetmap-carto ist das quelloffene Stilprojekt, das festlegt, wie die Karte aussieht – welche Farben, welche Schriften, ab welcher Zoomstufe welche Beschriftung.
- Mapnik ist die Bibliothek, die anhand dieses Stils aus den Datenbanktabellen das Bild zeichnet.
- renderd ist der Hintergrunddienst, der Zeichenaufträge sammelt, der Reihe nach abarbeitet und fertige Kacheln unter
/var/cache/renderd/tilesablegt. - mod_tile ist ein Apache-Modul. Es liefert vorhandene Kacheln sofort aus und meldet fehlende oder veraltete an renderd zur Nachproduktion.
Weil dieses Gespann Apache voraussetzt, läuft es am einfachsten auf einem eigenen Server oder – wenn NGINX bereits Port 80 und 443 belegt – hinter NGINX auf einem anderen Port.
Schritt 1: Pakete installieren
Ubuntu bringt alle Bestandteile in seinen Paketquellen mit.
sudo apt update
sudo apt install -y \
apache2 libapache2-mod-tile renderd \
mapnik-utils python3-mapnik python3-psycopg2 python3-yaml \
gdal-bin node-carto \
osm2pgsql git unzip
Schritt 2: Datenbank und Daten vorbereiten
Für das Kartenbild wird ein eigener Datenbankbenutzer und eine eigene Datenbank gis angelegt (die Trennung von der Wiki-Datenbank hält die Karten-Tabellen übersichtlich):
sudo -u postgres createuser _renderd
sudo -u postgres createdb -E UTF8 -O _renderd gis
sudo -u postgres psql -d gis -c "CREATE EXTENSION IF NOT EXISTS postgis;"
sudo -u postgres psql -d gis -c "CREATE EXTENSION IF NOT EXISTS hstore;"
Dann das Stilprojekt holen, denn der Import braucht die darin enthaltenen Regeldateien:
mkdir -p ~/src && cd ~/src
git clone https://github.com/gravitystorm/openstreetmap-carto.git
cd openstreetmap-carto
Jetzt den OpenStreetMap-Ausschnitt importieren – im Beispiel wieder der Ausschnitt aus dem Datenbank-Kapitel. Der Import verwendet die Regeldateien des Stilprojekts, damit die Tabellen genau so heißen und aufgebaut sind, wie der Stil sie erwartet:
osm2pgsql -d gis --create --slim -G --hstore \
--tag-transform-script ~/src/openstreetmap-carto/openstreetmap-carto.lua \
-S ~/src/openstreetmap-carto/openstreetmap-carto.style \
~/ahrensburg.pbf
Anschließend die vom Stil erwarteten Zusatzdaten (Küstenlinien, Landflächen) und Schriften laden sowie die zusätzlichen Datenbank-Indizes anlegen:
cd ~/src/openstreetmap-carto
scripts/get-external-data.py
./get-fonts.sh
sudo -u postgres psql -d gis -f indexes.sql
Schritt 3: Den Kartenstil übersetzen
Das Stilprojekt beschreibt die Karte in vielen kurzen Regeldateien. Mapnik erwartet daraus eine einzige große XML-Datei. Das Werkzeug carto fasst die Regeln zu dieser XML-Datei zusammen:
cd ~/src/openstreetmap-carto
carto project.mml > mapnik.xml
Die entstandene Datei mapnik.xml ist der Bauplan, nach dem renderd später zeichnet.
Schritt 4: renderd einstellen
Die Einstellungen von renderd stehen in /etc/renderd.conf. Wichtig sind der Pfad zur eben erzeugten mapnik.xml, die Adresse, unter der die Kacheln erreichbar sein sollen, und der Ablageort:
sudo nano /etc/renderd.conf
Im Abschnitt für die Karte (er heißt oft [default]) diese Werte setzen:
[default]
URI=/tiles/
XML=/home/thorsten/src/openstreetmap-carto/mapnik.xml
HOST=localhost
TILEDIR=/var/cache/renderd/tiles
MAXZOOM=20
Danach den Dienst starten:
sudo systemctl enable --now renderd
sudo systemctl status renderd
Schritt 5: Apache mit mod_tile einstellen
Das Paket libapache2-mod-tile legt eine Beispielkonfiguration an, die nur noch aktiviert werden muss. Sie verweist auf denselben Ablageort und dieselbe Adresse wie renderd:
LoadModule tile_module /usr/lib/apache2/modules/mod_tile.so
<IfModule tile_module>
ModTileTileDir /var/cache/renderd/tiles
ModTileRenderdSocketName /run/renderd/renderd.sock
AddTileConfig /tiles/ default
</IfModule>
Aktivieren und Apache neu laden:
sudo a2enmod tile
sudo a2enconf renderd
sudo systemctl reload apache2
Schritt 6: Testen
Eine einzelne Kachel abrufen – die Zahlen stehen für Zoomstufe 0, Spalte 0, Zeile 0, also die ganze Welt:
curl -o /tmp/test.png http://localhost/tiles/0/0/0.png
Kommt eine PNG-Datei zurück, arbeitet das Gespann. Zum Anzeigen im Browser genügt hier die schlanke Bibliothek Leaflet:
<div id="map" style="height: 100vh"></div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
<script>
const map = L.map("map").setView([53.67, 10.24], 13);
L.tileLayer("https://karten.meine-domain.de/tiles/{z}/{x}/{y}.png", {
maxZoom: 20,
attribution: "Karte: OpenStreetMap-Mitwirkende"
}).addTo(map);
</script>
Schritt 7: Kacheln im Voraus erzeugen
Standardmäßig zeichnet renderd eine Kachel erst, wenn sie zum ersten Mal angefragt wird – der erste Besucher eines Gebiets wartet dann kurz. Für kleine, oft genutzte Ausschnitte lohnt es sich, die Kacheln der unteren Zoomstufen vorab zu erzeugen:
render_list -m default -a -z 0 -Z 14 --num-threads 4
-z 0 -Z 14 legt den Bereich der Zoomstufen fest, --num-threads die Anzahl paralleler Zeichenvorgänge. Höhere Zoomstufen für die ganze Welt vorab zu erzeugen ist nicht praktikabel – dort wächst die Zahl der Kacheln ins Unermessliche.
Daten aktuell halten
OpenStreetMap ändert sich ständig. Um den lokalen Bestand nachzuführen, gibt es das Werkzeug osm2pgsql-replication: Es lädt regelmäßig die Änderungen seit dem letzten Stand und schreibt sie in die Datenbank. Betroffene Kacheln werden dabei als „veraltet" vermerkt und beim nächsten Abruf neu gezeichnet. Für einen kleinen Ausschnitt genügt oft auch ein wöchentlicher Neu-Import.
Für dieses Buch
Der Kartendienst ist eine optionale Ergänzung zum Web Stack, kein Pflichtbestandteil. Er baut auf der Datenbank mit PostGIS auf, die im Kapitel Datenbank eingerichtet wird.
Empfohlen wird Martin: Es erzeugt Vektorkacheln direkt aus den vorhandenen OpenStreetMap-Tabellen, läuft als schlanker Hintergrunddienst nur lokal und bekommt über den Webserver aus dem Kapitel Webserver einen verschlüsselten, zwischengespeicherten Zugang. Das Aussehen der Karte steckt in einer austauschbaren Stildatei im Browser und lässt sich jederzeit ändern.
Das Gespann renderd + mod_tile ist die richtige Wahl, wenn genau das bekannte OpenStreetMap-Kartenbild als PNG gebraucht wird. Es ist aufwendiger einzurichten, verlangt Apache und benötigt mehr Speicherplatz für die fertigen Kacheln, liefert dafür aber ohne JavaScript in jedem Browser ein vollständiges Kartenbild.
Fazit
Ein Tileserver macht aus Geodaten in der Datenbank eine bewegliche Karte, indem er sie in kleine, quadratisch nummerierte Kacheln zerlegt. Rasterkacheln sind fertige Bilder – einfach anzuzeigen, aber unflexibel und speicherhungrig. Vektorkacheln enthalten die Geometrien und werden erst im Browser gezeichnet – klein, scharf und jederzeit umgestaltbar. Für einen neuen Dienst auf Basis der OpenStreetMap-Daten dieses Buchs ist Martin die einfachste Lösung: Debian-Paket installieren, Verbindungszeichenkette zur Datenbank angeben, als Dienst hinter den Webserver stellen. Wer das klassische OpenStreetMap-Kartenbild als PNG braucht, richtet renderd + mod_tile mit Mapnik und dem Stilprojekt openstreetmap-carto ein.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Webserver
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
MediaWiki, die Grundlage der Wissenssammlung dieses Buchs, besteht aus vielen PHP-Dateien (siehe Laufzeitumgebung). Damit ein Besucher diese Seiten im Browser sehen kann, fehlt noch ein Programm dazwischen: der Webserver. Er nimmt die Anfrage aus dem Internet entgegen, holt die passende Seite und schickt sie zurück.
Dieses Kapitel erklärt, was ein Webserver ist, stellt die vier bekanntesten vor und zeigt für die drei, die man wirklich selbst betreibt, wie man sie auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) einrichtet und mit einem kostenlosen SSL-Zertifikat auf verschlüsselte Verbindungen (HTTPS) umstellt. Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen.
Was ein Webserver ist
Man kann sich einen Webserver wie den Empfang in einem großen Bürohaus vorstellen. Ein Besucher kommt herein und nennt sein Anliegen ("Ich möchte die Startseite von example.de sehen"). Der Empfang schaut nach, wer zuständig ist, holt die Auskunft und gibt sie heraus. Der Besucher muss nie selbst durch das Gebäude laufen.
Genau das macht ein Webserver mit Anfragen aus dem Internet. Er beherrscht dabei zwei Aufgaben:
- Feste Dateien ausliefern. Bilder, Stylesheets, heruntergeladene Dokumente oder eine einfache HTML-Seite liegen als Datei auf der Festplatte. Der Webserver schickt sie unverändert an den Browser.
- Anfragen weiterreichen. Seiten, die erst erzeugt werden müssen – jede MediaWiki-Seite gehört dazu –, gibt der Webserver an das zuständige Programm im Hintergrund weiter, bei MediaWiki an PHP-FPM. Er wartet auf dessen Antwort und leitet sie an den Browser zurück. In dieser Rolle heißt der Webserver auch Reverse Proxy.
Dazu kommen Aufgaben, die man an einer zentralen Stelle bündeln möchte: die Verschlüsselung der Verbindung (HTTPS), das Umleiten von alten auf neue Adressen, das Sperren unerwünschter Zugriffe und das Zusammenfassen mehrerer Programme unter einer Adresse. Auch der Zwischenspeicher aus dem Kapitel Containerisierung von Software sitzt oft hinter demselben Webserver.
Die vier bekanntesten Webserver
NGINX
NGINX (gesprochen "Engine-X") wurde entwickelt, um sehr viele gleichzeitige Verbindungen mit wenig Arbeitsspeicher zu bewältigen. Es liefert feste Dateien schnell aus und ist als Reverse Proxy vor anderen Programmen weit verbreitet. Die offizielle MediaWiki-Anleitung und ein Großteil der Beispiele im Internet gehen von NGINX aus. Die Einstellungen stehen in kurzen Textblöcken; man beschreibt darin, welche Adresse zu welchem Verzeichnis oder welchem Hintergrunddienst gehört.
Für die Wissenssammlung dieses Buchs ist NGINX die naheliegende Wahl: am meisten Anleitungen, sparsam im Verbrauch, gut mit PHP-FPM zu verbinden.
Apache HTTP Server
Der Apache HTTP Server ist der älteste der vier und lange Zeit der Standard im Web gewesen. Viele fertige Anleitungen und Auslieferungspakete – auch die "einfache" MediaWiki-Installation – sind auf Apache zugeschnitten. Seine Stärke ist die Erweiterbarkeit über Zusatzmodule und die Möglichkeit, Einstellungen pro Verzeichnis in einer Datei namens .htaccess abzulegen, ohne den ganzen Server neu zu laden.
Diese Bequemlichkeit hat einen Preis: Apache verbraucht bei vielen gleichzeitigen Besuchern mehr Arbeitsspeicher als NGINX. Für eine kleine Wissenssammlung fällt das kaum ins Gewicht. Wer bereits Apache-Erfahrung hat, kann bei Apache bleiben.
Caddy
Caddy ist der jüngste der vier und verfolgt ein klares Ziel: möglichst wenig Einrichtung. Sein größter Unterschied zu den anderen ist die automatische Verschlüsselung. Caddy besorgt sich das SSL-Zertifikat beim ersten Start selbst und erneuert es von allein – ein zusätzliches Werkzeug wie Certbot entfällt vollständig. Die Konfigurationsdatei ("Caddyfile") ist oft nur wenige Zeilen lang.
Caddy ist eine gute Wahl für alle, die den Server möglichst einfach halten wollen und keine besonderen Ansprüche an die Feinabstimmung haben. Es gibt weniger fertige Anleitungen als für NGINX, dafür braucht man auch weniger davon.
Pingora
Pingora fällt aus der Reihe. Es ist kein fertiger Webserver, den man installiert und startet, sondern ein Baukasten in der Programmiersprache Rust, mit dem Entwickler eigene Netzwerkdienste bauen. Die Firma Cloudflare hat Pingora zunächst für den Eigenbedarf geschrieben – als Ersatz für NGINX in ihrem weltweiten Netz – und den Baukasten später quelloffen veröffentlicht.
Für den Aufbau dieses Buchs spielt Pingora keine Rolle. Es gibt kein apt-Paket dafür; man bräuchte die vollständige Rust-Entwicklungsausstattung und müsste den Dienst selbst programmieren. Pingora ist hier nur genannt, weil der Name in Vergleichen und Nachrichten auftaucht. Wer einmal ein fertiges Programm betreibt, das auf Pingora aufbaut, merkt davon im Betrieb nichts Besonderes.
Kurzvergleich
| Webserver | Art | Verschlüsselung | Für diesen Aufbau |
|---|---|---|---|
| NGINX | fertiger Server | mit Certbot | empfohlen, die meisten Anleitungen |
| Apache HTTP Server | fertiger Server | mit Certbot | geeignet, etwas mehr Verbrauch |
| Caddy | fertiger Server | eingebaut, automatisch | geeignet, am wenigsten Einrichtung |
| Pingora | Programmbaukasten (Rust) | selbst zu bauen | nicht relevant, nur zum Einordnen |
Installation auf Ubuntu 26.04
Vor der Installation lohnt ein Blick auf die Ports: Ein Webserver belegt Port 80 (unverschlüsselt) und Port 443 (verschlüsselt). Läuft dort schon ein anderer Webserver, muss dieser vorher gestoppt werden – zwei gleichzeitig geht nicht.
NGINX
sudo apt update
sudo apt install nginx
# Zeigt die installierte Version zur Kontrolle an
nginx -v
Nach der Installation läuft NGINX bereits und zeigt unter der IP-Adresse des Servers eine Willkommensseite. Diese gehört zur mitgelieferten Beispielkonfiguration. Bevor eine eigene Seite eingerichtet wird, entfernt man sie:
sudo rm /etc/nginx/sites-enabled/default
Die eigenen Einstellungen kommen als neue Datei nach /etc/nginx/sites-available/ und werden mit einem Verweis ("Symlink") nach /etc/nginx/sites-enabled/ aktiv geschaltet. Nach jeder Änderung prüft sudo nginx -t die Datei auf Fehler, sudo systemctl reload nginx übernimmt sie.
Apache HTTP Server
sudo apt update
sudo apt install apache2
# Zeigt die installierte Version zur Kontrolle an
apache2 -v
Auch Apache startet sofort mit einer Standardseite. Für den Betrieb hinter PHP-FPM und für die spätere Verschlüsselung werden einige Zusatzmodule eingeschaltet:
sudo a2enmod proxy_fcgi setenvif rewrite headers ssl
sudo systemctl restart apache2
Die Standard-Beispielseite schaltet man mit sudo a2dissite 000-default ab. Eigene Konfigurationsdateien liegen unter /etc/apache2/sites-available/ und werden mit sudo a2ensite <name> aktiviert. sudo apachectl configtest prüft auf Fehler, sudo systemctl reload apache2 übernimmt Änderungen.
Caddy
Caddy liegt nicht in den Paketquellen von Ubuntu. Es wird über die offizielle Paketquelle des Herstellers eingerichtet, mitsamt einem digitalen Schlüssel, mit dem Ubuntu die Echtheit der Pakete prüft:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
Danach läuft Caddy als Hintergrunddienst. Die gesamte Konfiguration steht in der Datei /etc/caddy/Caddyfile. Für MediaWiki genügen wenige Zeilen: der Domainname, das Wurzelverzeichnis und die Weitergabe von PHP-Dateien an PHP-FPM. Nach dem Ändern der Datei übernimmt sudo systemctl reload caddy die neuen Einstellungen. Um Zertifikate muss man sich nicht kümmern – dazu unten mehr.
Verschlüsselung mit HTTPS
Eine Website sollte heute ausschließlich über verschlüsselte Verbindungen erreichbar sein. Sichtbar wird das am Kürzel https:// und am Schloss-Symbol im Browser. Die Verschlüsselung schützt nicht nur Passwörter, sondern verhindert auch, dass unterwegs jemand den Inhalt der Seiten mitliest oder verändert.
Grundlage ist ein SSL-Zertifikat. Es ist eine kleine, digital unterschriebene Datei, die bestätigt: "Dieser Server gehört wirklich zu dieser Domain." Ausgestellt wird es von einer Zertifizierungsstelle. Die gemeinnützige Stelle Let's Encrypt stellt solche Zertifikate kostenlos aus; sie sind allerdings nur 90 Tage gültig und müssen darum automatisch erneuert werden.
Das Werkzeug, das Zertifikate bei Let's Encrypt beantragt, einbaut und rechtzeitig erneuert, heißt Certbot. Ausnahme ist Caddy: Es bringt diese Aufgabe schon mit.
Voraussetzung: die Domain zeigt auf den Server
Bevor ein Zertifikat beantragt werden kann, muss die Domain (z. B. meine-domain.de) beim DNS-Anbieter auf die IP-Adresse des Servers zeigen – über einen sogenannten A-Record für IPv4 und, falls vorhanden, einen AAAA-Record für IPv6. Let's Encrypt prüft bei der Ausstellung, ob die Domain tatsächlich zu diesem Server führt.
Certbot installieren
Die Certbot-Entwickler empfehlen die Installation über das Paketformat Snap, weil diese Fassung immer aktuell bleibt:
sudo apt install snapd
sudo snap install core
sudo snap install --classic certbot
# Certbot als normalen Befehl "certbot" verfügbar machen
sudo ln -s /snap/bin/certbot /usr/bin/certbot
NGINX und Apache: Zertifikat in einem Schritt
Für den Normalfall – eine feste Domain, deren A-Record auf den Server zeigt – erledigt Certbot alles allein. Es beantragt das Zertifikat, trägt es in die Serverkonfiguration ein und richtet die Umleitung von http:// auf https:// ein:
# Für NGINX
sudo certbot --nginx -d meine-domain.de -d www.meine-domain.de
# Für Apache
sudo certbot --apache -d meine-domain.de -d www.meine-domain.de
Beim ersten Aufruf fragt Certbot nach einer E-Mail-Adresse für Ablaufwarnungen und nach der Zustimmung zu den Nutzungsbedingungen. Die automatische Erneuerung richtet Snap im Hintergrund selbst ein; sudo certbot renew --dry-run prüft, ob sie funktioniert.
Wildcard-Zertifikat über einen DNS-Eintrag
Soll ein Zertifikat für alle Unterdomains auf einmal gelten (*.meine-domain.de), reicht der einfache Weg nicht. Let's Encrypt verlangt dann einen Nachweis über einen DNS-Eintrag. Dieser Weg funktioniert für jeden Webserver gleich, weil er das Zertifikat nur beschafft (certonly) und nicht selbst einbaut:
sudo certbot certonly --manual --preferred-challenges dns \
-d '*.meine-domain.de' -d meine-domain.de
Certbot zeigt daraufhin eine zufällige Zeichenkette an und wartet. Diese Zeichenkette wird beim DNS-Anbieter als Eintrag hinterlegt:
- Beim DNS-Anbieter anmelden und die Verwaltungsoberfläche für die Domain öffnen.
- Den Bereich für DNS-Einträge suchen und einen neuen Eintrag anlegen:
- Typ: TXT
- Name/Host:
_acme-challenge(manche Oberflächen erwarten den vollständigen Namen_acme-challenge.meine-domain.de) - Wert: die von Certbot angezeigte Zeichenkette
- Den Eintrag speichern. Die Änderung braucht einige Minuten, bis sie weltweit sichtbar ist. Ob sie schon greift, lässt sich mit dem Befehl
digoder auf einer Prüfseite wie whatsmydns.net kontrollieren. - Erst dann bei Certbot die Eingabetaste drücken.
| Name/Host | Typ | Wert |
|---|---|---|
_acme-challenge.meine-domain.de | TXT | (zufällige Zeichenkette von Certbot) |
Hinweis: Jeder neue Antrag erzeugt eine neue Zeichenkette. Der TXT-Eintrag muss bei jeder Verlängerung von Hand angepasst werden – oder man verwendet ein Certbot-Zusatzmodul, das den Eintrag über die Schnittstelle des DNS-Anbieters selbst setzt.
Nach erfolgreicher Prüfung legt Certbot die Dateien ab und nennt die Pfade, zum Beispiel:
Certificate is saved at: /etc/letsencrypt/live/meine-domain.de/fullchain.pem
Key is saved at: /etc/letsencrypt/live/meine-domain.de/privkey.pem
fullchain.pem enthält das Zertifikat samt der Zwischenzertifikate, privkey.pem den geheimen Schlüssel. Diese beiden Pfade bleiben auch bei einer Erneuerung gleich: Certbot überschreibt die Dateien, der Ordnername unter /etc/letsencrypt/live/ ändert sich nicht. Deshalb kann man sie fest in die Konfiguration von NGINX oder Apache eintragen.
Caddy: nichts zu tun
Bei Caddy genügt es, im Caddyfile den Domainnamen anzugeben. Beim ersten Start holt Caddy das Zertifikat selbst und erneuert es fortan ohne weiteres Zutun. Ein Wildcard-Zertifikat ist die einzige Ausnahme: Dafür braucht auch Caddy ein Zusatzmodul für den jeweiligen DNS-Anbieter.
Für dieses Buch
Für die beschriebene Wissenssammlung ist NGINX die empfohlene Wahl: Es gibt die meisten Anleitungen – auch die offizielle von MediaWiki –, es verbraucht wenig, und das Zusammenspiel mit PHP-FPM ist gut dokumentiert. Wer die Einrichtung so knapp wie möglich halten will und auf Feinabstimmung verzichten kann, ist mit Caddy gut bedient, allein schon wegen der automatischen Verschlüsselung. Apache ist eine solide Wahl für alle, die damit schon vertraut sind. Pingora kommt für diesen Aufbau nicht in Frage.
Ein Grundsatz gilt für alle: HTTPS ist Pflicht, nicht Kür. Das Zertifikat von Let's Encrypt ist kostenlos, und die Erneuerung läuft nach der Einrichtung von selbst. Wer Docker einsetzt (siehe Containerisierung von Software), sollte zusätzlich beachten, dass Docker die Firewall umgehen kann; dort veröffentlicht man die Programme nur nach innen und stellt den Webserver davor.
Fazit
Ein Webserver nimmt Anfragen aus dem Internet entgegen, liefert feste Dateien selbst aus und reicht alles Übrige an das zuständige Programm weiter – bei MediaWiki an PHP-FPM. NGINX ist für diesen Aufbau die beste Wahl, Caddy die einfachste, Apache die vertraute; Pingora ist ein Programmbaukasten und kein fertiger Server. Auf Ubuntu 26.04 wird NGINX und Apache mit einem einzigen apt-Befehl eingerichtet, Caddy über die Paketquelle des Herstellers. Die verschlüsselte Verbindung besorgt bei NGINX und Apache das Werkzeug Certbot mit einem kostenlosen Zertifikat von Let's Encrypt – für eine feste Domain in einem Schritt, für alle Unterdomains über einen DNS-Eintrag. Caddy erledigt diesen Teil von allein.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Unix-Socket bei NGINX
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Der Webserver NGINX (siehe Webserver) sitzt zwischen dem Internet und den Programmen, die eine Seite erst erzeugen müssen – bei MediaWiki ist das PHP-FPM, bei XWiki der Anwendungsserver Tomcat. An zwei Stellen muss dabei eine Verbindung zustande kommen:
- vorne: Ein Besucher aus dem Internet erreicht NGINX.
- hinten: NGINX erreicht das Programm im Hintergrund und holt sich von dort die fertige Seite.
Beide Verbindungen können über einen Netzwerk-Port laufen oder über eine Socket-Datei – einen sogenannten Unix-Socket. Dieses Kapitel zeigt, wann sich der Unix-Socket lohnt und wie man ihn in der NGINX-Konfiguration einträgt: hinten als Weg zu PHP-FPM oder Tomcat, vorne als eigener Lauschposten und, als dritte Möglichkeit, als dauerhafte Brücke zwischen einem Port und einer Socket-Datei.
Alle Befehle werden in der Textkonsole des Servers eingegeben. Ein vorangestelltes sudo bedeutet: mit Verwaltungsrechten ausführen. Nach jeder Änderung an der Konfiguration prüft sudo nginx -t die Dateien auf Fehler, sudo systemctl reload nginx übernimmt sie.
Was ein Unix-Socket ist
Ein Netzwerk-Port ist der bekannte Weg: Ein Programm lauscht auf einer Nummer wie 9000, ein anderes verbindet sich mit 127.0.0.1:9000. Das funktioniert auch über Rechnergrenzen hinweg.
Ein Unix-Socket ist der zweite Weg. Statt einer Portnummer gibt es eine Datei im Dateisystem, zum Beispiel /run/php/php8.5-fpm.sock. Ein Programm lauscht an dieser Datei, ein anderes verbindet sich mit ihr. Beide müssen dafür auf demselben Rechner laufen. Zwei Eigenschaften machen den Unix-Socket für Server interessant:
- Kein offener Port. Eine Socket-Datei ist grundsätzlich nur auf demselben Rechner erreichbar. Sie kann nicht aus Versehen für das ganze Netz geöffnet werden.
- Zugriff über Dateirechte. Wer die Socket-Datei benutzen darf, regeln dieselben Lese- und Schreibrechte wie bei jeder anderen Datei.
Eine ausführliche Erklärung – auch dazu, wie man eine Socket-Datei zum Testen kurz als Port erreichbar macht – steht im Kapitel Unix-Socket.
Die zwei Verbindungen von NGINX
In der NGINX-Konfiguration tauchen die beiden Verbindungen an unterschiedlichen Stellen auf.
| Stelle | Aufgabe | über einen Port | über einen Unix-Socket |
|---|---|---|---|
listen | wo NGINX auf Besucher wartet | listen 80; | listen unix:/run/nginx-intern.sock; |
fastcgi_pass | Weg zu PHP-FPM | fastcgi_pass 127.0.0.1:9000; | fastcgi_pass unix:/run/php/php8.5-fpm.sock; |
proxy_pass | Weg zu einem anderen Programm (z. B. Tomcat) | proxy_pass http://127.0.0.1:9000/; | proxy_pass http://unix:/var/lib/tomcat10/xwiki.sock:/; |
Der häufigste Fall ist die hintere Verbindung über fastcgi_pass oder proxy_pass. Die vordere Verbindung über listen unix: braucht man selten und nur in besonderen Aufbauten.
Hinten: NGINX erreicht das Hintergrundprogramm über einen Socket
PHP-FPM
PHP-FPM legt seine Socket-Datei bei einer Standardinstallation von selbst an, bei PHP 8.5 unter /run/php/php8.5-fpm.sock. Diese Datei gehört dem Benutzer www-data, und unter genau diesem Benutzer läuft auch NGINX. Der Zugriff ist damit ohne weitere Einstellung möglich. In der Server-Konfiguration steht dann statt einer Adresse der Pfad:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.5-fpm.sock;
}
Das Kapitel MediaWiki einrichten verwendet genau diesen Weg. Ein Port für PHP-FPM wird dabei nirgends geöffnet.
Ein anderes Programm über den Reverse Proxy
Für Programme, die selbst HTTP sprechen – etwa Tomcat hinter XWiki –, benutzt NGINX proxy_pass. Auch hier kann statt der Adresse http://127.0.0.1:9000/ eine Socket-Datei stehen. Die Schreibweise ist etwas ungewohnt: Nach http://unix: folgt der Pfad, dann ein Doppelpunkt und der Pfad innerhalb der Anwendung.
location / {
proxy_pass http://unix:/var/lib/tomcat10/xwiki.sock:/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Anders als bei PHP-FPM gehört diese Socket-Datei nicht www-data, sondern dem Benutzer des jeweiligen Dienstes. Damit NGINX sie benutzen darf, wird www-data in dessen Gruppe aufgenommen – im XWiki-Beispiel ist das die Gruppe tomcat:
sudo usermod -aG tomcat www-data
sudo systemctl restart tomcat10 nginx
Der genaue Weg für XWiki steht im Kapitel XWiki einrichten.
Warum überhaupt ein Socket hinten?
Der Geschwindigkeitsunterschied zwischen Port und Socket ist auf einem einzelnen Server winzig und im Alltag nicht zu bemerken. Der eigentliche Gewinn liegt woanders:
- Es wird kein Port belegt, der versehentlich nach außen geöffnet werden könnte. Man muss ihn auch nicht in der Firewall ausdrücklich sperren.
- Der Zugriff hängt an Dateirechten. Nur wer in der richtigen Gruppe ist, kommt an den Dienst.
Für einen Aufbau, bei dem Webserver und Hintergrundprogramm ohnehin auf demselben Rechner liegen, ist der Unix-Socket deshalb die sauberere Wahl.
Vorne: NGINX wartet an einem Socket auf Besucher
Statt listen 80; kann ein NGINX-Server auch an einer Socket-Datei lauschen:
server {
listen unix:/run/nginx-intern.sock;
# ...
}
Das ergibt nur Sinn, wenn vor diesem NGINX noch etwas anderes steht, das die Anfragen über die Socket-Datei hereinreicht – zum Beispiel ein zweiter NGINX, ein Zwischenspeicher oder ein Anwendungsserver auf demselben Rechner. Für den normalen Betrieb, bei dem NGINX direkt die Verbindungen aus dem Internet annimmt, bleibt es bei listen 80; und listen 443 ssl;, denn aus dem Netz ist eine Socket-Datei nicht erreichbar.
Die dauerhafte Brücke: der stream-Baustein
Manchmal soll ein Werkzeug, das nur Ports kennt, dauerhaft an eine Socket-Datei kommen – oder umgekehrt. Für einen kurzen Test erledigt das der Befehl socat (siehe Unix-Socket). Läuft NGINX auf dem Server ohnehin, kann es diese Brücke dauerhaft übernehmen. Zuständig ist der stream-Baustein. Er arbeitet nicht mit HTTP-Seiten, sondern reicht rohe Verbindungen unverändert weiter.
Der stream-Block steht auf der obersten Ebene der Datei /etc/nginx/nginx.conf, außerhalb des http-Blocks:
stream {
server {
listen 127.0.0.1:9000;
proxy_pass unix:/var/lib/tomcat10/xwiki.sock;
}
}
Solange NGINX läuft, nimmt es auf Port 9000 – nur auf dem Rechner selbst, wegen 127.0.0.1 – Verbindungen an und leitet sie an die Socket-Datei weiter. Die umgekehrte Richtung geht genauso: listen unix:/run/meine.sock; und proxy_pass 127.0.0.1:9000;.
Der stream-Baustein gehört bei Ubuntu zum Standardpaket nginx und muss nicht nachinstalliert werden. Anders als ein socat-Befehl im Terminal übersteht diese Brücke einen Neustart des Servers.
Fehlersuche
Wenn NGINX das Hintergrundprogramm nicht erreicht, meldet der Browser 502 Bad Gateway. Den genauen Grund nennt das Fehlerprotokoll:
sudo tail -n 20 /var/log/nginx/error.log
connect() to unix:/… failed (13: Permission denied): Der Benutzerwww-datadarf die Socket-Datei nicht benutzen. Die Rechte zeigtls -l /run/php/php8.5-fpm.sock(bzw. der jeweilige Pfad). Meist fehltwww-datain der richtigen Gruppe; nachsudo usermod -aG <gruppe> www-datamuss NGINX neu gestartet werden (sudo systemctl restart nginx), ein bloßesreloadreicht für die neue Gruppenzugehörigkeit nicht.connect() to unix:/… failed (2: No such file or directory): Der Pfad stimmt nicht, oder der Dienst läuft nicht und hat die Socket-Datei deshalb nicht angelegt. Prüfen mitsystemctl status php8.5-fpmbzw.systemctl status tomcat10.invalid URL prefix in …beimnginx -t: Beiproxy_passauf einen Socket fehlt dashttp://unix:am Anfang oder der Doppelpunkt vor dem Pfad innerhalb der Anwendung.unknown directive "stream": Derstream-Block wurde in eine Server-Datei untersites-available/geschrieben. Er gehört auf die oberste Ebene von/etc/nginx/nginx.conf.
Für dieses Buch
Für die Wissenssammlung dieses Buchs erreicht NGINX PHP-FPM über dessen Socket-Datei /run/php/php8.5-fpm.sock – das ist die Standardeinstellung und braucht keine weitere Anpassung (siehe MediaWiki einrichten). Wer XWiki betreibt, kann Tomcat auf dieselbe Weise über einen Unix-Socket ansprechen und spart sich damit den offenen Port 9000 (siehe XWiki einrichten).
Die vordere Seite bleibt bei Ports: listen 80; und listen 443 ssl;. Der stream-Baustein ist nur dann nötig, wenn eine Socket-Datei auf dem Server dauerhaft auch als Port bereitstehen soll; für den einmaligen Test genügt socat.
Fazit
NGINX verbindet sich an zwei Stellen: vorne mit dem Besucher, hinten mit dem Programm, das die Seite erzeugt. Die hintere Verbindung läuft am besten über einen Unix-Socket – bei PHP-FPM mit fastcgi_pass unix:/run/php/php8.5-fpm.sock;, bei einem HTTP-Programm mit proxy_pass http://unix:/pfad/zur.sock:/;. Der Vorteil ist nicht die Geschwindigkeit, sondern dass kein Port offensteht und der Zugriff an Dateirechten hängt; deshalb muss www-data oft in die Gruppe des Dienstes aufgenommen werden. Die vordere Verbindung bleibt bei Ports. Soll eine Socket-Datei dauerhaft als Port erreichbar sein, übernimmt der stream-Baustein von NGINX diese Brücke – zuverlässiger als ein socat-Befehl im Terminal.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Webframework
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Die Wissenssammlung dieses Buchs läuft auf MediaWiki. MediaWiki ist eine fertige Anwendung: Man muss sie nur einrichten, nicht programmieren. Sobald aber ein eigenes Zusatzprogramm dazukommen soll – eine Schnittstelle, über die andere Programme die Inhalte abrufen, ein Werkzeug, das Texte aus einer alten Datenbank einliest, oder eine kleine Weboberfläche für eine Aufgabe, die MediaWiki nicht abdeckt –, schreibt man dieses Programm selbst. Dann stellt sich die Frage nach dem Webframework.
Dieses Kapitel erklärt, was ein Webframework ist, worin es sich von einer fertigen Anwendung wie MediaWiki unterscheidet, und stellt die Frameworks vor, die als besonders ausgereift und belastbar gelten – also solche, die auch mit sehr vielen Inhalten und über viele Jahre zuverlässig laufen. Es geht dabei nicht um die Einrichtung Schritt für Schritt, denn welches Framework überhaupt in Frage kommt, hängt vom geplanten Zusatzprogramm ab. Das Kapitel liefert die Grundlage für diese Wahl.
Was ein Webframework ist
Wer ein Haus baut, gießt nicht jeden Ziegel selbst und erfindet auch nicht die Statik neu. Es gibt Normmaße, fertige Träger, geprüfte Bauteile. Ein Webframework ist dieser Satz geprüfter Bauteile für Webprogramme. Es nimmt einem die immer gleichen Grundaufgaben ab, die jedes Webprogramm hat:
- Anfragen verstehen. Aus der rohen Anfrage des Browsers die wichtigen Angaben herauslesen – welche Adresse, welche Formulardaten, welcher angemeldete Benutzer.
- Die richtige Funktion aufrufen. Anhand der Adresse entscheiden, welcher Teil des eigenen Codes zuständig ist. Das nennt man Routing.
- Mit der Datenbank reden. Inhalte aus der Datenbank holen und speichern, ohne dass man die Datenbanksprache SQL von Hand zusammensetzen muss. Der Vermittler dafür heißt ORM (englisch für „objektrelationale Abbildung").
- Antworten erzeugen. Aus den Daten eine fertige HTML-Seite oder eine Antwort im JSON-Format bauen.
- Vor Angriffen schützen. Eingaben prüfen, Passwörter sicher speichern, gängige Angriffsmuster von vornherein abwehren.
Ein Framework ist also kein fertiges Programm, sondern ein Gerüst, in das man den eigenen Code einhängt. Es gibt die Struktur vor; die Fachlogik – was das Programm konkret tun soll – schreibt man selbst.
Framework, Anwendung, Content-Management-System
Drei Begriffe werden leicht verwechselt:
- Eine Anwendung wie MediaWiki ist fertig. Man installiert sie und füllt sie mit Inhalten.
- Ein Content-Management-System (CMS) wie WordPress, Drupal oder TYPO3 ist ebenfalls eine fertige Anwendung, aber eine, die stark auf das Verwalten von Seiteninhalten zugeschnitten und über Erweiterungen anpassbar ist. Für ein Wissensportal ist ein CMS oft schon die ganze Lösung.
- Ein Framework ist der Rohbau darunter. MediaWiki, WordPress und Drupal bringen ihren eigenen Unterbau mit; andere Anwendungen sind sichtbar auf einem bekannten Framework gebaut.
Wer nur eine Wissenssammlung betreiben will, bleibt bei der fertigen Anwendung. Das Framework wird erst zum Thema, wenn ein Zusatzprogramm entsteht, für das es nichts Fertiges gibt.
Was „robust" bei einem Framework bedeutet
Die Frage „Welches Framework hält auch eine Million Einträge aus, ohne kaputtzugehen?" lässt sich nicht am Framework allein beantworten. Drei Dinge spielen zusammen:
- Die Datenbank trägt die Last, nicht das Framework. Eine Million Texteinträge sind für eine ausgewachsene Datenbank wie PostgreSQL (siehe Inhalts-Software selbst betreiben) eine normale Größe. Ob das schnell bleibt, entscheidet sich an den Datenbank-Indizes und an der Frage, ob das Programm immer nur die gerade benötigten Einträge lädt – niemals alle auf einmal.
- Das Framework muss sparsam mit Daten umgehen. Ein gutes Framework holt Einträge seitenweise (Pagination), liefert große Mengen häppchenweise aus (Streaming) und lädt verknüpfte Daten gebündelt statt in tausend Einzelabfragen. Ob das passiert, liegt aber am Code, den man selbst schreibt – das Framework macht es nur möglich und bequem.
- Reifegrad heißt: Es bricht nicht bei der nächsten Aktualisierung. Ein ausgereiftes Framework hat einen festen Veröffentlichungsplan, eine Ausgabe mit langer Pflegezusage (LTS), eine klare Vorgehensweise beim Umstieg auf neue Versionen und eine große Gemeinschaft, die Fehler früh findet. Das ist der Unterschied zwischen einem Framework, auf das man einen Server für zehn Jahre stellt, und einem, das nach zwei Jahren nicht mehr gepflegt wird.
Verschiedene Inhaltstypen und Datensätze – Artikel, Bilder, Kategorien, Verweise, Nutzerkonten – verwaltet man über das Datenmodell. Jedes hier genannte Framework kann beliebig viele solcher Typen abbilden; die Arbeit steckt im sauberen Entwurf des Modells, nicht in der Wahl des Frameworks.
Ausgereifte Frameworks im Überblick
Die folgenden Frameworks gelten als besonders belastbar: Sie sind seit vielen Jahren im Einsatz, werden von großen Auftritten verwendet, haben einen verlässlichen Pflegeplan und eine breite Gemeinschaft. Sie sind nach der Programmiersprache geordnet; die passende Laufzeitumgebung dazu beschreibt das Kapitel Laufzeitumgebung.
Django und FastAPI (Python)
Django ist das Rundum-sorglos-Framework für Python. Es bringt ORM, Nutzerverwaltung, Sicherheitsfunktionen und eine fertige Verwaltungsoberfläche für die eigenen Daten von Haus aus mit. Genau diese eingebaute Verwaltungsoberfläche macht Django stark, wenn viele verschiedene Inhaltstypen zu pflegen sind: Man beschreibt das Datenmodell einmal und bekommt die Eingabemasken dazu geschenkt. Django gibt es seit 2005, es hat einen festen Veröffentlichungsplan mit LTS-Ausgaben und wird von sehr großen Auftritten eingesetzt.
FastAPI ist der modernere, schlankere Gegenentwurf – kein Rundum-Paket, sondern spezialisiert auf Schnittstellen im JSON-Format. Es ist schnell, erzeugt automatisch eine Beschreibung der eigenen Schnittstelle und eignet sich gut, wenn das Zusatzprogramm nur Daten bereitstellen und keine Webseiten anzeigen soll.
Laravel und Symfony (PHP)
Da MediaWiki in PHP geschrieben ist, liegt ein PHP-Framework für Zusatzprogramme nahe: Die Laufzeitumgebung ist ohnehin schon auf dem Server.
Laravel ist das meistgenutzte moderne PHP-Framework. Es gilt als angenehm zu bedienen, bringt viele fertige Bausteine mit (Warteschlangen für Hintergrundaufgaben, Zwischenspeicher, Nutzerverwaltung) und hat eine sehr große Gemeinschaft. Symfony ist der Baukasten darunter: eine Sammlung einzeln nutzbarer, sehr sorgfältig gepflegter Bauteile, aus denen unter anderem auch Teile von Laravel und dem CMS Drupal bestehen. Symfony hat einen besonders strengen Veröffentlichungsplan mit LTS-Ausgaben, die mehrere Jahre Unterstützung erhalten.
Ruby on Rails (Ruby)
Rails hat vieles von dem geprägt, was heute an allen Frameworks selbstverständlich ist. Es ist seit 2004 im Einsatz, sehr ausgereift und darauf ausgelegt, dass ein kleines Team schnell viel erreicht. Große, seit Jahren wachsende Auftritte laufen auf Rails. Wer keine Ruby-Kenntnisse im Umfeld hat, wählt es aber selten neu.
Spring Boot (Java)
Spring Boot ist der Standard für Java im Unternehmensumfeld. Es ist auf Langlebigkeit, Stabilität und die Anbindung an andere Unternehmenssysteme ausgelegt. Der Preis dafür ist ein höherer Einstiegsaufwand und mehr Verbrauch an Arbeitsspeicher als bei den schlankeren Frameworks. Für ein kleines Zusatzprogramm neben einer Wissenssammlung ist Spring Boot meist überdimensioniert; seine Stärke spielt es aus, wenn viele Dienste über Jahre zusammenwachsen.
ASP.NET Core (C#)
ASP.NET Core ist das Web-Framework von Microsoft, seit einigen Jahren quelloffen und auch auf Linux zu Hause. Es ist ausgereift, gut dokumentiert und in Vergleichsmessungen regelmäßig unter den schnellsten der weit verbreiteten Frameworks. Die passende Laufzeit lässt sich auf Ubuntu direkt aus den Paketquellen einrichten.
Express und NestJS (JavaScript, Node.js)
Express ist ein sehr kleines, seit vielen Jahren bewährtes Framework für Node.js – es kümmert sich fast nur um das Routing und überlässt den Rest Zusatzbausteinen. NestJS legt eine feste Struktur darüber und ähnelt damit eher den Rundum-Frameworks. Node.js ist ohnehin auf dem Server, wenn dort ein KI-Agent mit n8n läuft (siehe KI-Agenten auf dem Server).
Gin und Echo (Go)
Frameworks in der Sprache Go werden vor der Auslieferung zu einer einzelnen, eigenständigen Datei übersetzt, die ohne separate Laufzeitumgebung startet. Gin und Echo sind schlanke, schnelle Frameworks für Schnittstellen. Sie sind ausgereift, brauchen wenig Arbeitsspeicher und eignen sich gut für einen kleinen, dauerhaft laufenden Zusatzdienst.
Actix Web und Axum (Rust)
In der Sprache Rust geschriebene Frameworks wie Actix Web und Axum stehen in Vergleichsmessungen regelmäßig an der Spitze. Rust ist dafür bekannt, ganze Klassen von Programmierfehlern schon beim Übersetzen zu verhindern. Der Einstieg ist allerdings anspruchsvoll, und für die meisten Zusatzprogramme neben einer Wissenssammlung ist die Höchstgeschwindigkeit gar nicht der Engpass.
Zur Geschwindigkeit: Was Benchmarks sagen – und was nicht
Es gibt einen bekannten, offen einsehbaren Vergleich, die TechEmpower-Benchmarks. Dabei werden Hunderte Frameworks unter gleichen Bedingungen gemessen: einfache Antworten, Datenbankabfragen, das Zusammensetzen einer HTML-Seite. Die jüngste Runde (Runde 23, Februar 2025) zeigt das übliche Bild:
| Framework (Sprache) | Einordnung im Vergleich |
|---|---|
| Actix Web, Axum (Rust) | ganz oben |
| ASP.NET Core (C#) | sehr weit oben unter den verbreiteten Frameworks |
| Gin, Echo (Go) | weit oben |
| Spring Boot (Java) | oberes Mittelfeld |
| Express, NestJS (Node.js) | Mittelfeld |
| Rails (Ruby), Django (Python) | unteres Mittelfeld |
| Laravel (PHP) | unteres Mittelfeld |
Diese Reihenfolge sagt weniger aus, als es zunächst scheint. Zwei Punkte sind wichtig:
- Die Messung testet den Leerlauf des Frameworks. In einem echten Programm liegt die Wartezeit fast immer woanders: bei der Datenbank, beim Suchdienst, bei einer Anfrage an ein anderes Programm. Ein Framework, das im Test doppelt so schnell ist, macht das Gesamtprogramm selten spürbar schneller.
- Ein Zwischenspeicher hebt jedes Framework auf ein anderes Niveau. Wird eine fertige Antwort für kurze Zeit vorgehalten (etwa mit Redis oder direkt im Webserver), fällt das Framework als Zeitfaktor praktisch heraus.
Als grobe Regel gilt: Solange ein Zusatzprogramm nicht Tausende Anfragen pro Sekunde beantworten muss, ist die Framework-Geschwindigkeit nachrangig. Wichtiger sind eine gute Datenbankgestaltung, sinnvolle Indizes und ein Zwischenspeicher.
Direkt auf dem Server oder im Container
Ein selbst geschriebenes Programm mit Webframework lässt sich auf zwei Wegen betreiben:
- Direkt auf dem Server („bare metal", also ohne Zwischenschicht): Man richtet die Laufzeitumgebung ein, legt das Programm ab und startet es als Hintergrunddienst über
systemd. Davor sitzt der Webserver als Reverse Proxy (siehe Webserver). Dieser Weg hat die wenigsten beweglichen Teile. - Im Container (siehe Containerisierung von Software): Das Programm wird mit seiner Laufzeitumgebung in ein Abbild gepackt. Das erleichtert den Umzug auf einen anderen Server und das Nebeneinander von Test- und Betriebsfassung.
Für ein einzelnes kleines Zusatzprogramm ist der direkte Weg meist der einfachere. Sobald mehrere solche Programme zusammenkommen, wird der Container attraktiver.
Für dieses Buch
Für die beschriebene Wissenssammlung wird kein Webframework benötigt: MediaWiki, PostgreSQL, der Suchdienst und der KI-Agent decken alles ab. Ein Framework kommt erst ins Spiel, wenn ein eigenes Zusatzprogramm entsteht.
Für diesen Fall bieten sich zwei Wege an:
- Bleibt man bei PHP, weil die Laufzeitumgebung wegen MediaWiki ohnehin da ist, sind Laravel (bequem, große Gemeinschaft) oder Symfony (sehr sorgfältig gepflegt) die naheliegenden Frameworks.
- Geht es vor allem um eine Datenschnittstelle, ist FastAPI (Python) oder Gin (Go) schlank und schnell eingerichtet. Läuft ohnehin schon Node.js für den KI-Agenten, ist Express eine gute Wahl.
Django lohnt sich, wenn das Zusatzprogramm selbst viele eigene Inhaltstypen verwalten soll – die eingebaute Verwaltungsoberfläche spart dann viel Arbeit. Spring Boot, ASP.NET Core und die Rust-Frameworks sind für ein kleines Zusatzprogramm überdimensioniert; sie sind die richtige Wahl in größeren, über Jahre wachsenden Systemen.
Fazit
Ein Webframework ist der geprüfte Rohbau für ein selbst geschriebenes Webprogramm; es nimmt Routing, Datenbankzugriff, Antworterzeugung und Grundschutz ab. Für eine reine Wissenssammlung mit MediaWiki braucht man keines. Wird ein Zusatzprogramm nötig, gelten Django und FastAPI (Python), Laravel und Symfony (PHP), Ruby on Rails, Spring Boot (Java), ASP.NET Core (C#), Express und NestJS (Node.js), Gin und Echo (Go) sowie Actix Web und Axum (Rust) als besonders ausgereift. Ob ein Framework „eine Million Einträge aushält", entscheidet sich nicht am Framework, sondern an der Datenbank, an sauberem Datenzugriff und an einem Zwischenspeicher. Geschwindigkeits-Benchmarks messen den Leerlauf des Frameworks und sagen für den Alltag wenig aus. Für dieses Buch gilt: bei PHP bleiben, wenn nur ein kleines Zusatzprogramm gebraucht wird, und das Programm direkt auf dem Server hinter dem Webserver betreiben.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Postfix
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
MediaWiki – die Grundlage der Wissenssammlung dieses Buchs – und Drupal, ein weiteres Inhaltssystem, das auf demselben Server laufen kann, verschicken an vielen Stellen E-Mails: Ein neues Benutzerkonto bekommt einen Bestätigungslink, ein vergessenes Passwort einen Link zum Zurücksetzen, eine beobachtete Seite eine Änderungsmeldung. Damit diese Nachrichten den Server verlassen, fehlt ein Programm, das sie annimmt und an den Mailanbieter des Empfängers zustellt. Dieses Programm heißt Mail Transfer Agent (MTA). Der auf Linux mit Abstand verbreitetste ist Postfix.
Das Schwierige ist nicht die Installation – die ist ein einziger Befehl. Das Schwierige ist, dass große Anbieter wie Gmail (Google Mail) sehr genau prüfen, welche Post sie annehmen. Ein Server, der einfach „irgendwie" sendet, landet im Spam oder wird ganz abgewiesen. Dieses Kapitel zeigt Schritt für Schritt, wie man Postfix auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) so einrichtet, dass eine Gmail-Adresse die Post im Posteingang annimmt: mit verschlüsselten Verbindungen und einem Zertifikat von Certbot (siehe Webserver) sowie den drei DNS-Einträgen SPF, DKIM und DMARC.
Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen. Platzhalter wie meine-domain.de und die Beispiel-IP 203.0.113.10 müssen überall durch die eigenen Werte ersetzt werden.
Was Postfix macht
Man kann sich Postfix wie die Poststelle einer Firma vorstellen. Mitarbeiter (die Programme auf dem Server) legen ihre fertigen Briefe in ein Fach. Die Poststelle nimmt sie heraus, schaut auf die Anschrift, sucht den richtigen Zustellweg und übergibt den Brief nach draußen. Um die Zustellung im Haus kümmert sie sich getrennt davon.
Postfix kann in zwei Betriebsarten laufen:
- Nur senden. Postfix nimmt Post ausschließlich von Programmen auf demselben Server an und leitet sie nach außen weiter. Es gibt keine Postfächer, und von außen ist nichts erreichbar. Genau das brauchen MediaWiki und Drupal – und genau das richtet dieses Kapitel ein.
- Vollständiger Mailserver. Zusätzlich nimmt Postfix Post aus dem Internet an, legt sie in Postfächern ab, macht sie über IMAP abrufbar (mit dem Zusatzprogramm Dovecot), filtert Spam und so weiter. Das ist deutlich aufwendiger, ein eigenes Thema und hier nicht nötig.
Warum Gmail so wählerisch ist
Der Grund ist Spam. Bei jeder eingehenden Nachricht prüft Gmail unter anderem:
- Rückwärtsauflösung (PTR). Hat die IP-Adresse des sendenden Servers einen Namen, und zeigt dieser Name auf dieselbe IP zurück? Post von IPs ohne passenden PTR-Eintrag wird fast immer abgewiesen.
- SPF. Darf dieser Server überhaupt Post für diese Domain verschicken? Das legt ein DNS-Eintrag fest.
- DKIM. Ist die Nachricht digital unterschrieben, und passt die Unterschrift zu einem Schlüssel, der im DNS veröffentlicht ist? Das beweist, dass die Nachricht unterwegs nicht verändert wurde und wirklich von der Domain stammt.
- DMARC. Ein DNS-Eintrag, der dem Empfänger sagt, was er tun soll, wenn SPF oder DKIM nicht passen – und der Berichte anfordert.
- Verschlüsselung (TLS). Wird die Verbindung zwischen den Servern verschlüsselt?
- Ruf der IP-Adresse. Kam von dieser IP schon einmal Spam?
Seit Februar 2024 verlangt Gmail auch von kleinen Absendern mindestens SPF oder DKIM; bei größeren Mengen SPF und DKIM und DMARC. Am einfachsten richtet man von Anfang an alles ein.
Voraussetzungen
-
Eine eigene Domain mit Zugang zu den DNS-Einträgen (meist beim Anbieter, bei dem die Domain registriert ist).
-
Ein Server mit fester öffentlicher IPv4-Adresse – ein gewöhnlicher gemieteter Server genügt (siehe Server mieten).
-
Ausgehender Port 25 offen. Viele Anbieter sperren Port 25 zunächst, um Spam zu verhindern. Prüfen:
nc -zv gmail-smtp-in.l.google.com 25Bleibt der Befehl hängen oder meldet „timed out", muss man den Anbieter über den Support bitten, Port 25 freizuschalten. Ohne offenen Port 25 verlässt keine einzige Nachricht den Server.
-
Die Möglichkeit, den PTR-Eintrag für die Server-IP zu setzen – meist im Kundenbereich des Anbieters unter „Reverse DNS", „rDNS" oder „PTR".
-
Eine frische IP ohne schlechte Vorgeschichte hilft. Prüfen lässt sich das unter
check.spamhaus.org.
Schritt 1: Den Hostnamen des Servers festlegen
Der Server braucht einen vollständigen Namen, mit dem er sich bei anderen Mailservern meldet. Üblich ist mail.meine-domain.de.
sudo hostnamectl set-hostname mail.meine-domain.de
Danach die Datei /etc/hosts ergänzen, damit der Name auch lokal auflösbar ist. Eine Zeile hinzufügen:
203.0.113.10 mail.meine-domain.de mail
Kontrolle:
hostname --fqdn
# muss mail.meine-domain.de ausgeben
Schritt 2: DNS-Einträge für den Mailnamen
Beim DNS-Anbieter für die Domain anlegen:
| Name/Host | Typ | Wert |
|---|---|---|
mail | A | 203.0.113.10 |
@ (die Domain selbst) | MX | 10 mail.meine-domain.de. |
Der A-Eintrag lässt mail.meine-domain.de auf den Server zeigen. Der MX-Eintrag legt fest, welcher Server für Post an @meine-domain.de zuständig ist. Das ist nötig, damit Antworten und DMARC-Berichte irgendwo ankommen.
Da dieser Aufbau nur sendet und keine Post empfängt, sollte der MX-Eintrag auf ein vorhandenes Postfach zeigen – zum Beispiel das Postfach, das beim Domain-Anbieter mitgeliefert wird, oder ein anderes Mailkonto. Dorthin gehen dann Antworten und Berichte. Wer die Domain-Post selbst auf dem Server empfangen will, braucht den vollständigen Mailserver aus dem Abschnitt oben – ein eigenes Thema.
Schritt 3: Rückwärtsauflösung (PTR) setzen
Im Kundenbereich des Server-Anbieters die Rückwärtsauflösung für 203.0.113.10 auf mail.meine-domain.de einstellen. Prüfen:
dig +short -x 203.0.113.10
# muss mail.meine-domain.de. ausgeben
Die Änderung kann einige Zeit dauern. Ein fehlender oder falscher PTR-Eintrag ist der häufigste Grund, warum Gmail Post abweist – diesen Schritt also nicht überspringen.
Schritt 4: Postfix installieren
sudo apt update
sudo apt install postfix
Es erscheint ein blauer Einrichtungsdialog:
- General type of mail configuration: Internet Site auswählen.
- System mail name: meine-domain.de eintragen (ohne
mail.davor). Das ist die Domain, die hinter dem@in der Absenderadresse lokaler Post steht.
Erscheint der Dialog nicht oder wurde etwas falsch gewählt, holt man ihn mit sudo dpkg-reconfigure postfix zurück.
Dann noch ein Hilfsprogramm für Testnachrichten installieren:
sudo apt install mailutils
mailutils stellt den Befehl mail bereit, mit dem man später eine Testmail verschickt.
Schritt 5: Postfix als reinen Sendedienst einrichten
Die Haupteinstellungen stehen in /etc/postfix/main.cf. Statt die Datei von Hand zu öffnen, setzt man die Werte mit dem Befehl postconf -e – das vermeidet Tippfehler:
sudo postconf -e 'myhostname = mail.meine-domain.de'
sudo postconf -e 'myorigin = /etc/mailname'
sudo postconf -e 'mydestination = localhost'
sudo postconf -e 'inet_interfaces = loopback-only'
sudo postconf -e 'inet_protocols = ipv4'
Was die einzelnen Zeilen bedeuten:
myhostname– der vollständige Name, mit dem Postfix sich meldet.myorigin = /etc/mailname– die Datei/etc/mailnameenthält nach der Installation bereitsmeine-domain.de. Absenderadressen ohne Domain (etwawww-data) bekommen diesen Teil angehängt.mydestination = localhost– Postfix betrachtet nurlocalhostals „für mich bestimmt"; alles andere wird nach außen weitergeleitet.inet_interfaces = loopback-only– Postfix lauscht nur auf dem Server selbst (127.0.0.1), nie im Internet. Kein Fremder kann ihm Post übergeben. Damit ist ein Missbrauch als Spam-Verteiler ausgeschlossen.inet_protocols = ipv4– gesendet wird über IPv4. Nur wenn der Server eine funktionierende IPv6-Adresse mit passendem PTR-Eintrag hat, kann man hierallsetzen. Ein fehlender IPv6-PTR führt zu Abweisungen durch Gmail, deshalb ist IPv4 die sichere Voreinstellung.
Kurz prüfen, dass die Datei mit dem Mailnamen stimmt:
cat /etc/mailname
# meine-domain.de
Danach Postfix neu starten:
sudo systemctl restart postfix
Schritt 6: Absenderadressen sauber umschreiben
MediaWiki und Drupal setzen ihre Absenderadresse meist selbst sinnvoll. Systemnachrichten aber – etwa von zeitgesteuerten Aufgaben oder Fehlermeldungen – kommen von Adressen wie root@mail.meine-domain.de oder www-data@mail.meine-domain.de. Gmail mag Absender nicht, die es gar nicht gibt. Zwei Handgriffe helfen.
Weiterleitung für root. In /etc/aliases eine Zeile ergänzen:
root: postmaster@meine-domain.de
Danach:
sudo newaliases
Adressen beim Versand umschreiben. Eine neue Datei /etc/postfix/generic anlegen:
root@mail.meine-domain.de postmaster@meine-domain.de
www-data@mail.meine-domain.de noreply@meine-domain.de
@mail.meine-domain.de noreply@meine-domain.de
Dann in ein von Postfix lesbares Format übersetzen und aktivieren:
sudo postmap /etc/postfix/generic
sudo postconf -e 'smtp_generic_maps = hash:/etc/postfix/generic'
sudo systemctl restart postfix
smtp_generic_maps schreibt Adressen nur auf dem Weg nach draußen um. So trägt jede Nachricht, die den Server verlässt, eine echte Adresse an der eigenen Domain. Die Adressen postmaster@meine-domain.de und noreply@meine-domain.de müssen bei dem in Schritt 2 gewählten Postfach tatsächlich existieren (postmaster wird ohnehin erwartet; noreply kann ein Sammelpostfach sein).
Schritt 7: Verbindungen zu anderen Mailservern verschlüsseln
Beim Senden verschlüsselt Postfix in aktuellen Versionen bereits von sich aus, wann immer die Gegenseite es anbietet. Man setzt es trotzdem ausdrücklich:
sudo postconf -e 'smtp_tls_security_level = may'
sudo postconf -e 'smtp_tls_loglevel = 1'
may bedeutet: verschlüsseln, sobald die Gegenseite es kann – Gmail kann es immer. Ein eigenes Zertifikat braucht der Server dafür nicht, denn er stellt beim Senden keinen Ausweis vor.
Ein eigenes Zertifikat wird erst wichtig, sobald andere Server oder Mailprogramme sich mit dem Server verbinden – also wenn man später Post empfangen oder den Versand für entfernte Programme öffnen will. Wer das vorbereiten möchte, holt sich jetzt ein Zertifikat mit Certbot (Einrichtung siehe Webserver):
sudo certbot certonly --nginx -d mail.meine-domain.de
Danach in Postfix eintragen:
sudo postconf -e 'smtpd_tls_cert_file = /etc/letsencrypt/live/mail.meine-domain.de/fullchain.pem'
sudo postconf -e 'smtpd_tls_key_file = /etc/letsencrypt/live/mail.meine-domain.de/privkey.pem'
sudo postconf -e 'smtpd_tls_security_level = may'
Damit Postfix ein erneuertes Zertifikat übernimmt, legt man einen kleinen Haken für Certbot an. Datei /etc/letsencrypt/renewal-hooks/deploy/postfix-neuladen.sh:
#!/bin/sh
systemctl reload postfix
Ausführbar machen:
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/postfix-neuladen.sh
Schritt 8: SPF-Eintrag im DNS
Ein TXT-Eintrag an der Wurzel der Domain:
| Name/Host | Typ | Wert |
|---|---|---|
@ (die Domain selbst) | TXT | v=spf1 mx a ip4:203.0.113.10 -all |
Das bedeutet: Post für diese Domain darf von den MX-Servern, vom A-Server und von dieser IP kommen; alles andere (-all) soll abgewiesen werden. Wer sich zu Beginn unsicher ist, nimmt statt -all zunächst ~all (nur Verdacht statt Abweisung) und stellt nach erfolgreichen Tests auf -all um.
Es darf nur einen SPF-Eintrag pro Domain geben. Prüfen:
dig +short TXT meine-domain.de
Schritt 9: DKIM mit OpenDKIM einrichten
DKIM unterschreibt jede ausgehende Nachricht digital. Das Programm dafür heißt OpenDKIM.
sudo apt install opendkim opendkim-tools
Schlüssel erzeugen
sudo mkdir -p /etc/opendkim/keys/meine-domain.de
sudo opendkim-genkey -b 2048 -d meine-domain.de -D /etc/opendkim/keys/meine-domain.de -s default -v
sudo chown -R opendkim:opendkim /etc/opendkim
sudo chmod 600 /etc/opendkim/keys/meine-domain.de/default.private
Dabei entstehen zwei Dateien: default.private – der geheime Schlüssel, der auf dem Server bleibt – und default.txt – der öffentliche Schlüssel für das DNS. default ist der frei wählbare Name des Schlüssels (der „Selektor").
OpenDKIM einstellen
In der Datei /etc/opendkim.conf folgende Zeilen setzen bzw. ergänzen (vorhandene gleichnamige Zeilen anpassen):
Domain meine-domain.de
Selector default
KeyFile /etc/opendkim/keys/meine-domain.de/default.private
Socket local:/var/spool/postfix/opendkim/opendkim.sock
Mode sv
Canonicalization relaxed/simple
OversignHeaders From
SubDomains no
UMask 002
InternalHosts refile:/etc/opendkim/TrustedHosts
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
Falls in /etc/default/opendkim eine Zeile SOCKET= steht, wird sie mit # auskommentiert, damit die Angabe aus opendkim.conf gilt.
Die Datei /etc/opendkim/TrustedHosts anlegen mit dem Inhalt:
127.0.0.1
::1
localhost
mail.meine-domain.de
meine-domain.de
Platz für den Verbindungspunkt schaffen
Postfix läuft in einem abgeschotteten Verzeichnis (/var/spool/postfix). Der Verbindungspunkt zu OpenDKIM muss darin liegen:
sudo mkdir -p /var/spool/postfix/opendkim
sudo chown opendkim:postfix /var/spool/postfix/opendkim
sudo chmod 750 /var/spool/postfix/opendkim
sudo adduser postfix opendkim
Postfix mit OpenDKIM verbinden
sudo postconf -e 'milter_default_action = accept'
sudo postconf -e 'milter_protocol = 6'
sudo postconf -e 'smtpd_milters = local:opendkim/opendkim.sock'
sudo postconf -e 'non_smtpd_milters = local:opendkim/opendkim.sock'
Der Pfad ist ohne /var/spool/postfix davor angegeben, weil Postfix aus seinem abgeschotteten Verzeichnis heraus arbeitet. Entscheidend ist hier non_smtpd_milters: MediaWiki und Drupal übergeben ihre Post lokal, nicht über eine SMTP-Verbindung.
Dienste neu starten und für den Systemstart vormerken:
sudo systemctl restart opendkim
sudo systemctl enable opendkim
sudo systemctl restart postfix
Öffentlichen Schlüssel im DNS veröffentlichen
sudo cat /etc/opendkim/keys/meine-domain.de/default.txt
Die Ausgabe sieht ungefähr so aus:
default._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..." )
Daraus wird ein DNS-Eintrag:
| Name/Host | Typ | Wert |
|---|---|---|
default._domainkey | TXT | v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A... |
Der gesamte Inhalt ab v=DKIM1 wird zu einer Zeichenkette zusammengesetzt – die Anführungszeichen und Klammern aus der Datei entfallen, der p=-Teil wird ohne Leerzeichen aneinandergehängt. Viele DNS-Oberflächen nehmen den langen Wert direkt an.
Nach ein paar Minuten prüfen:
sudo opendkim-testkey -d meine-domain.de -s default -vvv
# die Meldung key OK bedeutet: passt
Schritt 10: DMARC-Eintrag im DNS
| Name/Host | Typ | Wert |
|---|---|---|
_dmarc | TXT | v=DMARC1; p=none; rua=mailto:postmaster@meine-domain.de; fo=1 |
p=none heißt: zu Beginn nur beobachten, nichts abweisen. An die rua-Adresse schicken die Empfänger regelmäßig Berichte. Sind diese Berichte nach ein bis zwei Wochen sauber, verschärft man auf p=quarantine (Verdachtspost in den Spam-Ordner) und später auf p=reject (Abweisung).
Schritt 11: Testen
Eine Testnachricht an eine eigene Gmail-Adresse senden:
echo "Dies ist ein Test von meinem eigenen Server." | mail -s "Postfix-Test" -a "From: noreply@meine-domain.de" meine-adresse@gmail.com
Dabei das Protokoll mitlesen:
sudo tail -f /var/log/mail.log
Gesucht wird eine Zeile mit status=sent und 250 2.0.0 OK. (Gibt es die Datei /var/log/mail.log nicht, hilft journalctl -u postfix -f.)
In Gmail die Nachricht öffnen, oben rechts auf die drei Punkte, dann Original anzeigen. Dort sollte stehen:
SPF: PASS
DKIM: 'PASS' with domain meine-domain.de
DMARC: 'PASS'
Zusätzlich die Nachricht durch mail-tester.com schicken: Die Seite zeigt eine Adresse an, an die man eine Mail sendet; nach dem Neuladen erscheint eine Bewertung. Ziel ist 10 von 10.
Landet die Post trotz dreier „PASS" im Spam, einmal „Kein Spam" wählen und einer neuen IP einige Tage Zeit geben, einen guten Ruf aufzubauen.
Schritt 12: MediaWiki anbinden
MediaWiki nutzt von Haus aus die mail()-Funktion von PHP, die die Nachricht über /usr/sbin/sendmail an Postfix übergibt. Es muss also nichts zusätzlich installiert werden – nur Adressen eingetragen. In LocalSettings.php:
$wgEnableEmail = true;
$wgEnableUserEmail = true;
$wgEmergencyContact = 'postmaster@meine-domain.de';
$wgPasswordSender = 'noreply@meine-domain.de';
$wgNoReplyAddress = 'noreply@meine-domain.de';
Die Einstellung $wgSMTP bleibt auf false (Voreinstellung), damit das lokale Postfix verwendet wird. Zum Prüfen die Seite Spezial:E-Mail_senden aufrufen oder ein Passwort zurücksetzen lassen.
Schritt 13: Drupal anbinden
Auch Drupal verschickt im Kern über die mail()-Funktion von PHP und damit über Postfix – ein Zusatzmodul ist nicht nötig. Die Absenderadresse der Website wird unter Verwaltung → Konfiguration → System → Basiseinstellungen (/admin/config/system/site-information) auf noreply@meine-domain.de gesetzt.
Wer später mehr Einfluss auf das Aussehen der E-Mails braucht (etwa HTML-Nachrichten), kann das Zusatzmodul Symfony Mailer nachrüsten; es kann das lokale Postfix als „Sendmail"-Weg weiterverwenden. Für Anmelde- und Passwortmails genügt der eingebaute Weg.
Zum Prüfen ein Testkonto anlegen oder /user/password verwenden.
Schritt 14: Laufender Betrieb
- Protokoll ansehen:
sudo tail -f /var/log/mail.log.deferredheißt: vorübergehend hängen geblieben, Postfix versucht es erneut;bouncedheißt: endgültig abgewiesen. - Warteschlange:
mailqzeigt wartende Post an,sudo postqueue -fstößt einen sofortigen neuen Versuch an. - Kein offenes Relay: Durch
inet_interfaces = loopback-onlynimmt der Server Post nur von sich selbst an. Diese Einstellung nicht ohne Anmeldung und weitere Regeln aufalländern. - Aktuell halten:
sudo apt upgradeversorgt Postfix und OpenDKIM mit Sicherheitsupdates. - Ruf der IP prüfen: gelegentlich unter
check.spamhaus.orgundmxtoolbox.comnachsehen. - DMARC verschärfen: nach sauberen Berichten
p=none→p=quarantine→p=reject. - Zertifikat: Wurde das Certbot-Zertifikat eingerichtet, bestätigt
sudo certbot renew --dry-run, dass die Erneuerung funktioniert.
Fehlersuche
| Symptom | Ursache | Lösung |
|---|---|---|
Post bleibt in der Warteschlange, connect to ...:25: Connection timed out | Anbieter sperrt ausgehenden Port 25 | beim Anbieter freischalten lassen |
Gmail: 550 ... does not have a valid PTR record | keine oder falsche Rückwärtsauflösung | PTR im Anbieter-Panel auf mail.meine-domain.de setzen |
Gmail-Header SPF: SOFTFAIL oder FAIL | SPF-Eintrag fehlt oder IP nicht enthalten | TXT-Eintrag v=spf1 ... ip4:203.0.113.10 -all prüfen |
Header DKIM: FAIL oder NEUTRAL | öffentlicher Schlüssel im DNS falsch, oder die Unterschrift greift nicht | opendkim-testkey ausführen; ist non_smtpd_milters gesetzt? Socket-Pfad richtig? |
warning: connect to Milter service local:opendkim/opendkim.sock: No such file or directory | Verzeichnis für den Verbindungspunkt fehlt oder falsche Rechte | /var/spool/postfix/opendkim anlegen, chown opendkim:postfix, OpenDKIM neu starten |
| Post landet trotz „PASS" im Spam | Ruf der IP noch niedrig | „Kein Spam" wählen, abwarten, Menge langsam steigern |
Für dieses Buch
Für den beschriebenen Aufbau ist ein Postfix, das nur sendet, genau das richtige Maß: MediaWiki und Drupal müssen Post verschicken, nicht empfangen. Der Server bleibt zum Internet hin geschlossen (loopback-only), womit das größte Risiko entfällt – der Missbrauch als Spam-Verteiler. Die Arbeit steckt nicht in Postfix selbst, sondern in den vier Nachweisen auf der DNS-Seite: Rückwärtsauflösung, SPF, DKIM und DMARC. Sind alle vier gesetzt, stellt Gmail in den Posteingang zu; fehlt einer, verschwindet die Post im Spam. Das Empfangen von Post (Postfächer, IMAP, Spam-Filter) ist eine eigene, größere Aufgabe; bis dahin zeigt der MX-Eintrag der Domain auf ein vorhandenes Postfach, damit Antworten und Berichte trotzdem ankommen.
Fazit
Postfix ist das Programm, das die E-Mails von MediaWiki und Drupal annimmt und zustellt. Auf Ubuntu 26.04 ist es mit einem apt-Befehl installiert und mit wenigen postconf-Zeilen als reiner Sendedienst eingerichtet: inet_interfaces = loopback-only hält den Server dabei nach außen dicht. Damit Gmail die Post annimmt, zählen vier Dinge im DNS: ein passender PTR-Eintrag für die IP, ein SPF-Eintrag, eine DKIM-Unterschrift über OpenDKIM mit veröffentlichtem Schlüssel und ein DMARC-Eintrag. Die Verbindung zu anderen Mailservern verschlüsselt Postfix beim Senden von selbst; ein eigenes Zertifikat von Certbot wird erst beim Empfangen nötig. MediaWiki und Drupal brauchen keine Zusatzsoftware – sie geben ihre Post über die mail()-Funktion von PHP direkt an das lokale Postfix. Ein Test an eine Gmail-Adresse und ein Blick in „Original anzeigen" auf die Zeilen SPF: PASS, DKIM: PASS und DMARC: PASS bestätigen, dass alles greift.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Containerisierung von Software
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Die Programme aus dem Kapitel Inhalts-Software selbst betreiben lassen sich auf zwei Arten auf einem Server einrichten. Der erste Weg ist die direkte Installation: Man lädt jedes Programm mit dem Paketbefehl des Betriebssystems (siehe Betriebssystem) herunter und startet es als Hintergrunddienst. Der zweite Weg heißt Containerisierung: Jedes Programm läuft dann in einem eigenen, abgeschlossenen Paket, einem sogenannten Container.
Dieses Buch beschreibt in den anderen Kapiteln den direkten Weg. Er ist für eine einzelne, kleine Wissenssammlung übersichtlich und braucht kein zusätzliches Werkzeug. Trotzdem gehört die Containerisierung zum Grundwissen für den Betrieb eines Servers: Ein großer Teil der Anleitungen im Internet setzt sie voraus, und viele Programme werden heute zuerst als Container ausgeliefert. Dieses Kapitel erklärt darum, was ein Container ist, welche Eigenschaften ihn ausmachen, welche Programme es dafür gibt und wie man Docker auf einem Ubuntu-Server einrichtet.
Was ein Container ist
Der Name ist wörtlich gemeint. Ein Schiffscontainer ist eine genormte Kiste: Was drin ist, spielt für den Kran und das Schiff keine Rolle, denn außen sind alle Container gleich. Ein Software-Container macht dasselbe mit einem Programm. Er packt das Programm zusammen mit allem, was es zum Laufen braucht – Hilfsbibliotheken, Einstellungen, kleine Zusatzwerkzeuge – in ein einziges Bündel. Dieses Bündel läuft dann auf jedem Rechner gleich, egal welche Programme sonst darauf installiert sind.
Die Vorlage für einen Container heißt Image (englisch für „Abbild"). Ein Image ist eine unveränderliche Datei, die ein fertig eingerichtetes Programm enthält. Aus einem Image startet man einen oder mehrere Container. Der Container ist die laufende Ausführung, das Image die Blaupause dazu.
Ein Container ist nicht dasselbe wie eine virtuelle Maschine (siehe den Abschnitt zu Proxmox VE im Kapitel Betriebssystem). Eine virtuelle Maschine bringt ein komplettes eigenes Betriebssystem mit und braucht entsprechend viel Arbeitsspeicher und Festplattenplatz. Ein Container teilt sich den Kern des Betriebssystems mit dem Wirt und enthält nur das Programm selbst. Dadurch startet er in Sekunden und belegt wenig Platz.
Wesentliche Eigenschaften
Sechs Merkmale beschreiben, was einen Container ausmacht:
- Abgeschlossen. Jeder Container ist vom Rest des Systems getrennt. Ein Programm im Container sieht nur seine eigenen Dateien und Prozesse, nicht die der anderen Container oder des Wirts. Stürzt ein Container ab, bleiben die übrigen unberührt.
- Alles dabei. Das Image enthält das Programm samt aller benötigten Bibliotheken in genau der passenden Version. Es gibt keinen Streit mehr darüber, ob auf dem Server die richtige Fassung einer Hilfsbibliothek liegt.
- Sparsam. Weil sich alle Container den Betriebssystemkern des Wirts teilen, kostet ein Container kaum mehr Leistung als das Programm selbst. Auf einem kleinen Server können problemlos ein Dutzend Container nebeneinander laufen.
- Immer gleich. Dasselbe Image liefert auf dem Entwicklungsrechner, auf dem Testserver und im echten Betrieb dasselbe Ergebnis. Der Satz „Bei mir läuft es doch" verliert seinen Sinn.
- Wegwerfbar. Ein Container ist dazu gedacht, jederzeit gelöscht und neu gestartet zu werden. Alles, was dauerhaft bleiben soll – zum Beispiel die Datenbankinhalte von PostgreSQL –, wird deshalb in einem getrennten Speicherbereich abgelegt, einem sogenannten Volume. Das Volume überlebt den Container.
- Aus einer Textdatei beschrieben. Wie ein Image aufgebaut ist, steht in einer kurzen Textdatei (bei Docker heißt sie
Dockerfile). Welche Container zusammen eine Anwendung ergeben, steht in einer weiteren Textdatei (compose.yaml). Diese Dateien lassen sich versionieren und weitergeben; aus ihnen entsteht die gesamte Umgebung neu.
Die wichtigsten Programme
Docker
Docker ist das mit Abstand verbreitetste Container-Werkzeug und für viele gleichbedeutend mit dem Thema. Es besteht aus mehreren Teilen: der Docker Engine, einem Hintergrunddienst, der die Container verwaltet; dem Befehl docker für die Bedienung über die Textkonsole; und Docker Compose, mit dem sich mehrere Container gemeinsam aus einer compose.yaml-Datei starten lassen. Zu Docker gibt es die meisten Anleitungen und die größte Sammlung fertiger Images (im „Docker Hub"). Für den Einstieg ist Docker die naheliegende Wahl.
Ein Punkt verdient Aufmerksamkeit: Die Docker Engine läuft standardmäßig mit vollen Systemrechten. Wer einen Benutzer berechtigt, Docker zu bedienen, gibt ihm damit faktisch die volle Kontrolle über den Server. Dazu weiter unten mehr.
Podman
Podman verfolgt dasselbe Ziel wie Docker und versteht fast dieselben Befehle – oft genügt es, docker durch podman zu ersetzen. Zwei Unterschiede sind wichtig. Erstens kommt Podman ohne ständig laufenden Hintergrunddienst aus. Zweitens laufen Container bei Podman von Haus aus ohne Systemrechte („rootless"), was die Sicherheit erhöht. Podman stammt aus dem Umfeld von Red Hat und ist auf den Distributionen der Red-Hat-Familie (siehe Betriebssystem) vorinstalliert oder leicht nachzurüsten. Auf Debian und Ubuntu ist es ebenfalls verfügbar.
Kubernetes (K8s)
Kubernetes ist kein Ersatz für Docker oder Podman, sondern eine Ebene darüber. Es verteilt Container über viele Server hinweg, startet abgestürzte Container neu, verschiebt Last von einem Rechner auf den anderen und rollt Aktualisierungen ohne Unterbrechung aus. Die Abkürzung „K8s" steht für das Wort Kubernetes mit acht ausgelassenen Buchstaben zwischen „K" und „s".
Für eine einzelne selbst betriebene Wissenssammlung ist Kubernetes deutlich überdimensioniert. Der Aufwand für Einrichtung und Pflege übersteigt den Nutzen bei Weitem. Es wird hier nur genannt, weil der Begriff in vielen Anleitungen auftaucht. Wer trotzdem in die Technik hineinschnuppern will, greift zu einer abgespeckten Ausgabe wie k3s oder MicroK8s, die auf einem einzelnen Server läuft.
Weitere Werkzeuge
- containerd und runc. Das sind die unteren Bausteine, die unter Docker die eigentliche Arbeit erledigen. Man bedient sie normalerweise nicht direkt, hört die Namen aber in Fehlermeldungen und Anleitungen.
- LXC und Incus (früher LXD). Diese Werkzeuge starten sogenannte Systemcontainer. Ein Systemcontainer verhält sich eher wie ein sehr sparsamer kompletter Rechner mit eigenem Betriebssystem-Nutzerbereich, während ein Docker-Container üblicherweise nur ein einzelnes Programm enthält.
- Portainer. Eine Weboberfläche, mit der sich Docker-Container per Mausklick im Browser verwalten lassen, statt über die Textkonsole. Praktisch für alle, die sich die Befehle nicht merken wollen.
- Docker Compose. Streng genommen kein eigenständiges Programm mehr, sondern ein fester Bestandteil von Docker. Es ist das Werkzeug der Wahl, sobald mehrere Container zusammenspielen – also genau im Fall dieses Buchs mit MediaWiki, PostgreSQL, Meilisearch und Ollama.
Kurzvergleich
| Werkzeug | Aufgabe | Für diesen Aufbau |
|---|---|---|
| Docker | Container einzeln oder als Gruppe betreiben | gut geeignet, größte Anleitungssammlung |
| Podman | wie Docker, ohne Dauerdienst, ohne Systemrechte | gut geeignet, sicherer voreingestellt |
| Docker Compose | mehrere Container aus einer Textdatei starten | empfohlen, sobald mehr als ein Programm läuft |
| Kubernetes (K8s) | Container über viele Server verteilen | überdimensioniert |
| k3s / MicroK8s | Kubernetes für einen einzelnen Server | nur zum Ausprobieren |
| LXC / Incus | Systemcontainer statt Einzelprogramm-Container | Sonderfall |
| Portainer | Container im Browser verwalten | optionale Erleichterung |
Docker auf Ubuntu einrichten
Die folgenden Schritte gelten für Ubuntu 26.04 LTS und ebenso für die älteren Ausgaben 24.04 und 22.04. Alle Befehle werden in der Textkonsole des Servers eingegeben. Das Zeichen sudo am Anfang bedeutet: mit Verwaltungsrechten ausführen.
Schritt 1: Alte Pakete entfernen
Ubuntu bringt teils veraltete oder unvollständige Docker-Pakete mit. Diese werden zuerst entfernt, damit sie sich nicht mit der offiziellen Fassung ins Gehege kommen:
for paket in docker.io docker-doc docker-compose podman-docker containerd runc; do
sudo apt-get remove -y $paket
done
Meldet der Befehl, dass ein Paket gar nicht installiert war, ist das in Ordnung.
Schritt 2: Die Paketquelle von Docker eintragen
Damit Ubuntu die aktuelle Docker-Fassung findet, wird die offizielle Paketquelle des Herstellers hinzugefügt. Dazu gehört ein digitaler Schlüssel, mit dem Ubuntu prüft, dass die Pakete echt sind:
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Schritt 3: Docker installieren
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
Damit sind die Docker Engine, der Bedienbefehl docker und Docker Compose eingerichtet.
Schritt 4: Prüfen, ob es läuft
sudo docker run --rm hello-world
Docker lädt ein winziges Test-Image herunter, startet es und gibt eine Erfolgsmeldung aus. Der Zusatz --rm löscht den Test-Container gleich wieder.
Wichtige Einstellungen
Nach der Installation sind einige Anpassungen sinnvoll.
Docker ohne „sudo" bedienen – mit Bedacht
Damit ein normaler Benutzer docker ohne vorangestelltes sudo verwenden kann, wird er in die Gruppe docker aufgenommen:
sudo usermod -aG docker $USER
Danach einmal ab- und wieder anmelden. Wichtig zu wissen: Wer in dieser Gruppe ist, kann über Docker die volle Kontrolle über den Server erlangen. Auf einem Server sollte deshalb nur der Betreiber selbst in dieser Gruppe sein. Wer das vermeiden will, betreibt Docker im rootless-Modus (das Docker-Projekt liefert dafür das Skript dockerd-rootless-setuptool.sh mit) oder nutzt gleich Podman, das ohne Systemrechte arbeitet.
Automatischer Start nach einem Neustart
Damit die Docker Engine nach jedem Server-Neustart von selbst hochfährt:
sudo systemctl enable --now docker.service containerd.service
Einzelne Container starten nach einem Neustart nur dann wieder, wenn man ihnen das mitgibt – bei docker run mit dem Zusatz --restart unless-stopped, in einer compose.yaml mit der Zeile restart: unless-stopped.
Protokolldateien begrenzen
Ohne Vorgabe schreiben Container ihre Protokolle unbegrenzt auf die Festplatte, bis diese voll ist. Eine Obergrenze wird in der Datei /etc/docker/daemon.json gesetzt:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Danach sudo systemctl restart docker ausführen. Jeder Container behält so höchstens drei Protokolldateien zu je 10 Megabyte.
Speicherort der Daten kennen
Images, Container und Volumes liegen unter /var/lib/docker. Dieses Verzeichnis kann groß werden. Es sollte auf einer Festplatte mit genügend Platz liegen und in die Datensicherung einbezogen werden – allerdings nur die Volumes, denn nur dort stehen die eigenen Inhalte. Der Befehl docker system df zeigt den Verbrauch, docker system prune entfernt nicht mehr benötigte Reste.
Docker und die Firewall
Docker trägt seine Regeln direkt in die Netzwerkfilter des Betriebssystems ein und umgeht dabei die verbreitete Firewall ufw. Ein mit -p 8080:80 nach außen geöffneter Container ist deshalb aus dem Internet erreichbar, auch wenn ufw den Port eigentlich sperrt. Wer eine Firewall betreibt, veröffentlicht Container-Ports darum nur an die lokale Adresse (-p 127.0.0.1:8080:80) und stellt einen Webserver davor, oder richtet die Filterregeln von Hand ein.
Für dieses Buch
Die anderen Kapitel richten MediaWiki, PostgreSQL, Meilisearch und Ollama ohne Container ein. Dieser Weg bleibt die Empfehlung für eine erste, kleine Wissenssammlung: weniger Werkzeuge, weniger Schichten, weniger, das schiefgehen kann. Container werden interessant, sobald man die Sammlung auf einen neuen Server umziehen will, mehrere getrennte Umgebungen (Test und Betrieb) braucht oder ein Programm ausprobieren möchte, ohne den Server dauerhaft zu verändern. Dann lohnt sich der Blick auf Docker Compose, mit dem sich der gesamte Aufbau in einer einzigen Textdatei beschreiben lässt.
Fazit
Ein Container packt ein Programm mit allem Nötigen in ein abgeschlossenes, sparsames und überall gleich laufendes Bündel. Docker ist das gängige Werkzeug dafür, Podman die von Haus aus sicherere Alternative, Kubernetes eine Nummer zu groß für einen einzelnen Server. Auf Ubuntu wird Docker über die offizielle Paketquelle des Herstellers eingerichtet; danach sollte man den Zugang zur docker-Gruppe eng halten, den automatischen Start aktivieren, die Protokolle begrenzen und die Wechselwirkung mit der Firewall beachten. Für die Wissenssammlung dieses Buchs ist Containerisierung kein Muss – aber ein Werkzeug, das man kennen sollte, sobald der Aufbau wächst.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
KI-Agenten auf dem Server
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Ein KI-Agent ist ein Programm, das eine Aufgabe nicht nur beantwortet, sondern selbstständig ausführt: mehrere Schritte hintereinander, mit Werkzeugen, die es selbst bedient. Das Kapitel Desktop-Agenten beschreibt solche Programme für den eigenen Computer. Dieses Kapitel geht einen Schritt weiter: Der Agent läuft dann nicht mehr auf dem Arbeitsplatzrechner, sondern rund um die Uhr auf dem gemieteten Server (siehe Server mieten).
Das ist nützlich, wenn ein Agent Dinge tun soll, während niemand am Rechner sitzt: neue Seiten der Wissenssammlung nachts prüfen, auf eingehende Nachrichten reagieren, regelmäßig Daten zusammentragen. Damit die Inhalte dabei im eigenen Haus bleiben, arbeiten alle hier vorgestellten Programme mit Ollama zusammen – dem Dienst, der Sprachmodelle auf dem eigenen Rechner ausführt (siehe Inhalts-Software selbst betreiben).
Dieses Kapitel stellt drei Programme vor – n8n, OpenClaw und Hermes Agent –, richtet einen Ubuntu-Server dafür ein und zeigt, wie jedes von ihnen mit einem lokalen Sprachmodell verbunden wird.
Die drei Programme im Überblick
| Programm | Grundidee | Bedienung |
|---|---|---|
| n8n | Abläufe als Baukasten aus verbundenen Kästchen | Weboberfläche im Browser |
| OpenClaw | ein Assistent, den man über Messenger anspricht | Chat-App (Signal, Telegram …) plus Textkonsole |
| Hermes Agent | ein Agent für die Textkonsole, der dazulernt | Textkonsole, zusätzlich über Messenger erreichbar |
Alle drei sind quelloffen und dürfen kostenlos selbst betrieben werden. Sie schließen sich nicht aus – man kann mit einem beginnen und die anderen später daneben stellen.
n8n – Abläufe zusammenstecken
n8n ist ein Werkzeug für Automatisierung. Man baut einen Ablauf (dort „Workflow" genannt) aus einzelnen Bausteinen zusammen, die wie Kästchen auf einer Fläche liegen und mit Linien verbunden werden. Ein Baustein holt zum Beispiel eine neue Wiki-Seite ab, der nächste schickt ihren Text an ein Sprachmodell, der übernächste trägt das Ergebnis irgendwo ein. Für Hunderte Dienste gibt es fertige Bausteine; ein eigener Baustein „AI Agent" lässt das Modell selbst entscheiden, welche Werkzeuge es in welcher Reihenfolge benutzt.
n8n eignet sich, wenn der Ablauf klar umrissen ist und immer gleich abläuft. Die Weboberfläche macht sichtbar, was in welchem Schritt passiert, und das erleichtert die Fehlersuche. n8n steht unter einer quelloffenen Lizenz (der „Sustainable Use License"): Der Quelltext liegt offen, und der Betrieb für eigene Zwecke ist kostenlos; nur das Weiterverkaufen als eigener Dienst ist eingeschränkt.
OpenClaw – der Assistent im Messenger
OpenClaw ist ein selbst betriebener Assistent, den man über gewohnte Chat-Programme anspricht – etwa Signal, Telegram, Slack oder WhatsApp. Auf dem Server läuft ein Vermittler (im Projekt „Gateway" genannt), der die Nachrichten entgegennimmt, an ein Sprachmodell weiterreicht und die Antworten zurückschickt. Der Agent kann dabei auf dem Server Befehle ausführen, im Browser klicken, Dateien bearbeiten oder E-Mails schreiben.
OpenClaw eignet sich, wenn man den Agenten wie eine Person im Chat behandeln möchte: kurze Anweisung schicken, Ergebnis abwarten. Das Projekt ist noch jung, entwickelt sich schnell und wird von einer gemeinnützigen Stiftung offen gepflegt. Es steht unter der MIT-Lizenz, einer der freizügigsten Lizenzen überhaupt.
Ein Hinweis zur Vorsicht: Ein Agent, der Nachrichten aus einem Messenger annimmt und daraufhin Befehle auf dem Server ausführt, ist eine mächtige und zugleich heikle Kombination. Er sollte nur mit den nötigsten Rechten laufen und nicht auf demselben Server wie die öffentliche Wissenssammlung.
Hermes Agent – der lernende Agent in der Konsole
Hermes Agent stammt von der Forschungsgruppe Nous Research und läuft in der Textkonsole. Er führt Aufgaben mit über 40 Werkzeugen aus, kann Teilaufgaben an Unter-Agenten abgeben und Abläufe zu festen Zeiten starten. Die Besonderheit ist eine eingebaute Lernschleife: Aus erledigten Aufgaben legt der Agent kleine wiederverwendbare „Skills" an und erinnert sich über Sitzungen hinweg an frühere Gespräche.
Hermes Agent eignet sich für alle, die ohnehin auf dem Server über die Textkonsole arbeiten und einen Helfer für wiederkehrende Handgriffe suchen. Wie OpenClaw kann er über einen eingebauten Zugang zusätzlich aus Messengern angesprochen werden. Er steht unter der MIT-Lizenz und arbeitet mit lokalen Modellen über Ollama, LM Studio oder vergleichbare Dienste.
Den Server vorbereiten
Grundlage ist ein Server mit Ubuntu 26.04 LTS (siehe Betriebssystem). Alle Befehle werden in der Textkonsole des Servers eingegeben. sudo am Anfang bedeutet: mit Verwaltungsrechten ausführen.
Schritt 1: Das System aktualisieren
sudo apt update && sudo apt upgrade -y
Schritt 2: Docker einrichten
n8n wird am einfachsten als Container betrieben, OpenClaw und Hermes Agent lassen sich ebenfalls in einen Container packen. Die Einrichtung von Docker beschreibt das Kapitel Containerisierung von Software Schritt für Schritt. Kurz zusammengefasst:
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
Schritt 3: Ollama einrichten
Ollama stellt die Sprachmodelle bereit, die alle drei Agenten nutzen. Es wird mit einem Befehl installiert:
curl -fsSL https://ollama.com/install.sh | sh
Danach lädt man ein Modell herunter, zum Beispiel ein kleineres, das auch ohne starke Grafikkarte läuft:
ollama pull llama3.1:8b
Ollama lauscht danach auf dem eigenen Rechner unter der Adresse http://localhost:11434. Läuft ein Agent in einem Docker-Container, erreicht er Ollama nicht über localhost, sondern über die besondere Adresse http://host.docker.internal:11434. Diese muss dem Container beim Start mit dem Zusatz --add-host=host.docker.internal:host-gateway bekannt gemacht werden.
Für den echten Betrieb („Produktionsserver") gelten zwei Regeln:
- Ollama nicht ins Internet öffnen. Der Dienst hat keine Anmeldung. Er darf nur vom Server selbst und von den Containern darauf erreichbar sein, niemals von außen. Die Firewall des Anbieters sollte den Port
11434von außen sperren. - Modellgröße zur Hardware wählen. Ein Modell mit 8 Milliarden Parametern (Kurzform „8b") läuft auf bescheidener Hardware, antwortet aber langsamer. Für flüssige Antworten braucht der Server eine Grafikkarte mit ausreichend Speicher. Ohne Grafikkarte bleibt man besser bei kleinen Modellen und plant längere Wartezeiten ein.
n8n einrichten
n8n wird als einzelner Container gestartet. Zuerst wird ein dauerhafter Speicherbereich angelegt, damit die Abläufe einen Neustart überstehen:
docker volume create n8n_data
docker run -d --restart unless-stopped --name n8n \
-p 127.0.0.1:5678:5678 \
--add-host=host.docker.internal:host-gateway \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
Der Zusatz -p 127.0.0.1:5678:5678 sorgt dafür, dass die Weboberfläche nur vom Server selbst erreichbar ist. Für den Zugriff über das Internet stellt man einen Webserver mit Verschlüsselung und Passwortschutz davor; wie das geht, gehört in ein eigenes Kapitel.
Die Oberfläche ist danach unter http://localhost:5678 erreichbar (bei Fernzugriff über einen verschlüsselten Tunnel). Beim ersten Aufruf legt man ein Benutzerkonto an.
n8n mit Ollama verbinden
In einem Ablauf fügt man einen Baustein vom Typ AI Agent ein und weist ihm ein Sprachmodell zu. Als Modell wählt man Ollama Chat Model und trägt bei den Zugangsdaten die Adresse http://host.docker.internal:11434 ein. Anschließend lässt sich der gewünschte Modellname (etwa llama3.1:8b) auswählen. Ab jetzt bearbeitet der Baustein jede Anfrage mit dem lokalen Modell.
OpenClaw einrichten
OpenClaw wird mit einem Skript installiert. Das Projekt entwickelt sich schnell – die aktuelle Anleitung steht unter docs.openclaw.ai. Zum Zeitpunkt der Erstellung dieses Kapitels lautet der Weg:
curl -fsSL https://openclaw.ai/install.sh | bash
openclaw onboard --install-daemon
Der Befehl onboard führt durch die Einrichtung: Man wählt einen Messenger aus, hinterlegt die Zugangsdaten dafür und legt fest, welches Sprachmodell benutzt wird. Mit --install-daemon richtet OpenClaw sich als Hintergrunddienst ein, der nach jedem Server-Neustart von selbst wieder startet.
Wichtig: Skripte aus dem Internet direkt auszuführen, sollte man nur bei Quellen tun, denen man vertraut. Wer sichergehen will, lädt das Skript zuerst herunter, liest es und führt es dann aus. Alternativ bietet das Projekt eine
docker-compose.ymlan, mit der OpenClaw in einem Container läuft.
OpenClaw mit Ollama verbinden
Bei der Einrichtung – oder später in der Einstellungsdatei von OpenClaw – wählt man als Modellanbieter einen lokalen Dienst und trägt die Ollama-Adresse ein: http://localhost:11434 bei direkter Installation, http://host.docker.internal:11434 im Container. Als Modell wird der Name des mit ollama pull geladenen Modells angegeben. Danach laufen alle Anfragen über den eigenen Server, ohne dass Nachrichten an einen fremden Anbieter gehen.
Hermes Agent einrichten
Auch Hermes Agent wird per Skript installiert:
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
Das Installationsprogramm bringt die nötigen Hilfsprogramme (unter anderem Python und Node.js) selbst mit. Gestartet wird der Agent danach mit dem Befehl hermes in der Textkonsole. Beim ersten Start fragt er nach dem Modellanbieter.
Hinweis: Läuft die Verbindung zum Server über SSH, endet ein per Konsole gestarteter Agent, sobald die Verbindung getrennt wird. Damit er weiterläuft, startet man ihn in einer Sitzungsverwaltung wie tmux oder screen oder richtet ihn als Dienst ein. Der gleiche Sicherheitshinweis wie bei OpenClaw gilt auch hier.
Hermes Agent mit Ollama verbinden
In der Einrichtung wählt man einen lokalen, OpenAI-kompatiblen Anbieter und trägt als Adresse die Ollama-Schnittstelle ein: http://localhost:11434/v1. Als Modell wird der geladene Ollama-Modellname eingetragen. Ollama bietet neben seiner eigenen auch eine Schnittstelle im OpenAI-Format an; darüber sprechen die meisten Agenten mit lokalen Modellen.
Welches Programm wofür
| Aufgabe | Passendes Programm |
|---|---|
| Fester, wiederkehrender Ablauf mit vielen Diensten | n8n |
| Agent wie ein Chat-Kontakt per Messenger bedienen | OpenClaw |
| Helfer in der Textkonsole für Server-Handgriffe | Hermes Agent |
| Nur ausprobieren, ohne den Server zu verändern | jedes davon als Docker-Container |
Für dieses Buch
Für die Wissenssammlung dieses Buchs ist ein KI-Agent auf dem Server kein Pflichtbestandteil. Er wird interessant, sobald wiederkehrende Aufgaben anfallen: neue Seiten automatisch einordnen, Zusammenfassungen erzeugen, die Bedeutungssuche mit frischen Zahlenreihen versorgen. Für solche festen Abläufe ist n8n der übersichtlichste Einstieg, weil jeder Schritt sichtbar bleibt. OpenClaw und Hermes Agent sind die richtige Wahl, wenn man den Agenten frei anweisen möchte statt einen festen Ablauf zu bauen – mit dem Bewusstsein, dass ein frei handelnder Agent auf einem Server sorgfältig abgesichert werden muss.
Fazit
Ein KI-Agent auf dem Server erledigt Aufgaben, während niemand am Rechner sitzt. n8n baut feste Abläufe aus verbundenen Bausteinen und zeigt sie in einer Weboberfläche. OpenClaw macht aus einem Messenger die Fernbedienung für einen Assistenten. Hermes Agent ist ein lernender Helfer für die Textkonsole. Alle drei sind quelloffen, laufen auf einem Ubuntu-Server mit Docker und arbeiten mit lokalen Sprachmodellen über Ollama zusammen, sodass keine Inhalte an fremde Anbieter abfließen. Im echten Betrieb gilt: Ollama nie ins Internet öffnen, die Modellgröße zur Hardware wählen und einem frei handelnden Agenten nur die nötigsten Rechte geben.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Git Hosting
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Der Quelltext dieses Buchs liegt in einem Git-Verzeichnis (siehe Docs-as-Code). Git merkt sich jede Änderung: wer sie gemacht hat, wann und warum. Solange dieses Verzeichnis nur auf dem eigenen Rechner liegt, ist es aber schlecht geschützt und lässt sich nicht mit anderen teilen. Dafür braucht es eine zentrale Stelle im Netz, bei der alle Beteiligten ihre Änderungen abliefern und die Änderungen der anderen abholen. Diese Stelle heißt Git-Hosting.
Bekannt ist vor allem GitHub. Das ist ein Dienst einer Firma; die Verzeichnisse liegen auf deren Servern. Man kann so einen Dienst aber auch selbst betreiben (siehe Inhalts-Software selbst betreiben). Dieses Kapitel zeigt, wie man dafür Forgejo auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) einrichtet und über einen Unix-Socket an den Webserver NGINX anbindet – am Beispiel der Adresse https://git.meine-domain.de.
Alle Befehle werden in der Textkonsole des Servers eingegeben. Ein vorangestelltes sudo bedeutet: mit Verwaltungsrechten ausführen.
Was Git-Hosting ist
Git allein ist nur ein Programm auf der Festplatte. Es verwaltet die Versionsgeschichte eines Verzeichnisses. Damit mehrere Leute am selben Projekt arbeiten können, muss es eine gemeinsame Ablage geben, die alle erreichen. Diese gemeinsame Ablage nennt Git ein entferntes Verzeichnis (auf Englisch remote).
Ein Git-Hosting-Dienst stellt solche entfernten Verzeichnisse bereit und packt eine Weboberfläche darum herum. Damit kann man:
- Verzeichnisse anlegen und verwalten – öffentlich sichtbar oder nur für angemeldete Personen.
- Den Quelltext im Browser durchblättern, ohne ihn erst herunterzuladen.
- Änderungswünsche besprechen. Wer etwas beitragen möchte, reicht seine Änderungen als Vorschlag ein (auf Englisch pull request). Andere sehen den Unterschied Zeile für Zeile, schreiben Anmerkungen und übernehmen den Vorschlag erst, wenn er passt.
- Aufgaben und Fehler sammeln – als Liste von Einträgen (auf Englisch issues), die man einzelnen Personen zuordnen und abhaken kann.
- Automatische Abläufe starten, sobald neue Änderungen ankommen – zum Beispiel das Buch bauen und veröffentlichen (siehe Webseiten und Blogs).
Der eigentliche Datenaustausch läuft über zwei Wege: HTTPS (dieselbe verschlüsselte Verbindung wie beim Surfen) oder SSH (eine verschlüsselte Verbindung mit Schlüsseldatei statt Passwort). Die Weboberfläche selbst ist immer über HTTPS erreichbar.
Was Forgejo ist
Forgejo (gesprochen etwa „for-dsche-jo", vom Esperanto-Wort forĝejo – die Schmiede) ist ein Programm, mit dem man einen eigenen Git-Hosting-Dienst betreibt. Es ist Freie Software (siehe Freies Wissen) unter der Lizenz GPL Version 3 und wird von Codeberg e. V. getragen, einem gemeinnützigen Verein aus Berlin.
Woher Forgejo kommt
Forgejo ist eine Abspaltung von Gitea (auf Englisch fork): eine Kopie des Quelltexts, die von da an einen eigenen Weg geht. Gitea wiederum war selbst eine Abspaltung eines älteren Programms namens Gogs.
Der Grund für die Abspaltung war ein Streit um die Kontrolle über das Projekt. Ende 2022 übertrug der Hauptentwickler von Gitea die Namensrechte und die Leitung an eine gewinnorientierte Firma, ohne die Gemeinschaft der Mitwirkenden vorher zu fragen. Ein Teil dieser Gemeinschaft wollte das Projekt lieber in den Händen eines gemeinnützigen Vereins sehen und gründete daraufhin Forgejo. Anfangs übernahm Forgejo noch alle Änderungen von Gitea; seit Anfang 2024 sind die beiden Programme vollständig getrennt und entwickeln sich auseinander.
Für den Betrieb heißt das: Forgejo wird von einem Verein nach demokratischen Regeln geführt, nicht von einer einzelnen Firma. Wer von Gitea zu Forgejo wechselt, kann seine Daten in aller Regel unverändert übernehmen, weil beide noch dieselbe Grundstruktur haben.
Was Forgejo kann
Forgejo ist in der Programmiersprache Go geschrieben (siehe Programmiersprachen). Ein Go-Programm wird zu einer einzigen ausführbaren Datei übersetzt, die ohne weitere Bestandteile läuft. Deshalb besteht die Installation im Kern nur darin, diese eine Datei auf den Server zu legen.
Der Funktionsumfang ist groß:
| Bereich | Was Forgejo bietet |
|---|---|
| Verzeichnisse | anlegen, durchblättern, Rechte je Person oder Gruppe vergeben |
| Zusammenarbeit | Änderungsvorschläge, Anmerkungen Zeile für Zeile, Aufgabenlisten |
| Automatische Abläufe | „Forgejo Actions" – Aufgaben, die bei jeder Änderung anlaufen |
| Pakete | eine Ablage für fertige Programmbausteine (z. B. für Java, JavaScript, Container) |
| Wiki | zu jedem Verzeichnis eine kleine Sammlung von Erklärseiten |
| Anmeldung | eigene Konten oder Anbindung an einen zentralen Verzeichnisdienst |
Ein längerfristiges Ziel des Projekts ist die Föderation: Verschieden betriebene Forgejo-Server sollen sich untereinander verständigen können, sodass jemand auf Server A einen Änderungsvorschlag für ein Verzeichnis auf Server B einreichen kann, ohne dort ein Konto zu haben. Dieser Teil ist noch in Arbeit.
Forgejo im Vergleich
| Forgejo (selbst betrieben) | GitHub | GitLab (selbst betrieben) | |
|---|---|---|---|
| Betreiber | man selbst | Firma (Microsoft) | man selbst |
| Lizenz | Freie Software (GPL 3) | geschlossen | Kern frei, Zusätze geschlossen |
| Ressourcen | sehr sparsam | – | vergleichsweise hoch |
| Einrichtung | eine Programmdatei plus Datenbank | entfällt (fertiger Dienst) | umfangreich |
GitLab bietet mehr fertige Funktionen, verlangt aber deutlich mehr Arbeitsspeicher und Pflege. Für eine kleine Redaktion, die vor allem ein sicheres, gemeinsames Zuhause für ihre Texte und ihren Quelltext braucht, ist Forgejo die passende Größe.
Voraussetzungen
- Ein Server mit Ubuntu 26.04 LTS und einem Webserver davor. Dieses Kapitel geht von NGINX aus (siehe Webserver).
- Eine Domain, deren DNS-Eintrag auf den Server zeigt – hier
git.meine-domain.de. - Eine Datenbank. Forgejo kann eine einzelne Datei (SQLite) verwenden oder eine richtige Datenbank (PostgreSQL, MariaDB). Für wenige Nutzer genügt SQLite und spart die Einrichtung. Wer mit stärkerem Andrang rechnet, nimmt PostgreSQL (siehe Datenbank). Dieses Kapitel zeigt den Weg mit SQLite und nennt die Stellen, an denen PostgreSQL abweicht.
- Arbeitsspeicher: Forgejo selbst kommt mit wenigen Hundert MB aus. Zusammen mit Betriebssystem und Webserver reicht ein kleiner Server mit 1 bis 2 GB.
Forgejo installieren
Schritt 1: Git auf dem Server bereitstellen
Forgejo ruft im Hintergrund das Programm git auf. Für größere Dateien kommt git-lfs dazu:
sudo apt update
sudo apt install git git-lfs
Schritt 2: Die Programmdatei herunterladen und prüfen
Die aktuelle Versionsnummer steht auf der Seite https://forgejo.org/download/. Sie wird hier einmal in eine Variable geschrieben, damit die folgenden Befehle unverändert bleiben:
cd /tmp
VERSION=16.0.3
# Die Programmdatei für 64-Bit-PCs herunterladen
wget "https://code.forgejo.org/forgejo/forgejo/releases/download/v${VERSION}/forgejo-${VERSION}-linux-amd64"
# Die zugehörige Unterschrift herunterladen
wget "https://code.forgejo.org/forgejo/forgejo/releases/download/v${VERSION}/forgejo-${VERSION}-linux-amd64.asc"
# Den öffentlichen Schlüssel des Forgejo-Projekts holen
gpg --keyserver keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710
# Die Datei gegen die Unterschrift prüfen – die Ausgabe muss "Good signature" enthalten
gpg --verify "forgejo-${VERSION}-linux-amd64.asc" "forgejo-${VERSION}-linux-amd64"
Die digitale Unterschrift ist ein Nachweis, dass die Datei wirklich vom Forgejo-Projekt stammt und unterwegs nicht verändert wurde. Meldet gpg etwas anderes als eine gültige Unterschrift, wird die Datei nicht benutzt, sondern neu geladen. Der Hinweis „This key is not certified with a trusted signature" ist dabei normal – er besagt nur, dass man dem Schlüssel noch nicht ausdrücklich vertraut hat.
Danach die geprüfte Datei an ihren Platz legen:
sudo cp "forgejo-${VERSION}-linux-amd64" /usr/local/bin/forgejo
sudo chmod 755 /usr/local/bin/forgejo
Schritt 3: Einen eigenen Benutzer anlegen
Forgejo soll nicht mit Verwaltungsrechten laufen. Sonst hätte ein Fehler im Programm sofort Zugriff auf den ganzen Server. Deshalb bekommt es einen eigenen Benutzer namens git:
sudo adduser --system --shell /bin/bash --gecos 'Git Versionsverwaltung' \
--group --disabled-password --home /home/git git
--systemlegt ein Dienstkonto an, kein persönliches.--disabled-passwordverhindert das Anmelden mit einem Passwort.--shell /bin/bashwird hier gebraucht, weil Forgejo den Zugang über SSH später über diesen Benutzer abwickelt.
Schritt 4: Verzeichnisse anlegen
Forgejo trennt seine Dateien in zwei Bereiche: die Daten (Verzeichnisse, Datenbank, Anhänge) unter /var/lib/forgejo und die Konfiguration unter /etc/forgejo.
sudo mkdir /var/lib/forgejo
sudo chown git:git /var/lib/forgejo
sudo chmod 750 /var/lib/forgejo
sudo mkdir /etc/forgejo
sudo chown root:git /etc/forgejo
sudo chmod 770 /etc/forgejo
Das Konfigurationsverzeichnis gehört root, die Gruppe git darf hineinschreiben. Das ist nötig, weil die Ersteinrichtung im Browser die Konfigurationsdatei anlegt. Danach werden die Rechte wieder enger gesetzt (siehe Schritt 8).
Schritt 5: Eine erste Konfiguration schreiben
Forgejo liest beim Start die Datei /etc/forgejo/app.ini. Für den ersten Start genügt ein kleines Gerüst; den Rest ergänzt die Ersteinrichtung im Browser. Die Datei wird als Benutzer git angelegt:
sudo -u git nano /etc/forgejo/app.ini
Mit diesem Inhalt:
APP_NAME = Git der Redaktion
RUN_USER = git
RUN_MODE = prod
[server]
PROTOCOL = http+unix
HTTP_ADDR = /run/forgejo/forgejo.sock
UNIX_SOCKET_PERMISSION = 660
DOMAIN = git.meine-domain.de
ROOT_URL = https://git.meine-domain.de/
SSH_DOMAIN = git.meine-domain.de
[database]
DB_TYPE = sqlite3
PATH = /var/lib/forgejo/data/forgejo.db
Was die wichtigsten Zeilen bedeuten:
PROTOCOL = http+unixundHTTP_ADDR = …sagen Forgejo, dass es nicht auf einem Netzwerk-Port lauschen soll, sondern an einer Socket-Datei. Was das ist und warum es sich lohnt, erklären die Kapitel Unix-Socket und Unix-Socket bei NGINX. Kurz gesagt: So steht kein Port offen, der aus Versehen ins Netz geöffnet werden könnte, und der Zugriff hängt allein an Dateirechten.ROOT_URList die Adresse, unter der Besucher Forgejo erreichen. Sie muss stimmen, sonst baut Forgejo falsche Links.- Für PostgreSQL statt SQLite lautet der
[database]-Abschnitt anders (DB_TYPE = postgres, dazuHOST,NAME,USER,PASSWD); die Werte stammen aus dem Kapitel Datenbank.
Schritt 6: Den Dienst einrichten
Damit Forgejo beim Serverstart automatisch hochfährt, wird es als systemd-Dienst eingetragen. Das Projekt liefert eine fertige Dienstdatei mit:
sudo wget -O /etc/systemd/system/forgejo.service \
https://code.forgejo.org/forgejo/forgejo/raw/branch/forgejo/contrib/systemd/forgejo.service
Diese Datei setzt bereits die richtigen Pfade (WorkingDirectory=/var/lib/forgejo, Konfiguration unter /etc/forgejo/app.ini). Eine Ergänzung ist nötig, damit das Verzeichnis für die Socket-Datei bei jedem Start angelegt wird:
sudo systemctl edit forgejo
Im vorgesehenen Bereich eintragen:
[Service]
RuntimeDirectory = forgejo
RuntimeDirectoryMode = 0750
RuntimeDirectory = forgejo sorgt dafür, dass systemd beim Start des Dienstes das Verzeichnis /run/forgejo anlegt – dem Benutzer git gehörend – und beim Stoppen wieder entfernt. Genau dort legt Forgejo dann seine Socket-Datei ab.
Dann den Dienst bekannt machen, einschalten und starten:
sudo systemctl daemon-reload
sudo systemctl enable --now forgejo
sudo systemctl status forgejo
status sollte active (running) zeigen. Zur Kontrolle, dass die Socket-Datei da ist:
ls -l /run/forgejo/forgejo.sock
Schritt 7: NGINX als Reverse Proxy
Der Webserver NGINX nimmt die Verbindungen aus dem Internet an, verschlüsselt sie (HTTPS) und reicht sie an die Socket-Datei weiter. Diese Rolle heißt Reverse Proxy (siehe Webserver).
Zuerst darf der Benutzer www-data, unter dem NGINX läuft, die Socket-Datei benutzen. Die Datei gehört git:git mit den Rechten rw-rw----. Also wird www-data in die Gruppe git aufgenommen:
sudo usermod -aG git www-data
sudo systemctl restart forgejo nginx
Ein bloßes reload genügt für die neue Gruppenzugehörigkeit nicht; NGINX muss vollständig neu starten.
Dann das SSL-Zertifikat besorgen. Wie das mit Certbot und Let's Encrypt genau geht, steht im Kapitel Webserver; für eine feste Domain genügt:
sudo certbot certonly --nginx -d git.meine-domain.de
Jetzt die Konfigurationsdatei /etc/nginx/sites-available/git.meine-domain.de anlegen:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name git.meine-domain.de;
ssl_certificate /etc/letsencrypt/live/git.meine-domain.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.meine-domain.de/privkey.pem;
# Git-Verzeichnisse und Anhänge können groß werden
client_max_body_size 512m;
# Kodierte Schrägstriche in Adressen nicht zusammenfassen
merge_slashes off;
location / {
proxy_pass http://unix:/run/forgejo/forgejo.sock:/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Für die Live-Aktualisierung mancher Seiten
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
}
server {
listen 80;
listen [::]:80;
server_name git.meine-domain.de;
# Alle unverschlüsselten Aufrufe auf HTTPS umleiten
return 301 https://$host$request_uri;
}
Die Zeile proxy_pass http://unix:/run/forgejo/forgejo.sock:/; ist der Weg zur Socket-Datei. Die Schreibweise ist etwas ungewohnt: Nach http://unix: folgt der Pfad zur Socket-Datei, dann ein Doppelpunkt und der Pfad innerhalb der Anwendung (/).
Die Datei aktiv schalten, prüfen und übernehmen:
sudo ln -s /etc/nginx/sites-available/git.meine-domain.de /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Weil kein Port für Forgejo geöffnet wurde, ist an der Firewall nichts zusätzlich zu sperren. Es genügt, dem Webserver die Ports 80 und 443 zu erlauben (siehe Webserver).
Schritt 8: Die Ersteinrichtung im Browser
Jetzt https://git.meine-domain.de/ im Browser aufrufen. Beim ersten Mal zeigt Forgejo eine Einrichtungsseite. Die meisten Felder sind aus der app.ini schon vorbelegt. Wichtig sind:
- Datenbank: unverändert lassen (SQLite bzw. die PostgreSQL-Werte).
- Verwaltungskonto erstellen: ganz unten Benutzername, Passwort und E-Mail-Adresse für das erste Konto eintragen. Dieses Konto hat volle Rechte. Diesen Schritt nicht überspringen – sonst wird das erste selbst registrierte Konto zum Verwalter.
- Weitere Einstellungen (aufklappbar): Hier lässt sich „Selbstregistrierung deaktivieren" ankreuzen, damit sich nicht Fremde ein Konto anlegen können.
Nach einem Klick auf „Forgejo installieren" schreibt das Programm die vollständige app.ini und startet neu. Danach die Rechte an der Datei wieder eng setzen:
sudo chmod 640 /etc/forgejo/app.ini
sudo chmod 750 /etc/forgejo
Die Einrichtung ist damit abgeschlossen. Die Anmeldung erfolgt oben rechts mit dem eben angelegten Verwaltungskonto.
Schritt 9: Zugang über SSH (empfohlen)
Für das tägliche Arbeiten ist der Weg über SSH bequemer als über HTTPS, weil man kein Passwort und keinen Zugangs-Token eingeben muss. Forgejo nutzt dafür den vorhandenen SSH-Dienst des Servers und den Benutzer git.
In der Weboberfläche hinterlegt jede Person unter „Einstellungen → SSH-Schlüssel" ihren öffentlichen Schlüssel (die Datei ~/.ssh/id_ed25519.pub auf dem eigenen Rechner, siehe Allgemeine Einstellungen). Von da an funktioniert das Abliefern und Abholen ohne weitere Eingabe. Die Adresse eines Verzeichnisses sieht dann so aus:
git@git.meine-domain.de:redaktion/benutzerhandbuch.git
Aktualisieren
Forgejo besteht aus einer einzigen Programmdatei. Eine Aktualisierung heißt: neue Datei herunterladen, prüfen, austauschen, Dienst neu starten.
cd /tmp
VERSION=16.0.4 # neue Versionsnummer von forgejo.org/download
wget "https://code.forgejo.org/forgejo/forgejo/releases/download/v${VERSION}/forgejo-${VERSION}-linux-amd64"
wget "https://code.forgejo.org/forgejo/forgejo/releases/download/v${VERSION}/forgejo-${VERSION}-linux-amd64.asc"
gpg --verify "forgejo-${VERSION}-linux-amd64.asc" "forgejo-${VERSION}-linux-amd64"
sudo systemctl stop forgejo
sudo cp "forgejo-${VERSION}-linux-amd64" /usr/local/bin/forgejo
sudo chmod 755 /usr/local/bin/forgejo
sudo systemctl start forgejo
Vor einer Aktualisierung eine Sicherung anlegen. Forgejo bringt dafür einen Befehl mit, der Datenbank, Verzeichnisse und Konfiguration in eine einzige Datei packt:
sudo -u git forgejo dump -c /etc/forgejo/app.ini --work-path /var/lib/forgejo
Forgejo bleibt bei kleineren Versionssprüngen (etwa von 16.0 auf 16.1) verträglich. Vor einem großen Sprung (etwa von 15 auf 16) lohnt ein Blick in die Ankündigung auf https://forgejo.org/releases/, weil dort seltene Handgriffe vermerkt sind.
Fehlersuche
Wenn der Browser 502 Bad Gateway meldet, erreicht NGINX das Forgejo-Programm nicht. Den Grund nennt das Fehlerprotokoll:
sudo tail -n 20 /var/log/nginx/error.log
connect() to unix:/run/forgejo/forgejo.sock failed (13: Permission denied): Der Benutzerwww-dataist nicht in der Gruppegit, oder NGINX wurde nachusermodnur neu geladen statt neu gestartet.sudo systemctl restart nginx.connect() to unix:/run/forgejo/forgejo.sock failed (2: No such file or directory): Forgejo läuft nicht, oder die ErgänzungRuntimeDirectoryfehlt. Prüfen mitsystemctl status forgejoundls -l /run/forgejo/.invalid URL prefixbeimnginx -t: Beiproxy_passauf einen Socket fehlt dashttp://unix:am Anfang oder der Doppelpunkt vor dem Pfad innerhalb der Anwendung.
Weitere Anhaltspunkte liefert das Protokoll von Forgejo selbst:
sudo journalctl -u forgejo -f
- Falsche Links, Weiterleitungen ins Leere:
ROOT_URLin/etc/forgejo/app.inistimmt nicht mit der echten Adresse überein. Nach der Änderungsudo systemctl restart forgejo. - Der Zugang über SSH fragt nach einem Passwort: Der öffentliche Schlüssel ist in der Weboberfläche nicht (oder falsch) hinterlegt, oder der Benutzer
githat keine Anmelde-Shell (--shell /bin/bashin Schritt 3).
Für dieses Buch
Der Text dieses Buchs und der Aufbau der Kapitel gehören in ein Git-Verzeichnis, das die Redaktion gemeinsam pflegt. Forgejo ist dafür die richtige Größe: eine Programmdatei, eine Datenbank, ein Webserver davor – mehr braucht es nicht. Die Weboberfläche bündelt an einer Stelle, was sonst über E-Mails und Dateiordner verstreut wäre: Änderungsvorschläge, Anmerkungen, eine Liste offener Aufgaben.
Zwei Dinge gehören von Anfang an zum Betrieb: regelmäßige Sicherungen mit forgejo dump und zeitnahe Aktualisierungen, sobald eine neue Version erscheint. Weil Forgejo nur aus einer Datei besteht, ist beides schnell erledigt.
Wer die automatische Veröffentlichung des Buchs einrichten will (siehe Webseiten und Blogs), nutzt dafür Forgejo Actions: Bei jeder Änderung am Hauptzweig baut ein kurzer Ablauf das Buch und legt das Ergebnis auf dem Webserver ab.
Fazit
Git-Hosting ist die zentrale Stelle im Netz, an der alle Beteiligten ihre Änderungen an einem Git-Verzeichnis abliefern und abholen. Forgejo ist ein freies Programm dafür, getragen von einem gemeinnützigen Verein, entstanden als Abspaltung von Gitea. Es besteht aus einer einzigen ausführbaren Datei, braucht wenig Arbeitsspeicher und bietet dennoch Änderungsvorschläge, Aufgabenlisten, Pakete, ein Wiki und automatische Abläufe.
Die Einrichtung auf Ubuntu 26.04: die geprüfte Programmdatei nach /usr/local/bin/forgejo legen, einen eigenen Benutzer git anlegen, die Verzeichnisse /var/lib/forgejo und /etc/forgejo einrichten, eine kurze app.ini schreiben und den mitgelieferten systemd-Dienst starten. Die Verbindung zu NGINX läuft über einen Unix-Socket: In app.ini steht PROTOCOL = http+unix mit einem Pfad unter /run/forgejo, NGINX erreicht ihn über proxy_pass http://unix:/run/forgejo/forgejo.sock:/;, und www-data wird dafür in die Gruppe git aufgenommen. So steht für Forgejo kein Port offen, und der Zugriff hängt allein an Dateirechten.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Allgemeine Einstellungen
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Bevor auf dem Entwicklungs-Rechner – dem eigenen Computer, an dem gearbeitet wird – ein Editor eingerichtet oder die erste Programmiersprache installiert wird, sollte das System einmal grundlegend vorbereitet sein. Dieses Kapitel führt durch die Schritte, die für fast jedes spätere Kapitel die Grundlage bilden: das System aktualisieren, einige Hilfsbibliotheken einspielen, den Browser installieren, die Versionsverwaltung Git einrichten und den Zugang zum Passwortspeicher der Datenbank vorbereiten.
Als Grundlage dient wie im übrigen Buch Ubuntu. Alle Befehle werden in einem Terminal eingegeben – einem Fenster, in das man Anweisungen als Text tippt. Ein vorangestelltes sudo bedeutet: mit Verwaltungsrechten ausführen; das System fragt dann nach dem Passwort. Wer das Terminal noch nie geöffnet hat, findet es im Anwendungsmenü unter „Terminal" oder über die Tastenkombination Strg+Alt+T.
Die Reihenfolge der Abschnitte ist bewusst gewählt. Am besten arbeitet man sie einmal von oben nach unten ab.
System aktualisieren
Ein frisch installiertes Ubuntu ist selten auf dem neuesten Stand. Der erste Schritt bringt die Liste der verfügbaren Pakete und danach die installierte Software auf den aktuellen Stand:
# Die Liste der verfügbaren Pakete neu einlesen
sudo apt-get update
# Alle installierten Pakete auf die neueste Fassung bringen
sudo apt-get upgrade
apt-get ist das Programm, mit dem Ubuntu Software verwaltet – vergleichbar mit einem App-Laden, nur über die Tastatur bedient. Der Befehl update lädt dabei nur das Verzeichnis neu, upgrade installiert die Aktualisierungen tatsächlich. Bei upgrade fragt das System einmal nach, ob die aufgelisteten Änderungen ausgeführt werden sollen; mit J und Enter wird bestätigt.
Hilfsbibliotheken für den Passwortspeicher
Viele Entwicklerwerkzeuge – darunter Git und die KI-Agenten aus dem Kapitel Voraussetzungen – müssen Zugangsdaten speichern, damit man sie nicht bei jedem Schritt neu eintippt. Ubuntu hat dafür einen verschlüsselten Speicher, den Schlüsselbund (englisch keyring). Damit die Werkzeuge diesen Speicher nutzen können, wird die Bibliothek libsecret benötigt:
sudo apt install libsecret-1-0 libsecret-tools libsecret-1-dev libglib2.0-dev
Die vier Pakete haben unterschiedliche Aufgaben: libsecret-1-0 ist die eigentliche Bibliothek, libsecret-tools liefert das Kommando secret-tool zum Nachsehen, was gespeichert ist. Die Pakete mit -dev im Namen und libglib2.0-dev enthalten die Bauteile, mit denen sich das kleine Hilfsprogramm übersetzen lässt, das Git mit dem Schlüsselbund verbindet. Ohne diese Pakete lässt sich dieser Verbinder auf manchen Ubuntu-Fassungen nicht einrichten.
Zusätzliche Treiber
Ubuntu bringt für die meiste Hardware freie Treiber mit. Für einige Bauteile – vor allem Grafikkarten von Nvidia – gibt es zusätzlich Treiber des Herstellers, die mehr Leistung bringen. Dieser Befehl sucht die passenden heraus und installiert sie:
sudo ubuntu-drivers install
Nach der Installation ist ein Neustart des Rechners nötig, damit die neuen Treiber verwendet werden. Meldet der Befehl, dass keine zusätzlichen Treiber verfügbar sind, ist das kein Fehler – dann genügen die freien Treiber, und der Schritt kann übersprungen werden.
Google Chrome installieren
Ubuntu bringt den Browser Firefox bereits mit. Zusätzlich ist Google Chrome nützlich: Viele Weboberflächen werden vor allem in Chrome getestet, und für automatische Tests einer Webseite (siehe Webseiten und Blogs) wird oft Chrome im Hintergrund gesteuert.
Chrome liegt nicht in den Paketquellen von Ubuntu, sondern wird als einzelne Installationsdatei von Google geladen. Eine solche .deb-Datei ist die Installationsdatei für die Ubuntu-Familie, vergleichbar mit einer Setup-Datei unter Windows:
# In den Ordner für flüchtige Dateien wechseln
cd /tmp
# Die aktuelle Installationsdatei von Google herunterladen
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
# Die heruntergeladene Datei installieren
sudo dpkg -i google-chrome-stable_current_amd64.deb
wget lädt eine Datei aus dem Netz, dpkg -i spielt eine .deb-Datei ein. Beschwert sich dpkg über fehlende Bestandteile, holt der folgende Befehl sie nach und schließt die Installation ab:
sudo apt install -f
Bei der Installation trägt Chrome zusätzlich die Paketquelle von Google in das System ein. Neue Fassungen kommen dadurch später automatisch mit den übrigen Systemaktualisierungen.
Git einrichten
Git ist die Versionsverwaltung, mit der Änderungen an Dateien festgehalten und rückgängig gemacht werden können. Für dieses Buch ist es die Grundlage: Jedes Kapitel wird als Datei in einem Git-Verlauf gespeichert. Zusammen mit Git wird die GitHub CLI (gh) installiert – ein Zusatzwerkzeug, das die Arbeit mit dem Online-Dienst GitHub über das Terminal erledigt.
sudo apt-get install git gh
Nach der Installation trägt man einmalig seinen Namen und seine E-Mail-Adresse ein. Diese beiden Angaben schreibt Git in jede festgehaltene Änderung, damit später erkennbar ist, von wem sie stammt:
git config --global user.email "name@example.com"
git config --global user.name "Vorname Nachname"
--global bedeutet: Die Einstellung gilt für alle Projekte dieses Benutzers, nicht nur für ein einzelnes.
Anmeldung bei GitHub
Damit sich Git und gh mit dem eigenen GitHub-Konto verbinden können, meldet man sich einmal an:
gh auth login
Das Programm stellt dann einige Fragen: ob es um GitHub.com oder eine eigene Firmen-Installation geht, ob die Verbindung über HTTPS oder SSH laufen soll und ob die Anmeldung im Browser erfolgen darf. Für den Standardfall wählt man GitHub.com, HTTPS und die Anmeldung über den Browser. gh zeigt dann einen kurzen Zahlencode an, den man auf der geöffneten Webseite einträgt. Danach ist die Anmeldung dauerhaft gespeichert, und auch Git nutzt sie für den Zugriff auf die eigenen Projekte.
Passwort-Zugang zur Datenbank vorbereiten
Wer lokal mit der Datenbank PostgreSQL arbeitet (siehe Datenbank), muss sonst bei jedem Zugriff das Datenbank-Passwort eingeben. Das lässt sich mit einer kleinen Datei im persönlichen Ordner abkürzen. Sie heißt .pgpass – der Punkt am Anfang macht sie zu einer versteckten Datei:
nano ~/.pgpass
nano ist ein einfacher Editor im Terminal; ~ steht für den persönlichen Ordner. In die geöffnete Datei kommt eine Zeile nach diesem Muster:
localhost:5432:*:dein_benutzer:dein_passwort
Die fünf durch Doppelpunkte getrennten Felder bedeuten: Rechner, Anschlussnummer (bei PostgreSQL üblicherweise 5432), Datenbank (* steht für „alle"), Benutzername und Passwort. Gespeichert wird in nano mit Strg+O und Enter, geschlossen mit Strg+X.
PostgreSQL benutzt diese Datei nur, wenn sonst niemand sie lesen kann. Deshalb werden die Zugriffsrechte eng gesetzt:
chmod 0600 ~/.pgpass
0600 bedeutet: nur der Besitzer darf lesen und schreiben, sonst niemand. Fehlt dieser Schritt, weist PostgreSQL die Datei stillschweigend ab.
Sudo ohne Passwort (optional)
Bei der Arbeit auf dem Entwicklungs-Rechner fällt viel sudo an, und jedes Mal fragt das System nach dem Passwort. Man kann das für den eigenen Benutzer abschalten. Das ist bequem, senkt aber die Sicherheit spürbar: Jedes Programm, das unter dem eigenen Benutzer läuft, kann dann ohne Rückfrage Verwaltungsrechte erlangen. Auf einem Rechner, der nur zum Entwickeln dient und an dem sonst niemand arbeitet, ist das vertretbar – auf einem Server oder einem gemeinsam genutzten Rechner sollte man darauf verzichten.
Geändert wird die Einstellung mit einem eigenen Befehl, der die Konfigurationsdatei sicher öffnet und vor dem Speichern auf Fehler prüft:
sudo visudo
Am Ende der Datei wird eine Zeile ergänzt – dein_benutzername durch den eigenen Anmeldenamen ersetzen (der Befehl whoami zeigt ihn an):
dein_benutzername ALL=(ALL) NOPASSWD:ALL
Danach speichern und schließen. Öffnet visudo den Editor vi, der ungewohnt zu bedienen ist, hilft vorab die Umstellung auf nano:
sudo EDITOR=nano visudo
Wer die Bequemlichkeit möchte, ohne den vollen Verzicht auf die Passwortabfrage, kann NOPASSWD auch auf einzelne Befehle beschränken. Das sprengt aber den Rahmen dieses Kapitels und ist in der Regel nicht nötig.
Nächste Schritte
Das System ist jetzt vorbereitet. Danach folgen üblicherweise diese Kapitel:
- IDE – ein Programm zum Schreiben von Text und Code einrichten.
- Programmiersprachen – den Werkzeugkasten der benötigten Sprachen installieren.
- Docs-as-Code – wie die Kapitel dieses Buchs als Markdown-Dateien entstehen.
Fazit
Die Grundeinrichtung eines Entwicklungs-Rechners besteht aus wenigen Schritten: das System mit apt-get update und apt-get upgrade aktualisieren, mit libsecret den Zugang zum verschlüsselten Schlüsselbund schaffen, mit ubuntu-drivers install passende Treiber nachrüsten, Google Chrome als zweiten Browser installieren und Git samt GitHub CLI mit Namen, E-Mail und einmaliger Anmeldung einrichten. Eine .pgpass-Datei mit den Rechten 0600 erspart später die ständige Passworteingabe bei PostgreSQL. Das Abschalten der sudo-Passwortabfrage ist bequem, aber nur auf einem allein genutzten Entwicklungs-Rechner vertretbar.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
IDE
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Auf dem Entwicklungs-Rechner – dem eigenen Computer, an dem gearbeitet wird – braucht es ein Programm zum Schreiben und Ändern von Text und Code. Für dieses Buch ist das die Stelle, an der die Kapitel entstehen und an der ein KI-Agent wie Claude Code (siehe Voraussetzungen) mitarbeitet.
Ein solches Programm heißt Editor, wenn es vor allem Text bearbeitet, und IDE, wenn viele Hilfen fürs Programmieren fest eingebaut sind. „IDE" steht für „Integrated Development Environment", auf Deutsch „integrierte Entwicklungsumgebung": Editor, Fehlersuche, Versionsverwaltung und Werkzeuge zum Ausführen von Code stecken in einem einzigen Fenster. Der Übergang ist fließend – moderne Editoren lassen sich mit Erweiterungen so weit ausbauen, dass sie einer IDE nahekommen.
Dieses Kapitel zeigt, wie sich vier verbreitete Vertreter auf einem Rechner mit Ubuntu einrichten lassen: Visual Studio Code, die JetBrains-Programme, Zed und Vim. Ubuntu ist hier gewählt, weil es die größte Sammlung passender Anleitungen hat und weil der Rest des Buchs ebenfalls mit Ubuntu arbeitet (siehe Betriebssystem). Alle Befehle werden in einem Terminal eingegeben – einem Fenster, in das man Anweisungen als Text tippt. Ein vorangestelltes sudo bedeutet: mit Verwaltungsrechten ausführen; das System fragt dann nach dem Passwort.
Die vier Programme im Überblick
| Programm | Art | Grundlage | Besonders geeignet für |
|---|---|---|---|
| Visual Studio Code | Editor mit vielen Erweiterungen | frei nutzbar, von Microsoft | Der breite Standard; gute Anbindung an KI-Agenten |
| JetBrains (IntelliJ IDEA, PyCharm u. a.) | vollständige IDE | teils kostenlos, teils kostenpflichtig | Große Projekte in einer festen Programmiersprache |
| Zed | schneller Editor | quelloffen, in Rust geschrieben | Sehr schnelles Arbeiten; gemeinsames Bearbeiten |
| Vim | Editor für das Terminal | quelloffen, sehr alt und stabil | Arbeiten ganz ohne Maus, auch über eine Fernverbindung |
Man muss sich nicht auf ein Programm festlegen. Viele arbeiten mit einem Hauptprogramm und haben Vim zusätzlich für schnelle Änderungen auf dem Server.
Visual Studio Code
Visual Studio Code – kurz VS Code – ist der am weitesten verbreitete Editor dieser Art. Er ist kostenlos, läuft auf allen gängigen Betriebssystemen und lässt sich über einen eingebauten Laden mit Erweiterungen an fast jede Sprache und Aufgabe anpassen. Für dieses Buch ist wichtig: Für Claude Code gibt es eine fertige Erweiterung, sodass der KI-Agent ohne getrenntes Terminalfenster direkt im Editor arbeitet (siehe Voraussetzungen).
Installation über das .deb-Paket
Ein .deb-Paket ist die Installationsdatei für die Ubuntu-Familie – vergleichbar mit einer Setup-Datei unter Windows. Die aktuelle Datei wird von der offiziellen Seite code.visualstudio.com heruntergeladen (Schaltfläche „.deb", 64-Bit). Danach im Ordner mit der heruntergeladenen Datei:
sudo apt install ./code_*.deb
Der Punkt und der Schrägstrich vor dem Dateinamen sind wichtig: Sie sagen apt, dass eine Datei aus dem aktuellen Ordner gemeint ist und kein Paket aus dem Netz. Das Sternchen steht für den wechselnden Versionsteil im Dateinamen.
Bei der Installation trägt das Paket zusätzlich die Paketquelle von Microsoft in das System ein. Das hat einen praktischen Vorteil: Von da an kommen neue Fassungen von VS Code automatisch mit den übrigen Systemaktualisierungen, ohne dass man erneut eine Datei herunterladen muss.
sudo apt update
sudo apt upgrade
Gestartet wird der Editor über das Anwendungsmenü oder im Terminal mit code. Ein bestimmter Ordner öffnet sich mit code . – der Punkt steht für „der Ordner, in dem ich gerade bin".
Hinweis zur Snap-Fassung
Ubuntu bietet VS Code auch als Snap an – ein Paketformat von Canonical, bei dem das Programm stärker vom übrigen System abgeschottet läuft. Für VS Code führt diese Abschottung gelegentlich zu Reibung, etwa beim Zugriff auf andere Werkzeuge im Terminal. Das .deb-Paket ist deshalb die ruhigere Wahl.
Die JetBrains-Programme
JetBrains ist eine Firma, die für viele Programmiersprachen jeweils eine eigene, vollständige IDE anbietet: IntelliJ IDEA für Java und verwandte Sprachen, PyCharm für Python, WebStorm für Webentwicklung, CLion für C und C++, RustRover für Rust und weitere. Diese Programme nehmen einem viel Handarbeit ab – sie verstehen den Code tief, finden Fehler früh und benennen Dinge projektweit sicher um. Der Preis dafür: Sie brauchen mehr Arbeitsspeicher und starten langsamer als ein schlanker Editor. Einige Ausgaben (die „Community"-Fassungen von IntelliJ IDEA und PyCharm) sind kostenlos, die übrigen kosten eine jährliche Gebühr; für Lernende und quelloffene Projekte gibt es sie kostenfrei.
Installation über die Toolbox App
Der von JetBrains empfohlene Weg ist nicht, jede IDE einzeln zu installieren, sondern zuerst die Toolbox App. Das ist ein kleines Verwaltungsprogramm, über das sich alle JetBrains-IDEs mit einem Klick installieren, aktuell halten und wieder entfernen lassen. Es verwaltet auch mehrere Versionen nebeneinander und die Lizenzen.
Die Toolbox App wird von jetbrains.com/toolbox-app als .tar.gz-Archiv für Linux heruntergeladen – eine gepackte Datei, vergleichbar mit einem ZIP-Archiv. Danach im Ordner mit dem Download:
# Archiv in den Ordner /opt entpacken (dort liegen zusätzlich installierte Programme)
sudo tar -xzf jetbrains-toolbox-*.tar.gz -C /opt
# In den entpackten Ordner wechseln und das Programm einmalig starten
cd /opt/jetbrains-toolbox-*
./jetbrains-toolbox
Beim ersten Start trägt sich die Toolbox App selbst in das Anwendungsmenü ein; danach genügt der normale Programmstart. Über ihr Fenster wird dann die gewünschte IDE ausgewählt und installiert.
Startet die Toolbox App nicht und meldet einen Fehler zu „FUSE", fehlt eine Hilfsbibliothek zum Einbinden solcher Programmdateien. Sie wird mit einem Befehl nachgerüstet:
sudo apt install libfuse2t64
Einfachere Alternative über Snap
Wer nur eine einzige kostenlose IDE braucht und auf die Verwaltung über die Toolbox App verzichten kann, installiert sie direkt als Snap. Beispiel für die kostenlose Fassung von IntelliJ IDEA:
sudo snap install intellij-idea-community --classic
--classic erlaubt dem Programm den vollen Zugriff auf das System, den eine IDE braucht.
Zed
Zed ist ein neuerer Editor, der auf Geschwindigkeit ausgelegt ist. Er ist in der Programmiersprache Rust geschrieben, quelloffen und reagiert auch bei großen Dateien ohne spürbare Verzögerung. Eingebaut sind unter anderem das gemeinsame Bearbeiten einer Datei durch mehrere Personen in Echtzeit und eine Anbindung an KI-Modelle. Die Linux-Fassung kam 2024 dazu und wird seither stetig weiterentwickelt.
Installation über das offizielle Skript
JetBrains und VS Code werden als Paket installiert; Zed bringt ein eigenes Installationsskript mit. Der folgende Befehl lädt es herunter und führt es aus:
curl -f https://zed.dev/install.sh | sh
Das Skript legt Zed im persönlichen Ordner unter ~/.local ab – es sind also keine Verwaltungsrechte nötig, sudo entfällt hier. Ein solcher Befehl, der ein Skript aus dem Netz sofort ausführt, setzt Vertrauen in die Quelle voraus; das ist bei vielen Entwicklerwerkzeugen üblich (auch die KI-Agenten in Voraussetzungen werden so eingerichtet). Wer das Skript zuerst ansehen möchte, ruft https://zed.dev/install.sh im Browser auf und führt den Inhalt erst danach aus.
Nach der Installation wird der Editor mit zed gestartet, ein bestimmter Ordner mit zed .. Aktualisiert wird Zed von selbst; das Skript lässt sich zum Nachrüsten aber auch erneut ausführen.
Zed zeichnet seine Oberfläche über die Grafikschnittstelle Vulkan. Auf den meisten Ubuntu-Systemen ist die nötige Unterstützung vorhanden; fehlt sie, hilft:
sudo apt install mesa-vulkan-drivers
Vim
Vim ist ein Editor, der vollständig im Terminal läuft – ohne Fenster, ohne Maus, allein über die Tastatur. Das wirkt zunächst sperrig, hat aber einen handfesten Nutzen: Vim ist auf praktisch jedem Linux-Server bereits vorhanden, startet sofort und funktioniert auch über eine reine Textverbindung zu einem entfernten Rechner (SSH). Für schnelle Änderungen an einer Einstellungsdatei auf dem Server ist es deshalb das naheliegende Werkzeug, auch für alle, die sonst mit einem grafischen Editor arbeiten.
Installation
Ubuntu bringt nur eine abgespeckte Fassung mit. Die vollständige Fassung wird mit einem Befehl nachgeholt:
sudo apt update
sudo apt install vim
Gestartet wird der Editor mit vim gefolgt vom Dateinamen, zum Beispiel vim notiz.txt. Wichtig für den Anfang: Vim kennt verschiedene Zustände. Nach dem Start ist man im Normalmodus – Tastendrücke sind hier Befehle, kein Text. Mit der Taste i wechselt man in den Einfügemodus und schreibt wie gewohnt. Die Taste Esc führt in den Normalmodus zurück. Von dort speichert und beendet die Eingabe :wq gefolgt von Enter; ohne Speichern beendet :q!.
Eine eigene Einrichtung – Farben, Zeilennummern, Einrückung – kommt in die Datei ~/.vimrc im persönlichen Ordner. Sie ist beim ersten Mal leer und wird nach und nach ergänzt.
Neovim als moderne Fortführung
Aus Vim ist das Projekt Neovim hervorgegangen. Es ist mit Vim weitgehend gleich zu bedienen, aber innen aufgeräumt und leichter mit Erweiterungen auszubauen; viele fertige Einrichtungspakete bauen darauf. Ubuntu liefert eine aktuelle Fassung mit:
sudo apt install neovim
Gestartet wird es mit nvim. Wer die jeweils neueste Fassung möchte, fügt vorher die offizielle Paketquelle des Projekts hinzu:
sudo add-apt-repository ppa:neovim-ppa/stable
sudo apt update
sudo apt install neovim
Für dieses Buch
Für die Arbeit an diesem Handbuch wird Visual Studio Code empfohlen, installiert über das .deb-Paket. Der Grund ist die Zusammenarbeit mit dem KI-Agenten: Für Claude Code gibt es eine Erweiterung, die sich sauber in den Editor einfügt, und die meisten Anleitungen im Umfeld der KI-Agenten gehen von VS Code aus (siehe Voraussetzungen). Die Kapitel selbst sind einfache Markdown-Dateien (siehe Docs-as-Code), für die kein schweres Werkzeug nötig ist.
Zusätzlich lohnt es sich, Vim oder Neovim einzurichten – nicht als Hauptprogramm, sondern für schnelle Änderungen direkt auf dem Server, wo kein grafischer Editor zur Verfügung steht.
Eine vollständige JetBrains-IDE ist sinnvoll, sobald neben dem Buch ein größeres Programm in einer festen Sprache entsteht. Zed ist eine gute Wahl für alle, denen VS Code zu träge ist und die auf dessen großen Erweiterungsladen verzichten können.
Fazit
Auf dem Entwicklungs-Rechner braucht es ein Programm zum Bearbeiten von Text und Code. Visual Studio Code ist der breite Standard, wird über ein .deb-Paket installiert und hält sich danach über die Systemaktualisierungen selbst aktuell; für dieses Buch ist es wegen der Claude-Code-Erweiterung die erste Wahl. Die JetBrains-Programme sind vollständige Entwicklungsumgebungen für große Projekte und werden am besten über die Toolbox App verwaltet. Zed ist ein besonders schneller, quelloffener Editor und wird über ein offizielles Skript eingerichtet. Vim – oder seine Fortführung Neovim – läuft im Terminal, ist auf jedem Server vorhanden und deshalb für schnelle Änderungen über eine Fernverbindung unverzichtbar.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Programmiersprachen
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Auf dem Entwicklungs-Rechner – dem eigenen Computer, an dem gearbeitet wird – entsteht der Code. Damit man Code schreiben, ausprobieren und in ein fertiges Programm übersetzen kann, muss für jede Programmiersprache ihr Werkzeugkasten installiert sein. Dieser Werkzeugkasten besteht meist aus drei Teilen: dem Programm, das den Code ausführt oder übersetzt, einer Sammlung fertiger Bausteine und einem Paketwerkzeug, das weitere Bausteine aus dem Internet nachlädt.
Das Kapitel Laufzeitumgebung beschreibt das Gegenstück auf dem Server: Dort wird nur die schlanke Laufzeit eingerichtet, mit der fertige Programme betrieben werden. Auf dem Entwicklungs-Rechner ist es umgekehrt – hier braucht man die vollständige Entwicklungsausstattung, weil man Software nicht nur laufen lässt, sondern selbst baut.
Dieses Kapitel zeigt für acht verbreitete Sprachen, wie man ihren Werkzeugkasten auf einem Rechner mit Ubuntu einrichtet: Python, Java, C und C++, Go, Node.js, Rust, .NET und PHP. Ubuntu ist hier gewählt, weil der Rest des Buchs ebenfalls damit arbeitet (siehe IDE und Betriebssystem). Alle Befehle werden in einem Terminal eingegeben – einem Fenster, in das man Anweisungen als Text tippt. Ein vorangestelltes sudo bedeutet: mit Verwaltungsrechten ausführen; das System fragt dann nach dem Passwort.
Ein gemeinsames Hilfsmittel vorab: curl
Mehrere der folgenden Installationen laden Dateien aus dem Netz. Dafür wird das kleine Werkzeug curl benötigt. Es ist mit einem Befehl eingerichtet und danach für alle weiteren Schritte vorhanden:
sudo apt update
sudo apt install curl
Laufzeit oder volle Ausstattung
Bei einigen Sprachen gibt es zwei Pakete: die reine Laufzeit zum Betreiben fertiger Programme und die volle Ausstattung zum Entwickeln. Bei Java heißt die volle Ausstattung JDK (Java Development Kit), bei .NET SDK (Software Development Kit). Auf dem Entwicklungs-Rechner wählt man immer die volle Ausstattung – sie enthält den Übersetzer, die Fehlersuche und die Werkzeuge, die zum Bauen nötig sind. Die schlanke Laufzeit ist nur für den Server gedacht.
Python
Python ist eine Sprache, die auf gut lesbaren Code setzt. Sie wird oft für kurze Hilfsprogramme, Auswertungen und Automatisierung genommen und ist im KI-Umfeld die vorherrschende Sprache. Python-Code wird nicht vorab übersetzt, sondern von einem Ausführer Zeile für Zeile abgearbeitet.
Ubuntu bringt Python 3 bereits mit, aber ohne die üblichen Zusatzteile. Diese werden nachinstalliert:
# python3-pip ist das Paketwerkzeug, python3-venv legt abgetrennte Umgebungen an;
# python-is-python3 sorgt dafür, dass der Befehl "python" Python 3 startet
sudo apt install python3 python3-pip python3-venv python-is-python3
# Zeigt die installierte Version zur Kontrolle an
python --version
Eine Besonderheit von Python sollte man kennen: Zusätzliche Bausteine werden nicht für den ganzen Rechner installiert, sondern in einer abgetrennten Umgebung je Projekt, einer sogenannten virtuellen Umgebung. Das verhindert, dass zwei Projekte sich mit unterschiedlichen Versionen desselben Bausteins ins Gehege kommen. Angelegt und eingeschaltet wird eine solche Umgebung im Projektordner mit:
python -m venv .venv
source .venv/bin/activate
Solange die Umgebung eingeschaltet ist, landet jedes pip install nur in diesem einen Ordner. Neuere Ubuntu-Ausgaben bestehen sogar darauf: Ein pip install außerhalb einer virtuellen Umgebung wird abgewiesen.
Java
Java ist eine der ältesten noch weit verbreiteten Sprachen für Server. Java-Code wird nicht für einen bestimmten Rechnertyp übersetzt, sondern in eine Zwischenform, die auf jedem Betriebssystem dieselbe Laufzeitumgebung ausführt – die Java Virtual Machine. Dadurch läuft dasselbe Programm unverändert auf Windows, Linux und macOS.
Die freie Ausgabe von Java heißt OpenJDK. Zum Entwickeln wird das vollständige JDK installiert, nicht die abgespeckte Laufzeit:
# Vollständiges Entwicklungspaket ("jdk"), Fassung ohne grafische Bestandteile ("headless")
sudo apt install openjdk-26-jdk-headless
# Zeigt die installierte Version zur Kontrolle an
javac -version
Wer eine bestimmte ältere Java-Version für ein Projekt braucht, kann mehrere Fassungen nebeneinander installieren und mit dem Befehl sudo update-alternatives --config java zwischen ihnen umschalten.
Für größere Java-Projekte kommt zusätzlich ein Bauwerkzeug dazu, das den Ablauf vom Quellcode zum fertigen Programm steuert und Bausteine nachlädt. Verbreitet sind Maven und Gradle:
sudo apt install maven
C und C++
C und C++ sind hardwarenahe Sprachen. Ihr Code wird vollständig in Maschinenbefehle für genau einen Rechnertyp übersetzt und läuft danach ohne Laufzeitumgebung allein. Diese Übersetzung erledigt ein Compiler. Viele grundlegende Systemprogramme und Bibliotheken sind in C oder C++ geschrieben; auch andere Sprachen greifen beim Bauen oft auf einen C-Compiler zurück.
Ubuntu fasst die nötigen Werkzeuge im Sammelpaket build-essential zusammen. Dazu kommen üblicherweise noch CMake als Bauwerkzeug und gdb zur Fehlersuche:
# Compiler (gcc/g++), Binder und Standard-Werkzeuge zum Bauen
sudo apt install build-essential
# Bauwerkzeug, das große C/C++-Projekte plattformübergreifend steuert
sudo apt install cmake
# Debugger: hält ein laufendes Programm an und zeigt seinen Zustand
sudo apt install gdb
Nach der Installation steht der Compiler als Befehl gcc (für C) und g++ (für C++) bereit. Ein gcc --version zeigt die Fassung an.
Go
Go – auch Golang genannt – ist eine Sprache von Google, die auf einfache Sprachregeln und schnelles Übersetzen setzt. Wie bei C entsteht am Ende eine eigenständige Datei, die ohne Laufzeitumgebung läuft. Viele moderne Server- und Kommandozeilenwerkzeuge sind in Go geschrieben.
Die Fassung in den Ubuntu-Paketquellen ist oft mehrere Versionen alt. Für die Entwicklung lädt man Go darum direkt von der offiziellen Seite. Die aktuelle Versionsnummer steht auf go.dev/dl; im folgenden Beispiel ist es 1.26.5:
cd $HOME
# Eine eventuell vorhandene ältere Installation entfernen
sudo rm -rf /usr/local/go
# Das offizielle Archiv herunterladen
wget https://go.dev/dl/go1.26.5.linux-amd64.tar.gz
# Nach /usr/local entpacken; dort erwartet Go seine Dateien
sudo tar -C /usr/local -xzf go1.26.5.linux-amd64.tar.gz
Damit das Terminal den Befehl go findet, muss der Ordner mit den Go-Programmen in die Liste der Suchpfade (PATH) aufgenommen werden. Diese drei Zeilen ergänzen die persönliche Startdatei ~/.bashrc, die bei jeder neuen Terminal-Sitzung gelesen wird:
# Ort des go-Befehls bekannt machen
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
# GOPATH ist der Ordner, in dem Go heruntergeladene Bausteine und selbst
# gebaute Programme ablegt
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc
# Die geänderte Startdatei sofort für die laufende Sitzung übernehmen
source ~/.bashrc
# Zeigt die installierte Version zur Kontrolle an
go version
Node.js
JavaScript war ursprünglich nur die Sprache im Webbrowser. Node.js löst diese Sprache vom Browser und macht sie zu einer vollwertigen Laufzeitumgebung für Werkzeuge und Server. Das zugehörige Paketwerkzeug heißt npm. Sehr viele Entwicklerwerkzeuge – auch solche, die man nur nebenbei benutzt – sind auf Node.js gebaut.
Auf dem Entwicklungs-Rechner verlangen verschiedene Projekte oft verschiedene Node.js-Versionen. Darum installiert man hier nicht das Systempaket, sondern den Node Version Manager (nvm). Er wird für den eigenen Benutzer eingerichtet, nicht für den ganzen Rechner, und hält mehrere Node.js-Versionen nebeneinander vor:
# Installationsskript von nvm herunterladen und ausführen
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
# nvm in der laufenden Sitzung verfügbar machen (sonst hilft ein neues Anmelden)
\. "$HOME/.nvm/nvm.sh"
# Eine Node.js-Version installieren und benutzen
nvm install 25
nvm use 25
# Zeigt die Versionen von Node.js und npm zur Kontrolle an
node -v
npm -v
Hinweis: Ein Skript aus dem Internet direkt auszuführen, sollte man nur bei Quellen tun, denen man vertraut. Wer sichergehen will, ruft die Adresse zuerst im Browser auf, liest den Inhalt und führt ihn erst danach aus.
Für ein Projekt, das lange gepflegt werden soll, wählt man eine Version mit gerader Nummer (24, 26, …); nur diese erhalten über Jahre Sicherheitsupdates. Ungerade Nummern sind kurzlebige Zwischenausgaben.
Rust
Rust ist eine jüngere hardwarenahe Sprache. Sie erzeugt wie C eigenständige Programme, verhindert aber schon beim Übersetzen eine ganze Klasse von Speicherfehlern. Der Editor Zed aus dem Kapitel IDE ist ein Beispiel für ein größeres Programm in Rust.
Rust wird nicht über die Ubuntu-Paketquellen eingerichtet, sondern über das offizielle Verwaltungsprogramm rustup. Es installiert den Compiler und das Paketwerkzeug Cargo in den persönlichen Ordner – Verwaltungsrechte sind nicht nötig, sudo entfällt hier:
# Installationsskript von rustup herunterladen und ausführen
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Das Skript fragt nach der gewünschten Einrichtung; für den Standard genügt die Eingabetaste. Danach muss das Terminal einmal neu geöffnet oder die Startdatei neu gelesen werden:
source "$HOME/.cargo/env"
# Zeigt die installierten Versionen zur Kontrolle an
rustc --version
cargo --version
Aktualisiert wird Rust später mit rustup update.
.NET
.NET (gesprochen „dot net") ist die Programmierplattform von Microsoft, seit einigen Jahren quelloffen und auch für Linux verfügbar. Damit werden vor allem Webanwendungen und Kommandozeilenwerkzeuge in der Sprache C# gebaut.
Zum Entwickeln wird das vollständige SDK installiert. Auf Ubuntu 26.04 liegen die .NET-Pakete direkt in den Paketquellen des Systems; eine zusätzliche Paketquelle von Microsoft ist nicht mehr nötig:
sudo apt update
sudo apt install -y dotnet-sdk-10.0
# Zeigt die installierten Fassungen zur Kontrolle an
dotnet --info
Die Zahl 10.0 benennt die Hauptversion. .NET 10 hat eine lange Pflegezusage („LTS") und ist darum die richtige Wahl für ein Projekt, das ruhig laufen soll.
Viele Aufgaben erledigen kleine Zusatzwerkzeuge, die als globale Werkzeuge nachinstalliert werden – etwa dotnet-ef für Datenbank-Änderungen. Sie landen im Ordner ~/.dotnet/tools, der ebenfalls in die Liste der Suchpfade aufgenommen werden muss:
dotnet tool install --global dotnet-ef
dotnet tool install --global dotnet-aspnet-codegenerator
dotnet tool install --global Microsoft.Web.LibraryManager.Cli
# Ordner mit den globalen Werkzeugen bekannt machen und sofort übernehmen
echo 'export PATH=$HOME/.dotnet/tools:$PATH' >> ~/.bashrc
source ~/.bashrc
PHP
PHP ist die Sprache, in der ein großer Teil des Webs geschrieben ist – darunter MediaWiki, die Grundlage der Wissenssammlung dieses Buchs (siehe Wissenssystem). Wer an solchen Anwendungen arbeitet oder eigene Erweiterungen dafür schreibt, braucht PHP auch auf dem Entwicklungs-Rechner.
Damit sich die Umgebung wie auf dem Server verhält, installiert man dieselben Bestandteile: die Ausführungsart PHP-FPM für den Betrieb hinter einem Webserver, die Kommandozeilen-Fassung php-cli zum Testen und die üblichen Erweiterungen. Die Paketnamen ohne Versionsnummer ziehen automatisch die Fassung, die Ubuntu mitbringt:
sudo apt install php-fpm php-cli \
php-pgsql php-xml php-mbstring php-curl php-gd php-zip php-intl php-xmlrpc php-opcache
# Zeigt die installierte Version zur Kontrolle an
php -v
Die einzelnen php-*-Pakete sind Erweiterungen: php-pgsql verbindet PHP mit der Datenbank PostgreSQL, php-mbstring behandelt Texte mit Umlauten korrekt, php-gd verkleinert Bilder, und so fort. Welche eine Anwendung erwartet, nennt sie in ihrer Installationsprüfung.
Zum Entwickeln lohnt sich eine Datenbank auf demselben Rechner. PostgreSQL wird mit einem Befehl eingerichtet:
sudo apt install postgresql
Zusätzliche PHP-Bausteine verwaltet das Werkzeug Composer. Seine Einrichtung ist im Kapitel Laufzeitumgebung beschrieben und funktioniert auf dem Entwicklungs-Rechner genauso.
Kurzvergleich
| Sprache | Paket zum Entwickeln (Ubuntu) | Übersetzt zu | Paketwerkzeug |
|---|---|---|---|
| Python 3 | python3 python3-pip python3-venv | wird direkt ausgeführt | pip (in virtueller Umgebung) |
| Java | openjdk-26-jdk-headless | Zwischenform für die Java Virtual Machine | Maven, Gradle |
| C / C++ | build-essential cmake gdb | eigenständige Datei je Rechnertyp | – (oft über CMake) |
| Go | Archiv von go.dev | eigenständige Datei je Rechnertyp | go (eingebaut) |
| Node.js | über nvm | wird direkt ausgeführt | npm |
| Rust | über rustup | eigenständige Datei je Rechnertyp | Cargo |
| .NET (C#) | dotnet-sdk-10.0 | Zwischenform für die .NET-Laufzeit | NuGet |
| PHP | php-fpm php-cli + Erweiterungen | wird direkt ausgeführt | Composer |
Für dieses Buch
Für die Arbeit am Handbuch selbst wird keine dieser Sprachen zwingend gebraucht – die Kapitel sind einfache Markdown-Dateien (siehe Docs-as-Code). Sobald aber ein eigenes Programm oder eine Erweiterung für MediaWiki entsteht, richtet man den passenden Werkzeugkasten ein.
Zwei Grundsätze helfen, den Entwicklungs-Rechner übersichtlich zu halten. Erstens: Versionen, die schnell wechseln – vor allem Node.js, aber auch Go und Rust –, verwaltet man über das jeweilige eigene Werkzeug (nvm, die Neuinstallation von Go, rustup), nicht über die Systempaketquellen. So lassen sich mehrere Fassungen nebeneinander halten und einzeln aktualisieren. Zweitens: Wer mit Containern arbeitet (siehe Containerisierung von Software), kann den Werkzeugkasten einer Sprache auch ganz in einen Container legen und den eigenen Rechner sauber halten.
Fazit
Auf dem Entwicklungs-Rechner braucht jede Programmiersprache ihren vollständigen Werkzeugkasten: den Übersetzer oder Ausführer, fertige Bausteine und ein Paketwerkzeug. Python und PHP kommen weitgehend aus den Ubuntu-Paketquellen, Java, C/C++ und .NET ebenfalls, wobei man dort das volle Entwicklungspaket (JDK, build-essential, SDK) statt der schlanken Laufzeit wählt. Go lädt man direkt von der offiziellen Seite, Node.js über nvm und Rust über rustup – diese drei, weil sich ihre Versionen häufig ändern und man mehrere Fassungen nebeneinander benötigt. Für den Server gilt das Gegenteil: Dort wird nur die schlanke Laufzeit eingerichtet, wie im Kapitel Laufzeitumgebung beschrieben.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Unix-Socket
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Viele Dienste auf einem Server nehmen Verbindungen nicht über einen Netzwerk-Port entgegen, sondern über eine Socket-Datei – einen sogenannten Unix-Socket. Das Kapitel XWiki einrichten zeigt das an einem Beispiel: Statt auf Port 9000 kann der Anwendungsserver Tomcat auch über die Datei /var/lib/tomcat10/xwiki.sock ansprechbar sein. Der Webserver NGINX, der auf demselben Rechner läuft, kommt damit gut zurecht.
Beim Testen vom Entwicklungs-Rechner aus entsteht dann aber ein Problem: Ein Browser, das Werkzeug curl in einer älteren Fassung oder ein grafisches Datenbank-Programm sprechen nur über Ports, nicht über Socket-Dateien. Dieses Kapitel erklärt, was ein Unix-Socket ist, und zeigt, wie man mit einem einzigen Befehl eine Brücke von einem Port zu einer Socket-Datei baut – lokal auf dem Server und über eine verschlüsselte Verbindung bis auf den eigenen Rechner.
Alle Befehle werden in einem Terminal eingegeben – einem Fenster, in das man Anweisungen als Text tippt. Ein vorangestelltes sudo bedeutet: mit Verwaltungsrechten ausführen.
Was ein Unix-Socket ist
Wenn zwei Programme miteinander reden, brauchen sie einen gemeinsamen Kanal. Der bekannte Weg ist ein Netzwerk-Port: Ein Programm lauscht auf einer Nummer wie 9000, ein anderes verbindet sich mit 127.0.0.1:9000. Das funktioniert auch dann, wenn die beiden Programme auf verschiedenen Rechnern laufen.
Ein Unix-Socket ist der zweite Weg. Statt einer Portnummer gibt es eine Datei im Dateisystem, zum Beispiel /var/lib/tomcat10/xwiki.sock. Ein Programm lauscht an dieser Datei, ein anderes verbindet sich mit ihr. Beide müssen dafür auf demselben Rechner laufen – die Datei liegt ja auf genau einer Festplatte.
Der Name kommt daher, dass diese Technik aus der Unix-Welt stammt; genauer heißt sie Unix Domain Socket. Die Socket-Datei ist keine gewöhnliche Datei mit Inhalt. Sie ist nur ein Treffpunkt: Wer sie öffnet, landet bei dem Programm, das dort lauscht. Öffnet man sie versehentlich mit einem Texteditor, sieht man nichts Sinnvolles.
Zwei Eigenschaften machen den Unix-Socket für Server attraktiv:
- Kein offener Port. Ein Port kann aus Versehen für das ganze Netz geöffnet werden. Eine Socket-Datei kann das nicht – sie ist grundsätzlich nur auf demselben Rechner erreichbar.
- Zugriff über Dateirechte. Wer die Socket-Datei benutzen darf, regeln dieselben Lese- und Schreibrechte wie bei jeder anderen Datei. Im XWiki-Beispiel sorgt
rw-rw----dafür, dass nur der Tomcat-Benutzer und die Gruppe des Webservers an den Socket kommen.
Verbreitet sind Unix-Sockets unter anderem bei PostgreSQL (/var/run/postgresql/.s.PGSQL.5432), bei PHP-FPM (/run/php/php8.5-fpm.sock, siehe MediaWiki einrichten), bei Docker (/var/run/docker.sock) und eben bei Tomcat.
Das Problem beim Testen
Solange alle beteiligten Programme auf dem Server liegen, ist der Unix-Socket kein Hindernis. NGINX erreicht PHP-FPM und Tomcat problemlos über deren Socket-Dateien.
Beim Entwickeln will man den Dienst aber oft direkt ansehen, bevor der Webserver davorsteht – zum Beispiel den Einrichtungsassistenten von XWiki einmal im Browser durchklicken. Dann sollen Werkzeuge auf den Dienst zugreifen, die nur Ports kennen:
- ein Browser öffnet
http://localhost:9000/, aber niemals eine Socket-Datei - ältere Fassungen von
curlkönnen keine Unix-Sockets ansprechen - grafische Datenbank-Programme wie DBeaver oder pgAdmin erwarten Wirtsname und Portnummer
In all diesen Fällen fehlt ein Zwischenstück, das auf einer Seite einen Port anbietet und auf der anderen Seite die Socket-Datei benutzt. Genau das leistet socat.
socat: die Brücke in einem Befehl
socat (kurz für „socket cat") ist ein kleines Kommandozeilen-Werkzeug, das zwei Datenkanäle miteinander verbindet und alles, was auf der einen Seite hereinkommt, unverändert an die andere Seite weitergibt. Die beiden Seiten dürfen von ganz verschiedener Art sein – ein Port hier, eine Datei dort.
Installiert wird es aus den Paketquellen von Ubuntu:
sudo apt update
sudo apt install socat
Um einen lokalen Port 9000 mit der XWiki-Socket-Datei zu verbinden:
socat TCP-LISTEN:9000,bind=127.0.0.1,fork,reuseaddr \
UNIX-CONNECT:/var/lib/tomcat10/xwiki.sock
Solange dieser Befehl läuft, nimmt socat auf Port 9000 Verbindungen an und leitet sie an die Socket-Datei weiter. Ein Aufruf von http://127.0.0.1:9000/ landet dann bei Tomcat. Mit Strg+C wird socat wieder beendet; danach ist der Port geschlossen.
Die Bestandteile des Befehls
socat bekommt genau zwei Adressen. Die erste beschreibt, wo Verbindungen hereinkommen, die zweite, wohin sie gehen sollen. An jede Adresse werden mit Komma weitere Angaben angehängt.
| Baustein | Bedeutung |
|---|---|
TCP-LISTEN:9000 | auf dem Netzwerk-Port 9000 auf Verbindungen warten |
bind=127.0.0.1 | dabei nur auf dem Rechner selbst erreichbar sein, nicht im Netz |
fork | für jede neue Verbindung einen eigenen Ableger starten, damit mehrere gleichzeitig möglich sind |
reuseaddr | den Port sofort wieder benutzen dürfen, ohne kurze Wartezeit nach dem Beenden |
UNIX-CONNECT:/var/lib/tomcat10/xwiki.sock | sich mit dieser Socket-Datei verbinden |
bind=127.0.0.1 ist wichtig. Ohne diese Angabe würde socat den Port auf allen Netzwerk-Adressen öffnen und damit den Unix-Socket, der eigentlich vor dem Netz geschützt ist, für Fremde erreichbar machen. Der Zusatz sorgt dafür, dass die Brücke nur auf dem Server selbst existiert.
fork fehlt in vielen kurzen Beispielen, wird aber fast immer gebraucht: Ohne fork bedient socat genau eine Verbindung und beendet sich danach. Ein Browser öffnet für eine einzige Seite oft mehrere Verbindungen parallel – ohne fork bricht das sofort ab.
Die Richtung umdrehen
Der umgekehrte Fall kommt ebenfalls vor: Ein Werkzeug spricht nur über eine Socket-Datei, der Dienst hört aber auf einem Port. Dann werden die beiden Adressen einfach getauscht:
socat UNIX-LISTEN:/tmp/meine.sock,fork,reuseaddr \
TCP-CONNECT:127.0.0.1:9000
socat legt dabei die Datei /tmp/meine.sock an und reicht alles, was dort ankommt, an Port 9000 weiter. Nach dem Beenden bleibt die Datei manchmal liegen und muss mit rm /tmp/meine.sock entfernt werden.
Bis auf den eigenen Rechner: SSH-Tunnel
Die socat-Brücke hilft auf dem Server. Auf dem Entwicklungs-Rechner ist der Server-Socket damit aber noch nicht erreichbar. Dafür sorgt ein SSH-Tunnel – dieselbe Technik, die das Kapitel XWiki einrichten für den Port 9000 verwendet.
Moderne Fassungen von OpenSSH (ab Version 6.7, auf aktuellem Ubuntu immer gegeben) können am entfernten Ende eines Tunnels statt eines Ports auch eine Socket-Datei ansprechen:
ssh -L 9000:/var/lib/tomcat10/xwiki.sock admin@SERVER-IP
Der Teil -L 9000:/var/lib/tomcat10/xwiki.sock öffnet auf dem eigenen Rechner den Port 9000 und verbindet ihn durch die verschlüsselte SSH-Verbindung direkt mit der Socket-Datei auf dem Server. Ein socat auf dem Server ist in diesem Fall gar nicht nötig. Solange das SSH-Fenster offen ist, landet jeder Aufruf von http://localhost:9000/ im Browser des eigenen Rechners bei Tomcat.
socat auf dem Server und der SSH-Tunnel lösen also dieselbe Aufgabe an zwei verschiedenen Stellen. Wenn SSH die Socket-Datei direkt ansprechen kann, ist der Tunnel allein die einfachere Wahl. socat bleibt nützlich, wenn auf dem Server selbst ein Werkzeug an den Socket soll oder wenn eine ältere SSH-Fassung im Spiel ist.
Andere Wege zum selben Ziel
socat ist die kürzeste Lösung für den schnellen Test. Für den Dauerbetrieb gibt es solidere Möglichkeiten.
| Werkzeug | Einsatz | Anmerkung |
|---|---|---|
| socat | schneller Test im Terminal | ein Befehl, läuft nur, solange das Fenster offen ist |
SSH-Tunnel (ssh -L) | Zugriff vom eigenen Rechner | verschlüsselt, kein zusätzliches Programm auf dem Server |
systemd-socket-proxyd | dauerhafte Brücke auf dem Server | wird als Dienst eingerichtet, startet nach einem Neustart von selbst wieder |
NGINX (stream-Baustein) | dauerhafte Brücke, wenn NGINX ohnehin läuft | ein kleiner stream { … }-Abschnitt in der Konfiguration |
ncat (aus dem Nmap-Paket) | Ersatz für socat, falls dieses fehlt | Aufruf etwas umständlicher |
Für eine Brücke, die dauerhaft bestehen soll, ist ein per systemd eingerichteter Dienst der richtige Weg. Ein socat-Befehl im Terminal ist dagegen als Wegwerf-Lösung für einen einzelnen Testlauf gedacht.
Fehlersuche
Connection refusedbeim Verbinden mit dem Port:socatläuft nicht oder hört auf einem anderen Port. Prüfen mitss -tlnp | grep 9000.socat: … Permission deniedbeiUNIX-CONNECT: Der Benutzer, dersocatstartet, darf die Socket-Datei nicht benutzen. Die Rechte zeigtls -l /var/lib/tomcat10/xwiki.sock. Meist hilft es,socatmitsudooder als der Benutzer des Dienstes zu starten.socat: … No such file or directory: Der Pfad zur Socket-Datei stimmt nicht, oder der Dienst läuft nicht und hat den Socket deshalb nicht angelegt.- Die erste Seite lädt, weitere Anfragen hängen: Die Angabe
forkfehlt. Den Befehl mit,forkan der ersten Adresse neu starten.
Für dieses Buch
Für die Einrichtung von XWiki (siehe XWiki einrichten) reicht in fast allen Fällen der SSH-Tunnel auf die Socket-Datei aus – er braucht kein zusätzliches Programm auf dem Server und ist verschlüsselt.
socat ist das Mittel der Wahl, wenn direkt auf dem Server ein Werkzeug an einen Unix-Socket muss – etwa curl für einen kurzen Test – oder wenn die Socket-Datei aus einem anderen Grund kurz als Port erreichbar sein soll. Der Befehl läuft nur, solange das Terminal-Fenster offen ist; danach ist der Port wieder zu. Für eine dauerhafte Brücke wird stattdessen ein systemd-Dienst oder der stream-Baustein von NGINX eingerichtet.
Fazit
Ein Unix-Socket ist ein Treffpunkt für zwei Programme auf demselben Rechner in Form einer Datei im Dateisystem – ohne Port, mit Zugriffsschutz über die Dateirechte. Viele Serverdienste bieten sich so an. Werkzeuge wie Browser oder grafische Datenbank-Programme sprechen dagegen nur über Ports. socat baut die Brücke in einem einzigen Befehl: TCP-LISTEN auf der einen Seite, UNIX-CONNECT auf der anderen, dazu bind=127.0.0.1 für die Beschränkung auf den Rechner selbst und fork für mehrere gleichzeitige Verbindungen. Vom eigenen Rechner aus erreicht ein SSH-Tunnel die Socket-Datei auf dem Server sogar ohne Zusatzprogramm. Für den Dauerbetrieb übernehmen systemd-socket-proxyd oder NGINX dieselbe Aufgabe zuverlässiger.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Docs-as-Code
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Dieses Buch ist selbst nach dem Verfahren entstanden, um das es in diesem Kapitel geht. Jedes Kapitel ist eine einfache Textdatei im Format Markdown unter dem Ordner src/. Aus diesen Dateien baut ein kleines Programm die fertigen HTML-Seiten. Die Textdateien liegen in einer Versionsverwaltung, jede Änderung ist nachvollziehbar, und der Bau läuft automatisch. Dieses Vorgehen heißt Docs-as-Code – auf Deutsch etwa „Dokumentation wie Programmcode".
Das Kapitel erklärt, was Docs-as-Code ist, was „robust" in diesem Zusammenhang bedeutet, und stellt die wichtigsten Gruppen von Werkzeugen vor: Buch-Generatoren, Dokumentations-Frameworks, Notizbuch-Systeme mit ausführbarem Code, Generatoren für lokale Notizsammlungen sowie die neueren Ansätze mit Künstlicher Intelligenz. Bei jeder Gruppe geht es besonders um die Frage, welche Werkzeuge als ausgereift gelten und auch sehr große Textmengen zuverlässig verarbeiten.
Was Docs-as-Code ist
Programmierer schreiben ihren Code als reinen Text, legen ihn in eine Versionsverwaltung, lassen Änderungen von Kollegen prüfen und bauen daraus mit einem festen Ablauf ein lauffähiges Programm. Docs-as-Code überträgt genau diesen Ablauf auf Dokumentation. Fünf Bausteine gehören dazu:
- Reiner Text als Quelle. Der Inhalt wird in einer einfachen Auszeichnungssprache geschrieben – meist Markdown, seltener AsciiDoc oder reStructuredText. Das sind Textdateien, die man mit jedem Editor öffnen kann. Formatierung wie Überschriften oder Listen steht als Zeichen im Text (
# Überschrift,- Listenpunkt), nicht in einem unsichtbaren Format wie bei einem Textverarbeitungsprogramm. - Versionsverwaltung mit Git. Jede Änderung wird gespeichert, mit Datum, Verfasser und einer kurzen Beschreibung. Man kann jederzeit sehen, was sich zwischen zwei Ständen geändert hat, und zu einem alten Stand zurückkehren.
- Prüfung vor der Übernahme. Änderungen laufen über einen sogenannten Merge Request oder Pull Request: Erst schlägt jemand eine Änderung vor, dann sieht ein anderer sie durch und übernimmt sie. So wie bei einem Vier-Augen-Prinzip.
- Automatischer Bau. Sobald eine Änderung übernommen ist, baut ein Server ohne weiteres Zutun die Webseite neu. Dieser Ablauf heißt CI/CD (englisch für „fortlaufende Integration und Auslieferung").
- Ein Generator erzeugt die Ausgabe. Ein Programm, der Static-Site-Generator (Generator für statische Webseiten), macht aus den Textdateien fertige HTML-Seiten, oft auch eine PDF- oder E-Book-Fassung. „Statisch" heißt: Es entstehen einfache Dateien, die jeder Webserver ohne Datenbank ausliefern kann.
Der Nutzen: Der Text gehört einem selbst und steckt nicht in einem fremden Dienst fest. Man kann ihn durchsuchen, mit anderen Ständen vergleichen, offline bearbeiten und mit denselben Werkzeugen verwalten wie Code. Der Nachteil: Man muss den Umgang mit Git lernen, und es gibt keine Oberfläche, in der man den Text wie in einem Textverarbeitungsprogramm formatiert sieht, während man ihn schreibt.
Abgrenzung zum Wiki
Die Wissenssammlung dieses Buchs läuft nicht nach Docs-as-Code, sondern auf einem Wiki (MediaWiki). Das ist Absicht. Ein Wiki ist eine laufende Anwendung mit Datenbank, in der viele Menschen direkt im Browser schreiben, ohne Git zu kennen. Docs-as-Code passt besser, wenn wenige Personen an einem abgeschlossenen Text arbeiten, die Änderungen streng geprüft werden sollen und der Text auch als Buch erscheinen soll. Beide Ansätze schließen sich nicht aus – dieses Projekt nutzt beide nebeneinander.
Was „robust" bei Docs-as-Code bedeutet
Die Frage „Welches Werkzeug verkraftet eine Million Textinhalte, ohne kaputtzugehen?" zielt auf einen anderen Punkt als bei einer laufenden Anwendung. Fertige HTML-Seiten auszuliefern ist für jeden Webserver mühelos, egal wie viele es sind – das ist der schnelle Teil, „auf dem Blech" (bare metal) ohne Zwischenschichten. Der Engpass liegt woanders:
- Die Bauzeit. Aus einer Million Textdateien alle HTML-Seiten zu erzeugen, kann je nach Generator Sekunden oder viele Stunden dauern. Ausgereifte Generatoren bauen inkrementell: Sie erzeugen nach einer Änderung nur die betroffenen Seiten neu, nicht alles.
- Der Suchindex. Viele Generatoren bauen eine Volltextsuche ein, die im Browser läuft. Bei sehr vielen Seiten wird diese Index-Datei zu groß zum Herunterladen. Dann braucht es eine serverseitige Suche (siehe Inhalts-Software selbst betreiben).
- Verschiedene Inhaltstypen und Datensätze. Neben Fließtext fallen Bilder, Tabellen, Codebeispiele, Kennzahlen und ganze Datensätze an. Gute Werkzeuge trennen Inhalt und Daten: Der Text steht in Markdown, feste Angaben stehen im Kopf der Datei (Frontmatter) oder in getrennten Datendateien (YAML, JSON, CSV), aus denen der Generator Seiten oder Tabellen erzeugt.
- Der Reifegrad. Ausgereift heißt: Das Werkzeug gibt es seit vielen Jahren, es hat einen festen Veröffentlichungsplan, eine große Gemeinschaft, eine klare Vorgehensweise beim Umstieg auf neue Versionen und bekannte, große Projekte, die es einsetzen. Das ist der Unterschied zwischen einem Werkzeug, auf das man ein Buch für zehn Jahre stellt, und einem, das nach zwei Jahren nicht mehr gepflegt wird.
Einen einheitlichen, neutralen Geschwindigkeitsvergleich wie bei Webframeworks gibt es für Dokumentations-Generatoren nicht. Als grobe Ordnung gilt: Generatoren, die als eine einzige eigenständige Programmdatei ausgeliefert werden (geschrieben in Go oder Rust), bauen am schnellsten; Generatoren auf Basis von Python liegen im Mittelfeld; Generatoren, die im Bau ein ganzes Webprogramm mitpacken (JavaScript), sind bei sehr vielen Seiten am langsamsten. Der einzige verlässliche Test ist, die eigene Textmenge nachzubilden und die Bauzeit zu messen.
Buch-Generatoren (Markdown/AsciiDoc)
Diese Werkzeuge erzeugen ein Buch: einen durchgehenden Text von vorne nach hinten, mit Kapiteln, Inhaltsverzeichnis und meist auch einer PDF- oder E-Book-Fassung. Sie eignen sich für Handbücher, Lehrbücher und Nachschlagewerke – überall dort, wo der Inhalt eine feste Reihenfolge hat.
| Werkzeug | Sprache des Werkzeugs | Auszeichnungssprache | Besonders geeignet für |
|---|---|---|---|
| mdBook | Rust | Markdown | Schlanke Handbücher, sehr schneller Bau; nutzt dieses Buch |
| Sphinx | Python | reStructuredText, Markdown | Sehr große Nachschlagewerke mit vielen Querverweisen |
| Antora | JavaScript | AsciiDoc | Sehr große Dokumentation aus vielen getrennten Quellen, mit Versionen |
| Quarto | – (eigenständig) | Markdown | Wissenschaftliche Bücher mit Rechenergebnissen im Text |
| Bookdown | R | Markdown | Bücher aus der Statistik-Welt |
| Pandoc | Haskell | Markdown u. v. m. | Umwandlung in nahezu jedes Ausgabeformat |
Sphinx gilt als das ausgereifteste Werkzeug für sehr umfangreiche Dokumentation. Es gibt es seit 2008, die Dokumentation der Programmiersprache Python und die des Linux-Kernels werden damit gebaut. Seine Stärke sind Querverweise und Stichwortverzeichnisse über Tausende von Seiten, die auch bei einem Umbau nicht ins Leere zeigen.
Antora ist eigens für sehr große, aufgeteilte Dokumentation gebaut: Der Inhalt liegt in vielen getrennten Ablagen, Antora fügt ihn zu einer Webseite zusammen und verwaltet dabei mehrere Versionen nebeneinander. Der Softwarehersteller Red Hat pflegt damit seine Produkthandbücher.
mdBook ist bewusst einfach gehalten. Es baut auch große Bücher in Sekunden und kann eingebettete Codebeispiele beim Testen ausführen (siehe unten). Für ein Handbuch wie dieses ist es die passende Größe.
Dokumentations-Frameworks (moderne Web-Dokumentation, Komponenten, API-Docs)
Diese Werkzeuge stellen nicht das Buch in den Mittelpunkt, sondern die Dokumentations-Webseite eines Produkts: mit eingebauter Suche, mehreren Versionen, mehreren Sprachen und interaktiven Bausteinen auf den Seiten. Häufig wird damit auch die Beschreibung einer Programmierschnittstelle (API) dargestellt.
| Werkzeug | Grundlage | Besonders geeignet für |
|---|---|---|
| Material for MkDocs | Python (MkDocs) | Der einfache Einstieg; sehr gute eingebaute Suche |
| Docusaurus | JavaScript (React), von Meta | Interaktive Bausteine in den Seiten, Versionen, viele Sprachen |
| Starlight | JavaScript (Astro) | Moderne, schnelle Dokumentations-Webseiten |
| VitePress | JavaScript (Vue) | Schneller Bau; baut die Dokumentation von Vue und Vite |
| Antora | JavaScript | Dokumentation aus vielen Quellen und mit Versionen (siehe oben) |
| Redoc / Swagger UI | JavaScript | Reine API-Beschreibungen aus einer OpenAPI-Datei |
Material for MkDocs ist unter diesen Werkzeugen am weitesten verbreitet. Es ist schnell eingerichtet, die eingebaute Suche ist gut, und es wird von sehr vielen Projekten eingesetzt. Docusaurus ist mächtiger, aber aufwendiger: Es erlaubt echte Programmbausteine mitten im Text (Format MDX, also Markdown mit eingebauten Bedienelementen) und bringt Versions- und Übersetzungsverwaltung mit. Beide sind bei großen Projekten bewährt; bei sehr vielen Seiten wächst die Bauzeit spürbar, weshalb der inkrementelle Bau wichtig wird.
Für reine API-Beschreibungen erzeugen Redoc und Swagger UI die Seiten unmittelbar aus einer formalen Beschreibungsdatei (OpenAPI). Ändert sich die Schnittstelle, ändert sich die Dokumentation automatisch mit.
Notizbuch-Systeme mit ausführbarem Code
Ein „Notizbuch" (englisch notebook) mischt Text und Programmcode in einem Dokument. Beim Bau wird der Code ausgeführt, und sein Ergebnis – eine Zahl, eine Tabelle, ein Diagramm – landet direkt im fertigen Text. So bleiben Erklärung und Rechenergebnis immer zusammen und immer aktuell.
| Werkzeug | Sprachen für den Code | Speicherform | Besonderheit |
|---|---|---|---|
| Jupyter | Python, R, Julia u. a. | JSON (.ipynb) | Der weit verbreitete Standard |
| Jupyter Book / MyST | wie Jupyter | Markdown + Notizbücher | Ganze Bücher aus Notizbüchern; mit Zwischenspeicher |
| Quarto | Python, R, Julia, JavaScript | Markdown (.qmd) | Ein System für Buch, Webseite und Folien |
| marimo | Python | reine Python-Datei (.py) | Reagiert wie eine Tabellenkalkulation; gut für Git |
| Observable Framework | JavaScript | Markdown | Datenauswertungen und Übersichtsseiten |
Für Docs-as-Code ist die Speicherform entscheidend. Klassische Jupyter-Notizbücher liegen als JSON-Datei vor, in der auch die Ausgaben mitgespeichert werden. Solche Dateien lassen sich mit Git schlecht vergleichen – schon ein erneuter Lauf verändert die halbe Datei. marimo speichert das Notizbuch als gewöhnliche Python-Datei, Quarto und MyST als Markdown. Diese Formen zeigen im Vergleich sauber, was sich geändert hat, und passen deshalb besser in den Docs-as-Code-Ablauf.
Der Engpass bei großen Sammlungen ist die Ausführungszeit: Wird bei jedem Bau sämtlicher Code neu gerechnet, dauert es lange. Ausgereifte Systeme haben deshalb einen Zwischenspeicher (Jupyter Cache, bei Quarto „freeze" genannt): Nur geänderter Code wird neu ausgeführt, der Rest kommt aus dem Speicher.
Auch mdBook kennt eine einfache Form davon: mdbook test führt die in den Text eingebetteten Rust-Beispiele aus und meldet, wenn eines nicht mehr stimmt.
Generatoren für lokale Notizsammlungen
Hier geht es um die persönliche Wissensablage: viele kleine, untereinander verlinkte Notizen, lokal auf dem eigenen Rechner geschrieben, oft mit Rückverweisen (Backlinks – jede Notiz zeigt, welche anderen Notizen auf sie verweisen). Im Netz wird eine solche veröffentlichte Sammlung „digitaler Garten" genannt.
| Werkzeug | Art | Besonderheit |
|---|---|---|
| Obsidian | Schreibprogramm | Arbeitet auf einem Ordner lokaler Markdown-Dateien; sehr große Sammlungen |
| Quartz | Generator | Macht aus einem Obsidian-Ordner eine Webseite mit Rückverweisen |
| Logseq | Schreibprogramm | Gliederung in Stichpunkten, lokale Markdown-Dateien |
| Hugo | Generator (Go) | Extrem schnell, verkraftet Zehntausende Seiten in Sekunden |
| Zola | Generator (Rust) | Eine einzige Programmdatei, sehr schneller Bau |
| Eleventy | Generator (JavaScript) | Sehr anpassbar |
| Jekyll | Generator (Ruby) | Standard bei GitHub Pages, bei vielen Seiten aber langsam |
Für die Sammlung selbst ist Obsidian verbreitet; es kommt auch mit vielen Tausend Notizen gut zurecht, weil es einfach lokale Textdateien bearbeitet. Für die Veröffentlichung ist dann der Generator der Engpass. Quartz ist eigens für digitale Gärten gemacht und stellt Rückverweise und eine Übersichtskarte dar. Wer allein auf Geschwindigkeit bei sehr vielen Seiten achtet, wählt Hugo oder Zola: Beide bauen große Sammlungen in unter einer Sekunde bis wenigen Sekunden. Jekyll ist am längsten im Umlauf, wird bei großen Sammlungen aber deutlich langsam.
KI- und LLM-Wiki-Konzepte
Mit den Sprachmodellen sind zwei neuere Ansätze entstanden, bei denen eine Künstliche Intelligenz an der Wissenssammlung mitarbeitet. „LLM" steht für Large Language Model, also ein großes Sprachmodell.
LLM-Wiki. Ein Agent baut die Wissenssammlung selbst auf – aus vorhandenem Material wie Programmcode oder Dokumenten – und hält sie danach fortlaufend aktuell. Der Gedanke dahinter: Das Verständnis sammelt sich an, statt bei jeder Frage neu erarbeitet zu werden. Bekannte Vertreter sind DeepWiki, das aus einer Code-Ablage auf GitHub ein durchblätterbares Wiki mit Chat-Funktion erzeugt, sowie OpenWiki und ähnliche quelloffene Werkzeuge, die ein solches Wiki über die Änderungen im Git regelmäßig nachführen.
Co-Wiki. Mensch und Agent bearbeiten dieselbe Sammlung gemeinsam: Der Agent schreibt Entwürfe, ergänzt fehlende Abschnitte oder beantwortet Fragen auf Grundlage der vorhandenen Artikel; ein Mensch prüft und gibt frei. Dienste wie GitBook oder Mintlify bauen eine solche KI-Unterstützung fest in die Dokumentations-Webseite ein.
Wichtig ist dabei die redaktionelle Kontrolle. Von einer KI erzeugte Inhalte können falsch sein und müssen geprüft werden, bevor sie stehen bleiben – genau das schreibt auch die Arbeitsweise dieses Buchs vor (Prüfschritte und der Transparenzhinweis nach Art. 50 EU AI Act). Die verlässliche Fassung bleibt der von Menschen geprüfte Text unter Git; das KI-Wiki ist eine Zuarbeit, keine Quelle der Wahrheit.
KI-Agenten-Tauglichkeit und RAG-Integration
Docs-as-Code ist die beste Grundlage, wenn ein KI-Agent (siehe KI-Agenten auf dem Server) auf die Inhalte zugreifen soll. Der übliche Weg dafür heißt RAG (englisch für „Erzeugung mit Anreicherung durch Abruf"): Der Agent sucht zuerst die passenden Textstellen heraus und schreibt seine Antwort dann nur auf deren Grundlage. Reiner Markdown-Text hilft dabei an mehreren Stellen:
- Sauberes Zerteilen. RAG zerlegt die Texte in Häppchen. Überschriften in Markdown sind natürliche Trennstellen – jeder Abschnitt wird ein sinnvolles Häppchen.
- Feste Adressen. Jede Seite und jeder Abschnitt hat eine feste Web-Adresse. Der Agent kann seine Antwort damit belegen und auf die Stelle verweisen.
- Angaben im Dateikopf. Das Frontmatter (Titel, Datum, Schlagworte) lässt sich zum Filtern nutzen.
- Git-Verlauf. Der Agent kann erkennen, was sich seit wann geändert hat.
Dazu gibt es einen jungen Standard namens llms.txt: eine Datei im Wurzelverzeichnis der Webseite, die alle wichtigen Seiten mit einer kurzen Beschreibung auflistet – ähnlich wie robots.txt für Suchmaschinen. Oft kommt eine zweite Datei llms-full.txt dazu, die den gesamten Inhalt als reinen Markdown-Text enthält. Für einen Agenten ist das viel sparsamer als die HTML-Seiten: Der Verbrauch an Recheneinheiten (Token) sinkt um etwa 90 Prozent. Nach Angaben des Anbieters GitBook stammen inzwischen rund 40 Prozent der Zugriffe auf Dokumentations-Seiten von KI-Agenten und nicht mehr von Menschen.
Manche Werkzeuge erzeugen llms.txt von selbst (etwa Mintlify), für andere gibt es Zusatzbausteine (für MkDocs und Docusaurus). Den Abruf durch den Agenten übernehmen entweder eine selbst gebaute RAG-Kette (mit Bausteinkästen wie LlamaIndex, LangChain oder Haystack) oder ein fertiger Dienst, der die Dokumentation als Chat zugänglich macht.
Reifegrad im Überblick
| Aufgabe | Ausgereifte Wahl für große Mengen | Warum |
|---|---|---|
| Handbuch, schlank | mdBook | Sehr schneller Bau, einfache Struktur |
| Nachschlagewerk, sehr groß | Sphinx | Seit 2008, Querverweise über Tausende Seiten, große Projekte |
| Dokumentation aus vielen Quellen, mit Versionen | Antora | Eigens dafür gebaut, im Einsatz bei großen Herstellern |
| Produkt-Dokumentation mit Suche | Material for MkDocs, Docusaurus | Weit verbreitet, bei großen Projekten bewährt |
| Text mit Rechenergebnissen | Quarto, Jupyter Book | Zwischenspeicher für den Code, mehrere Sprachen |
| Lokale Notizsammlung, sehr viele Seiten | Hugo, Zola | Bau in Sekunden auch bei Zehntausenden Seiten |
| Zugriff durch KI-Agenten | jedes Markdown-Werkzeug + llms.txt | Reiner Text zerteilt und belegt sich sauber |
Für dieses Buch
Dieses Handbuch nutzt mdBook. Das passt: Der Inhalt hat eine feste Reihenfolge, die Menge bleibt überschaubar, der Bau ist in Sekunden fertig, und eingebettete Codebeispiele lassen sich testen.
Die eigentliche Wissenssammlung läuft bewusst nicht nach Docs-as-Code, sondern als Wiki – weil dort viele Personen ohne Git-Kenntnisse direkt im Browser schreiben sollen. Beide Wege bestehen nebeneinander.
Für die Zusammenarbeit mit einem KI-Agenten gilt: Die Kapitel bleiben reiner Markdown-Text, und sobald die Webseite online geht, kommt eine llms.txt-Datei dazu. Der Agent bekommt sowohl das Buch als auch das Wiki über eine RAG-Kette zugänglich gemacht.
Sollte das Buch sehr stark wachsen oder mehrere Versionen nebeneinander brauchen, sind Antora oder Sphinx die ausgereiften Alternativen.
Fazit
Docs-as-Code heißt, Dokumentation wie Programmcode zu behandeln: als reinen Text in Git, mit Prüfung vor der Übernahme und automatischem Bau. Ob ein Werkzeug „eine Million Inhalte aushält", entscheidet sich nicht am Ausliefern der Seiten – das ist für jeden Webserver mühelos –, sondern an der Bauzeit, am Suchindex und an der sauberen Trennung von Text und Daten. Als besonders ausgereift gelten Sphinx und Antora für sehr große Nachschlagewerke, Material for MkDocs und Docusaurus für Produkt-Dokumentation, mdBook für schlanke Handbücher, Quarto und Jupyter Book für Text mit Rechenergebnissen sowie Hugo und Zola für sehr große lokale Notizsammlungen. Von KI erzeugte Wikis sind eine nützliche Zuarbeit, ersetzen aber nicht die redaktionelle Prüfung. Für den Zugriff durch KI-Agenten ist reiner Markdown-Text zusammen mit einer llms.txt-Datei die beste Grundlage. Für dieses Buch bleibt es bei mdBook, mit dem Wiki daneben und einer geplanten llms.txt für den Agenten.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Docs-as-Code für Webseiten und Blogs
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Das Kapitel Docs-as-Code beschreibt das Verfahren am Beispiel eines Buchs: ein durchgehender Text mit fester Reihenfolge. Für eine allgemeine Webseite oder einen Blog gilt dasselbe Verfahren – reiner Text in Git, Prüfung vor der Übernahme, automatischer Bau –, aber die Anforderungen sind andere. Es gibt keine feste Lesereihenfolge, dafür viele einzelne Beiträge, Übersichtsseiten, Schlagwort-Seiten, Archive nach Jahr und Monat, Autorenseiten und oft auch Seiten, die aus reinen Datensätzen entstehen.
Dieses Kapitel beantwortet die Frage: Welche Werkzeuge für Webseiten und Blogs sind so ausgereift und so robust, dass sie auch sehr große Inhaltsmengen – bis in den Bereich einer Million einzelner Beiträge – zuverlässig verarbeiten, verschiedene Inhaltstypen und Datensätze sauber verwalten, dabei schnell bleiben und sich verlässlich messen lassen?
Worauf es bei großen Mengen ankommt
Eine fertige Webseite besteht am Ende nur aus HTML-, CSS- und Bilddateien. Diese Dateien auszuliefern ist für jeden Webserver mühelos – ob es hundert oder eine Million sind, spielt kaum eine Rolle. Das ist der schnelle Teil: einfache Dateien direkt „vom Blech" (bare metal), ohne Datenbank, ohne Programm dazwischen. Ein vorgelagertes Auslieferungsnetz (CDN, ein Netz aus Zwischenspeichern nah bei den Besuchern) liefert sie mit nahezu Leitungsgeschwindigkeit aus.
Der Engpass liegt nicht beim Ausliefern, sondern beim Bau:
- Die Bauzeit von Grund auf. Aus einer Million Textdateien alle HTML-Seiten neu zu erzeugen, dauert je nach Werkzeug wenige Minuten oder viele Stunden. Werkzeuge, die für große Mengen taugen, brauchen für die volle Million höchstens einige Minuten.
- Der inkrementelle Bau. Nach einer kleinen Änderung darf nicht alles neu gebaut werden, sondern nur die betroffenen Seiten. Ausgereifte Werkzeuge erkennen, welche Seiten von einer Änderung abhängen, und bauen nur diese neu.
- Der Speicherbedarf. Manche Werkzeuge halten während des Baus die gesamte Webseite im Arbeitsspeicher. Bei sehr vielen Seiten reicht der Speicher dann nicht mehr, und der Bau bricht ab.
- Die Suche. Eine im Browser laufende Volltextsuche lädt eine Index-Datei herunter. Bei sehr vielen Seiten wird diese Datei zu groß. Dann braucht es eine serverseitige Suche (siehe Inhalts-Software selbst betreiben).
- Verschiedene Inhaltstypen und Datensätze. Neben Beiträgen fallen Bilder, Tabellen, Kennzahlen und ganze Datensätze an. Gute Werkzeuge trennen Text und Daten sauber (siehe unten).
Was „ausgereift" bedeutet
Ausgereift heißt bei diesen Werkzeugen dasselbe wie im Kapitel Docs-as-Code: Das Werkzeug gibt es seit vielen Jahren, es hat einen festen Veröffentlichungsplan, eine große Gemeinschaft, eine klare Vorgehensweise beim Umstieg auf neue Versionen und bekannte große Webseiten, die darauf laufen. Für einen Blog, der zehn Jahre bestehen soll, ist das der entscheidende Punkt – wichtiger als jede einzelne Funktion.
Die Werkzeuge im Überblick
| Werkzeug | Sprache des Werkzeugs | Im Umlauf seit | Besonders geeignet für |
|---|---|---|---|
| Hugo | Go | 2013 | Sehr große Blogs und Webseiten; schnellster Bau; eine einzige Programmdatei |
| Zola | Rust | 2017 | Wie Hugo, sehr schneller Bau, eine Programmdatei; kleinere Gemeinschaft |
| Jekyll | Ruby | 2008 | Am längsten erprobt; Standard bei GitHub Pages; bei großen Mengen langsam |
| Eleventy (11ty) | JavaScript | 2018 | Sehr anpassbar; schlanke Ausgabe ohne unnötiges JavaScript |
| Astro | JavaScript | 2021 | Moderne inhaltslastige Webseiten; Inhalts-Sammlungen mit Prüfung |
| Next.js | JavaScript (React) | 2016 | Sehr großes Ökosystem; auch gemischter Betrieb (siehe Webframework) |
| Gatsby | JavaScript (React) | 2015 | War lange verbreitet; Bau bei vielen Seiten sehr langsam; rückläufig |
| Pelican | Python | 2010 | Blogs in der Python-Welt |
| Hexo | JavaScript | 2012 | Blogs; im asiatischen Raum weit verbreitet |
Hugo – die ausgereifte Wahl für sehr große Webseiten
Hugo wird als eine einzige eigenständige Programmdatei ausgeliefert; es gibt keine weiteren Teile zu installieren. Nach eigenen Angaben baut Hugo eine durchschnittliche Seite in unter einer Millisekunde, sodass selbst Webseiten mit vielen Tausend Seiten in unter einer Sekunde fertig sind. Für eine Million Beiträge bewegt sich der vollständige Bau je nach Rechner im Bereich weniger Minuten. Hugo baut auch inkrementell und meldet auf Wunsch, wie viel Zeit und Speicher der Bau gebraucht hat. Große Nachrichten- und Unternehmensseiten laufen damit. Wenn allein die schiere Menge zählt, ist Hugo die naheliegende Wahl.
Für Fälle, in denen selbst Hugo an Grenzen kommt, kann Hugo den Bau in Abschnitte teilen und nur einzelne Abschnitte neu erzeugen. So lässt sich eine sehr große Webseite in mehreren Läufen bauen, statt in einem einzigen.
Zola – gleiche Idee, andere Grundlage
Zola verfolgt denselben Ansatz wie Hugo: eine einzige Programmdatei, sehr schneller Bau, keine Zusatzteile. Es ist in der Sprache Rust geschrieben und in manchen Vergleichen noch etwas schneller als Hugo. Die Gemeinschaft ist kleiner, es gibt weniger fertige Vorlagen und Erweiterungen. Für eine überschaubare, aber sehr große Webseite mit klaren Anforderungen ist Zola eine gute Wahl; wo viele fertige Bausteine gebraucht werden, ist Hugo im Vorteil.
Jekyll – am längsten erprobt, aber langsam
Jekyll ist der Urvater dieser Werkzeuge und die Standard-Grundlage von GitHub Pages. Es ist außerordentlich stabil und gut dokumentiert. Sein Nachteil zeigt sich genau bei der Frage dieses Kapitels: Bei mehreren Tausend Seiten wird der Bau spürbar langsam, bei Hunderttausenden ist er kaum noch praktikabel. Für einen kleinen bis mittleren Blog ist Jekyll solide; für sehr große Mengen ist es die falsche Wahl.
Eleventy und Astro – flexibel und modern
Eleventy ist bewusst schlank und lässt sich weitgehend anpassen. Es erzeugt standardmäßig reines HTML ohne mitgeliefertes JavaScript, was die Seiten leicht macht. Bei sehr großen Mengen liegt es in der Geschwindigkeit im Mittelfeld – schneller als Jekyll, langsamer als Hugo.
Astro ist auf inhaltslastige Webseiten ausgelegt. Es liefert ebenfalls überwiegend reines HTML aus und lädt JavaScript nur dort nach, wo es wirklich gebraucht wird (dieses Vorgehen heißt „Inseln", englisch islands). Astro bringt Inhalts-Sammlungen mit: Man legt für jeden Inhaltstyp fest, welche Angaben im Dateikopf stehen müssen, und der Bau bricht ab, wenn ein Beitrag diese Vorgabe verletzt. Das hält große Sammlungen sauber. Astro ist noch vergleichsweise jung, wächst aber schnell und wird bereits von großen Webseiten eingesetzt.
Next.js und Gatsby – die React-Werkzeuge
Next.js kann Seiten beim Bau als statische Dateien erzeugen, aber auch beim Aufruf durch den Server (siehe Webframework). Für sehr große Webseiten bietet es einen Mittelweg: Nur die wichtigsten Seiten werden beim Bau erzeugt, die übrigen entstehen beim ersten Aufruf und werden dann zwischengespeichert. So lässt sich eine Million Seiten betreiben, ohne sie alle im Voraus zu bauen. Der Preis dafür ist ein laufender Server statt reiner Dateien.
Gatsby war einige Jahre sehr beliebt, gilt inzwischen aber als rückläufig. Der Bau ist bei vielen Seiten langsam und speicherhungrig. Für neue Projekte in großem Umfang ist es nicht die erste Wahl.
Verschiedene Inhaltstypen und Datensätze verwalten
Ein Blog besteht nicht nur aus Fließtext. Ausgereifte Werkzeuge trennen drei Dinge:
- Der Text steht in Markdown, eine Datei je Beitrag.
- Feste Angaben zum Beitrag – Titel, Datum, Autor, Schlagworte, Kurzbeschreibung – stehen im Kopf der Datei, dem Frontmatter. Daraus baut das Werkzeug automatisch Übersichts-, Schlagwort- und Archivseiten.
- Reine Datensätze – etwa eine Liste von Produkten, Orten oder Kennzahlen – stehen in getrennten Datendateien (Formate YAML, JSON, TOML oder CSV). Das Werkzeug erzeugt daraus Tabellen oder ganze Seiten, ohne dass man jede von Hand anlegt.
Größere Redaktionen legen die Inhalte oft nicht als Dateien ab, sondern in einem Headless-CMS – einer Inhaltsverwaltung, die eine bequeme Schreiboberfläche bietet, die Inhalte aber nicht selbst anzeigt, sondern nur über eine Schnittstelle herausgibt. Der Generator holt die Inhalte beim Bau von dort ab und macht daraus statische Seiten. So schreiben Redakteure in einer vertrauten Oberfläche, und die ausgelieferte Webseite bleibt trotzdem eine Sammlung einfacher Dateien.
Für Bilder haben Hugo, Astro und Eleventy eine eingebaute Bildverarbeitung: Sie erzeugen beim Bau verkleinerte Fassungen in mehreren Größen und modernen Formaten, sodass jeder Besucher nur die passende Größe lädt.
Messbarkeit: den eigenen Fall nachbauen
Einen einheitlichen, neutralen Geschwindigkeitsvergleich – wie ihn Webframeworks mit dem TechEmpower-Vergleich haben (siehe Webframework) – gibt es für diese Werkzeuge nicht. Veröffentlichte Vergleiche messen unterschiedliche Seiten, unterschiedliche Vorlagen und unterschiedliche Rechner; ihre Zahlen sind nur grobe Anhaltspunkte.
Der einzige verlässliche Test ist, die eigene Inhaltsmenge nachzubilden und selbst zu messen:
- Testinhalte erzeugen. Ein kleines Skript legt so viele Beispielbeiträge an, wie später erwartet werden – etwa hunderttausend oder eine Million, mit realistischem Frontmatter und realistischer Textlänge.
- Den Bau von Grund auf messen. Wie lange dauert ein vollständiger Bau ohne Zwischenspeicher? Wie viel Arbeitsspeicher wird dabei belegt?
- Den inkrementellen Bau messen. Wie lange dauert der Bau, nachdem sich ein einziger Beitrag geändert hat?
- Auf der Zielumgebung messen. Der Bau-Server im automatischen Ablauf (CI/CD) hat oft weniger Leistung als der eigene Rechner. Die Messung zählt nur dort, wo später wirklich gebaut wird.
Hugo bringt für Schritt 2 und 3 eigene Anzeigen mit (Bauzeit je Vorlage, belegter Speicher). Bei den anderen Werkzeugen misst man die Gesamtzeit von außen.
Als grobe Ordnung – wie im Kapitel Docs-as-Code – gilt: Werkzeuge, die als eine einzige Programmdatei in Go oder Rust ausgeliefert werden (Hugo, Zola), bauen am schnellsten und verkraften die größten Mengen. Werkzeuge auf Basis von Python oder Ruby (Pelican, Jekyll) liegen im Mittelfeld bis hinten. Werkzeuge, die im Bau ein ganzes Webprogramm mitführen (Gatsby, teils Next.js), sind bei sehr vielen Seiten am langsamsten und brauchen am meisten Speicher.
Reifegrad im Überblick
| Anforderung | Ausgereifte Wahl | Warum |
|---|---|---|
| Sehr großer Blog, reine Dateien | Hugo | Bau in Minuten auch bei einer Million Beiträgen; eine Programmdatei; große Gemeinschaft |
| Sehr große Webseite, klare Anforderungen | Hugo, Zola | Schnellster Bau, geringster Speicherbedarf |
| Eine Million Seiten ohne vollständigen Vorab-Bau | Next.js | Wichtige Seiten beim Bau, der Rest beim ersten Aufruf mit Zwischenspeicher |
| Kleiner bis mittlerer Blog, höchste Stabilität | Jekyll | Seit 2008, Standard bei GitHub Pages |
| Inhaltslastige Webseite mit vielen Inhaltstypen | Astro | Inhalts-Sammlungen mit Prüfung; schlanke Ausgabe |
| Schlanke, stark angepasste Ausgabe | Eleventy | Reines HTML, weitgehend anpassbar |
Für dieses Buch
Dieses Handbuch ist ein Buch mit fester Reihenfolge und nutzt daher mdBook. Entstünde stattdessen ein Blog oder eine allgemeine Webseite in großem Umfang, wäre Hugo die ausgereifte Wahl: reine Dateien in Git, Bau in Minuten auch bei sehr großen Mengen, saubere Trennung von Text und Daten und eine einzige Programmdatei ohne weitere Abhängigkeiten. Erst wenn die Zahl der Seiten so groß wird, dass sich ein vollständiger Vorab-Bau nicht mehr lohnt, käme der gemischte Betrieb mit Next.js in Frage – um den Preis eines laufenden Servers statt reiner Dateien.
Fazit
Für Webseiten und Blogs gilt dasselbe Docs-as-Code-Verfahren wie für ein Buch, nur mit vielen einzelnen Beiträgen statt einem durchgehenden Text. Ob ein Werkzeug „eine Million Beiträge aushält", entscheidet sich nicht am Ausliefern der Seiten – das ist für jeden Webserver und jedes Auslieferungsnetz mühelos –, sondern an der Bauzeit von Grund auf, am inkrementellen Bau, am Speicherbedarf und an der sauberen Trennung von Text und Daten. Am besten schneiden die Werkzeuge ab, die als eine einzige Programmdatei ausgeliefert werden: Hugo und, mit kleinerer Gemeinschaft, Zola. Jekyll ist am längsten erprobt, aber bei großen Mengen zu langsam. Astro und Eleventy sind moderne, flexible Alternativen im Mittelfeld. Wo eine Million Seiten nicht mehr sinnvoll im Voraus gebaut werden können, bietet Next.js einen Mittelweg mit laufendem Server. Verlässliche Zahlen liefert nur ein eigener Test mit der eigenen Inhaltsmenge auf der eigenen Bau-Umgebung.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Wissenssystem
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Ein Wissenssystem ist das Programm, in dem die Texte geschrieben, gelesen und geordnet werden. Es ist die oberste Schicht des Web Stacks: Der Besucher sieht nur dieses Programm. Darunter liegen die Datenbank, in der alle Inhalte dauerhaft gespeichert sind, und der Webserver, der die Seiten ausliefert. Im Kapitel Inhalts-Software selbst betreiben ist dieses oberste Programm bereits als ein Baustein aufgetaucht; im Kapitel Freies Wissen stehen mehrere davon in einer Liste. Dieses Kapitel trifft die Wahl.
Die Ausgangsfrage des Autors lautete: Welches Wissenssystem ist industrietauglich, sehr robust, verwaltet eine Million Texteinträge mit verschiedenen Inhaltstypen und Datensätzen, geht dabei nicht kaputt, ist schnell und lässt sich vergleichend messen, hat den höchsten Reifegrad und läuft direkt auf dem Server – wobei als Datenbank ausschließlich PostgreSQL vorgesehen ist. Diese Anforderungen werden im Folgenden einzeln geprüft und daraus eine Empfehlung abgeleitet.
Was schon feststeht
Drei Dinge sind durch die vorigen Kapitel bereits entschieden und schränken die Auswahl ein:
- Die Datenbank ist PostgreSQL. Das Kapitel Datenbank richtet PostgreSQL 18 ein, samt der Erweiterungen für die Suche. Ein Wissenssystem, das PostgreSQL nicht unterstützt, scheidet damit aus – auch dann, wenn es sonst gut passen würde.
- Es läuft „auf dem Metall". Das Programm wird direkt auf dem Server installiert, ohne Zwischenschicht wie einen Container (siehe Containerisierung von Software). Das bedeutet: Es muss sich als normales Paket oder als entpacktes Archiv auf Ubuntu einrichten lassen und darf nicht zwingend eine Container-Umgebung voraussetzen.
- Es wird selbst betrieben. Die Inhalte bleiben auf dem eigenen Server. Bezahldienste in fremder Hand und Programme ohne offenen Quelltext kommen nicht in Frage.
Die Kriterien der Frage, einzeln betrachtet
Die Begriffe aus der Ausgangsfrage klingen anspruchsvoller, als sie in der Praxis sind. Es lohnt sich, jeden einzeln einzuordnen.
- „Eine Million Texteinträge" ist für ein ausgereiftes Wissenssystem eine kleine bis mittlere Größe. Die deutschsprachige Wikipedia hat ein Vielfaches davon. Über die Geschwindigkeit entscheidet nicht die Menge der Seiten, sondern ob die Datenbank die passenden Indizes hat – ein Index ist ein zusätzliches Verzeichnis, das das Suchen abkürzt, so wie das Stichwortverzeichnis am Ende eines Buchs. Dieser Punkt ist im Kapitel Datenbank ausführlich behandelt.
- „Verschiedene Inhaltstypen und Datensätze" meint: nicht nur Fließtext, sondern auch feste Felder – etwa eine Liste von Geräten mit Hersteller, Baujahr und Standort, die sich sortieren und filtern lässt. Reine Wikis können das nur mit Zusatzprogrammen; einige Systeme bringen es von Haus aus mit. Das ist der Punkt, an dem sich die Kandidaten am stärksten unterscheiden.
- „Industrietauglich" und „höchster Reifegrad" bedeuten dasselbe aus zwei Richtungen: Das Programm wird seit vielen Jahren ohne Unterbrechung gepflegt, Sicherheitslücken werden zügig geschlossen, der Umstieg auf neue Versionen ist geregelt, und es gibt genug andere Betreiber, dass man bei Problemen nicht allein ist.
- „Robust" / „geht nicht kaputt" heißt: Ein Absturz des Servers hinterlässt keine zerrissenen Daten (dafür sorgt die Datenbank, siehe Datenbank), und ein Programmfehler legt nicht die ganze Sammlung lahm.
- „Schnell und benchmarkbar" – vergleichende Messungen unter gleichen Bedingungen. Für Wissenssysteme sind solche Messungen selten aussagekräftig, weil das Ergebnis fast immer an der Datenbank, den Indizes und einem Zwischenspeicher hängt, nicht am Wissenssystem selbst. Dazu weiter unten mehr.
Die Kandidaten im Überblick
Aus der Liste in Freies Wissen kommen die folgenden Programme für eine große, selbst betriebene Sammlung in Frage. Entscheidend ist die Spalte „Datenbank".
| System | Technik | Datenbank | Seit | Stärke |
|---|---|---|---|---|
| MediaWiki | PHP | MariaDB/MySQL; PostgreSQL zweitrangig | 2002 | die Software der Wikipedia; größtes Ökosystem an Erweiterungen |
| XWiki | Java | PostgreSQL (empfohlen), MariaDB | 2004 | strukturierte Daten und kleine Anwendungen von Haus aus |
| Wiki.js | JavaScript | PostgreSQL (ab der nächsten Hauptversion die einzige) | 2017 | modernes Bedienbild, Seiten zusätzlich als Git-Ablage |
| Outline | JavaScript | PostgreSQL + Redis | 2016 | schneller Editor, gut für ein Team, weniger für ein offenes Nachschlagewerk |
| Docmost | JavaScript | PostgreSQL + Redis | 2024 | beliebig verschachtelte Seiten, gemeinsames Bearbeiten in Echtzeit |
| BookStack | PHP | nur MariaDB/MySQL | 2015 | sehr einfacher Einstieg durch feste Gliederung |
| DokuWiki | PHP | keine (einfache Dateien) | 2004 | sehr wartungsarm, kein Datenbankbetrieb nötig |
Zwei Kandidaten fallen sofort heraus:
- BookStack unterstützt ausschließlich MariaDB oder MySQL. Mit der Festlegung auf PostgreSQL ist es damit außen vor, so angenehm es sonst zu bedienen wäre.
- DokuWiki benutzt gar keine Datenbank, sondern legt jede Seite als einzelne Datei ab. Das macht es extrem wartungsarm, passt aber nicht zu einem Aufbau, der bewusst auf PostgreSQL setzt, und wird bei einer Million Seiten und anspruchsvoller Suche zäh.
Der Filter „nur PostgreSQL"
Übrig bleiben MediaWiki, XWiki, Wiki.js, Outline und Docmost. Hier ist ein genauer Blick nötig, denn „unterstützt PostgreSQL" bedeutet nicht bei allen dasselbe.
- XWiki empfiehlt PostgreSQL ausdrücklich als Datenbank für den ernsthaften Betrieb. Die Unterstützung ist gleichwertig zu allen anderen; nichts fühlt sich wie ein Nebengleis an.
- Wiki.js, Outline und Docmost sind von Grund auf für PostgreSQL gebaut. Bei Wiki.js wird PostgreSQL ab der nächsten Hauptversion sogar die einzige unterstützte Datenbank sein. Outline und Docmost brauchen zusätzlich Redis, einen schnellen Zwischenspeicher – ein weiteres Programm, das eingerichtet und überwacht werden will.
- MediaWiki unterstützt PostgreSQL zwar seit vielen Jahren, aber erklärtermaßen nur zweitrangig. Empfohlen für den Produktivbetrieb sind MariaDB oder MySQL. In der Praxis heißt das: Der Kern läuft auf PostgreSQL, aber einzelne wichtige Erweiterungen (etwa die verbreitete Übersetzungs-Erweiterung „Translate") setzen MySQL voraus. Wer MediaWiki auf PostgreSQL betreibt, geht einen weniger begangenen Weg und muss bei jeder Erweiterung vorher prüfen, ob sie mitspielt.
Der Filter „industrietauglich, höchster Reifegrad"
Von den fünf verbliebenen Systemen haben zwei einen deutlich längeren und breiteren Erfolgsnachweis als die anderen drei:
- MediaWiki wird seit 2002 entwickelt, betreibt die Wikipedia mit Millionen Seiten und Milliarden Zugriffen und hat das mit Abstand größte Ökosystem an Erweiterungen, Anleitungen und erfahrenen Betreibern.
- XWiki wird seit 2004 entwickelt, wird von einem Unternehmen (XWiki SAS) kommerziell gepflegt und ist von Anfang an als „Enterprise-Wiki" für Firmen ausgelegt. Große Installationen mit Hunderten gleichzeitigen Benutzern sind dokumentiert.
Wiki.js, Outline und Docmost sind moderne, gut gemachte Programme, aber jünger und mit kleinerem Umfeld. Wiki.js hat einen langen, holprigen Übergang zwischen zwei Hauptversionen hinter sich; Docmost ist erst seit 2024 öffentlich. Für ein Team-Notizbuch mit einigen Tausend Seiten sind alle drei eine gute Wahl. Für den Anspruch „eine Million Einträge, darf auf keinen Fall kaputtgehen, muss in zehn Jahren noch gepflegt sein" sind sie die riskantere Wette.
MediaWiki oder XWiki – der eigentliche Unterschied
Damit stehen sich zwei ausgereifte Systeme gegenüber. Die Wahl zwischen ihnen hängt an zwei Fragen.
Erste Frage: Fließtext oder auch strukturierte Daten?
- MediaWiki ist auf verlinkten Fließtext ausgelegt – Artikel, die aufeinander verweisen und in Kategorien stehen. Feste Datenfelder gibt es nur über Erweiterungen wie „Semantic MediaWiki" oder eine angeschlossene Wikibase. Das funktioniert, ist aber zusätzlicher Aufbau.
- XWiki bringt strukturierte Einträge von Haus aus mit. Man legt eine Vorlage mit festen Feldern an – etwa „Gerät" mit Hersteller, Baujahr, Standort – und bekommt daraus Formulare, sortierbare Listen und Auswertungen, ohne eine Zeile Programmcode. Wenn „verschiedene Inhaltstypen und Datensätze" wörtlich gemeint ist, ist das der Punkt, der für XWiki spricht.
Zweite Frage: Wie wörtlich ist „nur PostgreSQL"?
- Ist PostgreSQL fest gesetzt und soll das Wissenssystem wirklich ohne Umwege darauf laufen, ist XWiki die natürliche Wahl: PostgreSQL ist dort erste Wahl, nicht geduldet.
- Ist MediaWiki aus anderen Gründen gewünscht (das Wikipedia-Bedienbild, eine bestimmte Erweiterung, vorhandene Erfahrung), sollte man ehrlich abwägen, ob man den Preis der zweitrangigen PostgreSQL-Unterstützung zahlen will – oder für MediaWiki doch MariaDB einsetzt. MariaDB und PostgreSQL können auf demselben Server nebeneinander laufen; die übrigen Kapitel dieses Buchs ändern sich dadurch kaum, da die Suchdienste und die Bedeutungssuche auch mit einer MariaDB-gestützten MediaWiki-Installation zusammenarbeiten.
Ein Mischweg ist ebenfalls möglich und in der Praxis verbreitet: MediaWiki mit MariaDB für die Texte, PostgreSQL mit pgvector daneben allein für die Bedeutungssuche. Dann hat jede Datenbank die Aufgabe, für die sie am besten unterstützt ist.
Zur Geschwindigkeit: Was Vergleichsmessungen taugen
Für Wissenssysteme kursieren kaum belastbare Vergleichsmessungen, und das aus gutem Grund: Die Antwortzeit einer Wiki-Seite hängt fast vollständig an drei Dingen, die alle unterhalb des Wissenssystems liegen:
- Die richtigen Indizes in der Datenbank. Eine Abfrage ohne passenden Index durchsucht die ganze Tabelle; mit Index springt sie sofort zum Ziel. Der Unterschied ist oft der Faktor Tausend.
- Ein Zwischenspeicher für fertige Seiten. Wird eine einmal erzeugte Seite für kurze Zeit vorgehalten (im Wissenssystem selbst, im Webserver oder in einem eigenen Zwischenspeicher wie Redis), spielt die Geschwindigkeit von Datenbank und Wissenssystem für den nächsten Abruf keine Rolle mehr.
- Sparsames Laden. Gute Systeme holen Listen seitenweise statt alles auf einmal.
MediaWiki wie XWiki bringen diese Mechanik mit. Der Unterschied in der reinen Geschwindigkeit ist im Alltag einer Wissenssammlung nicht spürbar. Wer trotzdem messen will, misst am Ende die Datenbank und den Zwischenspeicher – nicht das Wissenssystem.
Für dieses Buch
Die Kapitel Inhalts-Software selbst betreiben und Datenbank beschreiben den Aufbau mit MediaWiki. Das ist die Wahl für den Fall, dass die Sammlung im Kern ein verlinktes Nachschlagewerk nach dem Vorbild der Wikipedia ist: größtes Ökosystem, längster Erfolgsnachweis, die meisten Anleitungen. Dabei gilt die oben genannte Einschränkung – MediaWikis PostgreSQL-Unterstützung ist zweitrangig, weshalb für MediaWiki auch MariaDB eine vertretbare Wahl ist.
Wenn die strikte Festlegung auf PostgreSQL im Vordergrund steht oder die Sammlung von Anfang an auch strukturierte Datensätze führen soll, ist XWiki das passendere System: PostgreSQL ist dort erste Wahl, und feste Datenfelder sind eingebaut. XWiki braucht mehr Arbeitsspeicher (es läuft in einer Java-Laufzeitumgebung) und hat ein kleineres Umfeld als MediaWiki, ist aber genauso ausgereift und industrietauglich.
Die jüngeren Systeme Wiki.js, Outline und Docmost sind für ein Team-Wissensnetz eine gute Wahl, aber nicht für den Anspruch „eine Million Einträge, über viele Jahre, darf nicht kaputtgehen". BookStack und DokuWiki scheiden an der Festlegung auf PostgreSQL aus.
Fazit
Ein Wissenssystem ist die oberste Schicht des Web Stacks – das Programm, in dem geschrieben und gelesen wird. Die Festlegung auf PostgreSQL, auf den Betrieb direkt auf dem Server und auf höchsten Reifegrad grenzt die Auswahl auf zwei Systeme ein: MediaWiki und XWiki. MediaWiki ist die Wahl für ein Nachschlagewerk nach Wikipedia-Vorbild, mit der Einschränkung, dass PostgreSQL dort nur zweitrangig unterstützt wird. XWiki ist die Wahl, wenn PostgreSQL fest gesetzt ist oder neben Fließtext auch strukturierte Datensätze verwaltet werden sollen. Eine Million Einträge sind für beide unproblematisch; ob die Sammlung schnell bleibt, entscheidet nicht das Wissenssystem, sondern die Indizes in der Datenbank und ein Zwischenspeicher.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
MediaWiki einrichten
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Das Kapitel Wissenssystem grenzt die Auswahl auf zwei Programme ein: MediaWiki und XWiki. MediaWiki ist die passende Wahl, wenn die Sammlung im Kern ein verlinktes Nachschlagewerk nach dem Vorbild der Wikipedia sein soll: viele Artikel, die aufeinander verweisen und in Kategorien stehen. MediaWiki hat das mit Abstand größte Umfeld an Erweiterungen, Anleitungen und erfahrenen Betreibern und ist seit 2002 ohne Unterbrechung in Entwicklung.
Dieses Kapitel zeigt Schritt für Schritt, wie MediaWiki auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) eingerichtet wird: von der Laufzeitumgebung über die Datenbank und die Ersteinrichtung bis zum öffentlichen Zugang über einen Webserver. Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen.
Was bei MediaWiki zusammenspielt
MediaWiki ist eine Sammlung von Dateien in der Programmiersprache PHP. PHP-Code läuft nicht allein, sondern braucht ein Programm auf dem Server, das ihn ausführt – die Laufzeitumgebung (siehe Laufzeitumgebung). MediaWiki selbst speichert nichts; es zeigt Seiten an und nimmt Änderungen entgegen, ablegen tut es sie in einer Datenbank.
Vier Teile arbeiten zusammen:
- PHP-FPM – die Laufzeitumgebung, die den MediaWiki-Code ausführt. „FPM" steht für „FastCGI Process Manager": PHP läuft als Hintergrunddienst, an den der Webserver die Anfragen weiterreicht (siehe Laufzeitumgebung).
- PostgreSQL – die Datenbank, in der alle Seiten, alle früheren Versionen und alle Einstellungen liegen (siehe Datenbank). Fällt sie aus, ist das Wiki leer.
- Ein Webserver davor – nimmt die Anfragen aus dem Internet entgegen, verschlüsselt die Verbindung (HTTPS) und reicht die Seiten an PHP-FPM weiter (siehe Webserver). In diesem Buch ist das NGINX.
- MediaWiki selbst – der PHP-Code, der aus den Daten in der Datenbank die fertigen Seiten baut.
Ein Hinweis zur Datenbank vorweg
MediaWiki wird von seinen Entwicklern zusammen mit MariaDB oder MySQL empfohlen. Die Unterstützung für PostgreSQL ist vorhanden und wird gepflegt, gilt aber ausdrücklich als zweitrangig: Sie wird von Freiwilligen betreut, weniger getestet, und einzelne Erweiterungen setzen MySQL voraus. Das Kapitel Wissenssystem geht darauf genauer ein.
Dieses Kapitel richtet MediaWiki trotzdem auf PostgreSQL ein, weil das ganze Buch auf PostgreSQL aufbaut (unter anderem für die Bedeutungssuche mit pgvector, siehe Datenbank). Wer nur MediaWiki betreiben und keine PostgreSQL-Erweiterungen braucht, folgt besser der offiziellen Anleitung mit MariaDB; die übrigen Kapitel dieses Buchs ändern sich dadurch kaum.
Welche Version
MediaWiki bringt etwa alle sechs Monate eine neue Ausgabe heraus. Jede vierte davon – ungefähr alle zwei Jahre – ist eine Ausgabe mit langer Pflegezusage („LTS", englisch für „Long Term Support"). Eine LTS-Ausgabe bekommt drei Jahre lang Sicherheitskorrekturen. Für einen Server, der ruhig laufen soll, ist eine LTS-Ausgabe die richtige Wahl.
Zum Zeitpunkt dieses Kapitels ist 1.46 die neueste reguläre Ausgabe und 1.43 die aktuelle LTS-Ausgabe (gepflegt bis Ende 2027). Die nächste LTS-Ausgabe, 1.47, wird für Ende 2026 erwartet.
Wichtig ist der Zusammenhang mit PHP: MediaWiki 1.43 läuft nur mit PHP 8.1 bis 8.3, nicht mit neueren PHP-Fassungen. Ubuntu 26.04 liefert aber PHP 8.5 mit (siehe Laufzeitumgebung). Damit passt 1.43 nicht ohne Weiteres zu diesem Server. Erst MediaWiki 1.46 unterstützt PHP bis 8.5.
Daraus ergibt sich für dieses Buch: die reguläre Ausgabe 1.46 einsetzen und auf 1.47 LTS wechseln, sobald sie erschienen ist. Die folgenden Befehle nennen 1.46 an den Stellen, an denen die Versionsnummer vorkommt; für eine spätere Ausgabe wird sie entsprechend ersetzt.
Voraussetzungen
Bevor es losgeht, sollte Folgendes vorhanden sein:
- Ein Server mit Ubuntu 26.04 und Zugang über SSH.
- PostgreSQL ist eingerichtet (siehe Datenbank). Die leere Datenbank für MediaWiki wird in Schritt 2 angelegt.
- Eine Domain, die auf die IP-Adresse des Servers zeigt, zum Beispiel
wiki.meine-domain.de. Sie wird für das SSL-Zertifikat und den Webserver gebraucht. - NGINX ist installiert (siehe Webserver).
Schritt 1: PHP-FPM und die benötigten Erweiterungen installieren
MediaWiki braucht PHP-FPM und eine Reihe von PHP-Erweiterungen. Jede Erweiterung erledigt eine Teilaufgabe: php-pgsql verbindet PHP mit PostgreSQL, php-mbstring behandelt Texte mit Umlauten korrekt, php-gd verkleinert hochgeladene Bilder, php-intl sorgt für die richtige Sortierung fremdsprachiger Namen.
sudo apt update
sudo apt install php-fpm php-cli \
php-pgsql php-mbstring php-xml php-curl php-gd php-intl php-zip \
php-apcu php-openssl
# Zeigt die installierte Version zur Kontrolle an
php -v
php-apcu ist ein Zwischenspeicher im Arbeitsspeicher; MediaWiki wird damit spürbar schneller. php-openssl wird von MediaWiki 1.43 an vorausgesetzt.
Nach der Installation läuft PHP-FPM bereits als Hintergrunddienst. Die Socket-Datei, über die NGINX es später erreicht, liegt bei PHP 8.5 unter /run/php/php8.5-fpm.sock. Der genaue Name lässt sich prüfen mit:
ls /run/php/
Zwei Einstellungen in PHP sollten für MediaWiki angehoben werden: die Obergrenze für den Arbeitsspeicher eines einzelnen Aufrufs und die maximale Größe eines Datei-Uploads. Beides steht in der Datei /etc/php/8.5/fpm/php.ini:
sudo nano /etc/php/8.5/fpm/php.ini
Dort diese Werte suchen und anpassen:
memory_limit = 256M
upload_max_filesize = 100M
post_max_size = 100M
Danach PHP-FPM neu starten, damit die Änderungen greifen:
sudo systemctl restart php8.5-fpm
Schritt 2: Datenbank und Datenbankbenutzer in PostgreSQL anlegen
PostgreSQL legt bei der Installation einen Systembenutzer postgres an, der die Datenbank verwaltet. Über ihn werden ein eigener Datenbankbenutzer für das Wiki und eine leere Datenbank angelegt, die ihm gehört. Die Namen (hier wiki) sind frei wählbar, müssen aber später in der MediaWiki-Konfiguration genau so eingetragen werden.
# Datenbankbenutzer anlegen, dabei nach einem Passwort fragen
sudo -u postgres createuser --pwprompt wiki
# Datenbank mit UTF-8-Zeichensatz anlegen, Eigentümer ist "wiki"
sudo -u postgres createdb -E UTF8 -O wiki wiki
UTF8 ist der Zeichensatz, der alle Buchstaben und Zeichen der Welt kennt – wichtig für Umlaute, Anführungszeichen und fremdsprachige Inhalte.
Die Tabellen legt der MediaWiki-Installationsassistent in Schritt 5 selbst an. Ein eigenes Datenbankschema muss nicht von Hand eingerichtet werden.
Schritt 3: MediaWiki herunterladen
Am einfachsten ist der Weg über das fertige Archiv („Tarball"), das das MediaWiki-Projekt für jede Ausgabe bereitstellt. Es enthält alles, was für den Betrieb nötig ist: den Kern, die Standard-Oberflächen („Skins") und die mitgelieferten PHP-Bausteine.
cd /var/www
sudo wget https://releases.wikimedia.org/mediawiki/1.46/mediawiki-1.46.0.tar.gz
sudo wget https://releases.wikimedia.org/mediawiki/1.46/mediawiki-1.46.0.tar.gz.sig
Vor dem Entpacken lohnt ein Blick auf die Prüfsumme, damit sichergestellt ist, dass die Datei unterwegs nicht verändert wurde. Das MediaWiki-Projekt veröffentlicht dafür digitale Signaturen; die Anleitung dazu steht auf der Download-Seite von MediaWiki. Danach entpacken und den Ordner auf einen kurzen Namen bringen:
sudo tar -xzf mediawiki-1.46.0.tar.gz
sudo mv mediawiki-1.46.0 mediawiki
sudo rm mediawiki-1.46.0.tar.gz mediawiki-1.46.0.tar.gz.sig
MediaWiki liegt jetzt unter /var/www/mediawiki.
Alternative: über Git
Wer die Ausgabe später mit einem einzigen Befehl aktualisieren möchte, kann MediaWiki stattdessen aus dem Quelltext-Verwaltungssystem Git holen. Dieser Weg hat mehr Schritte, weil Skins und die PHP-Bausteine getrennt nachgeladen werden müssen:
cd /var/www
sudo git clone --branch REL1_46 https://gerrit.wikimedia.org/r/mediawiki/core.git mediawiki
cd mediawiki
sudo git submodule update --init --recursive
# Composer holt die benötigten PHP-Bausteine in den Ordner vendor/
sudo composer update --no-dev
REL1_46 ist der Zweig der Ausgabe 1.46; er bekommt weiterhin Sicherheitskorrekturen. Ein späteres sudo git pull in diesem Ordner holt sie. Das Werkzeug Composer wird im Kapitel Laufzeitumgebung eingerichtet.
Schritt 4: Dateirechte setzen
Der Webserver und PHP-FPM laufen unter dem Benutzer www-data. Damit MediaWiki hochgeladene Bilder ablegen und den Zwischenspeicher schreiben kann, muss dieser Benutzer Schreibrechte auf die entsprechenden Ordner haben. Der übrige Code sollte ihm nur zum Lesen gehören.
# Alles gehört www-data, Lese- und Ausführungsrechte für die Gruppe
sudo chown -R www-data:www-data /var/www/mediawiki
# Schreibbar nur die Ordner, die MediaWiki wirklich beschreibt
sudo find /var/www/mediawiki -type d -exec chmod 755 {} \;
sudo find /var/www/mediawiki -type f -exec chmod 644 {} \;
sudo chmod -R 775 /var/www/mediawiki/images
Der Ordner cache/ wird erst nach der Einrichtung gebraucht; MediaWiki legt ihn bei Bedarf an.
Schritt 5: MediaWiki einrichten
Bei der Einrichtung wird die Datei LocalSettings.php erzeugt. Sie enthält alle Einstellungen des Wikis, darunter das Datenbankpasswort. Es gibt zwei Wege dorthin.
Weg A: über die Textkonsole (empfohlen)
MediaWiki bringt ein Einrichtungsprogramm mit, das ohne Browser auskommt. Es fragt nichts nach, sondern nimmt alle Angaben als Befehlszeile entgegen und schreibt am Ende die fertige LocalSettings.php:
cd /var/www/mediawiki
sudo -u www-data php maintenance/run.php install \
--dbtype postgres \
--dbserver localhost \
--dbname wiki \
--dbuser wiki \
--dbpass 'DATENBANKPASSWORT' \
--installdbuser wiki \
--installdbpass 'DATENBANKPASSWORT' \
--server "https://wiki.meine-domain.de" \
--scriptpath "" \
--lang de \
--pass 'ADMINPASSWORT' \
"Wissenssammlung" "Admin"
--dbtype postgreswählt PostgreSQL als Datenbank.--dbname,--dbuser,--dbpasssind die Angaben aus Schritt 2.--serverist die spätere öffentliche Adresse,--scriptpath ""legt fest, dass das Wiki direkt unter dieser Adresse liegt (nicht in einem Unterordner).- Die beiden letzten Werte sind der Name des Wikis und der Name des Administratorkontos;
--passist dessen Passwort.
Das Programm legt die Tabellen in der Datenbank an und schreibt LocalSettings.php in den aktuellen Ordner. Danach die Datei absichern, damit nur www-data sie lesen kann:
sudo chown www-data:www-data /var/www/mediawiki/LocalSettings.php
sudo chmod 600 /var/www/mediawiki/LocalSettings.php
Weg B: über den Assistenten im Browser
MediaWiki hat auch einen grafischen Einrichtungsassistenten unter der Adresse /mw-config/. Er darf während der Einrichtung nicht öffentlich erreichbar sein, denn solange keine LocalSettings.php vorhanden ist, kann jeder Besucher das Wiki einrichten.
Der einfachste Schutz ist, die Einrichtung über einen verschlüsselten SSH-Tunnel zu erledigen, genau wie im Kapitel XWiki einrichten beschrieben. NGINX aus Schritt 6 muss dafür schon stehen, darf aber testweise nur auf 127.0.0.1 hören. Der Assistent führt durch dieselben Fragen wie Weg A und bietet am Ende die fertige LocalSettings.php zum Herunterladen an. Diese Datei wird dann auf den Server kopiert:
# Auf dem eigenen Rechner ausführen
scp ~/Downloads/LocalSettings.php admin@wiki.meine-domain.de:/tmp/LocalSettings.php
# Auf dem Server ausführen
sudo mv /tmp/LocalSettings.php /var/www/mediawiki/LocalSettings.php
sudo chown www-data:www-data /var/www/mediawiki/LocalSettings.php
sudo chmod 600 /var/www/mediawiki/LocalSettings.php
Weg A ist kürzer und sicherer, weil dabei zu keinem Zeitpunkt eine ungeschützte Seite im Netz steht.
Schritt 6: NGINX als Webserver einrichten
Damit das Wiki öffentlich und verschlüsselt erreichbar ist, kommt NGINX davor. Es liefert die festen Dateien (Bilder, Stylesheets) selbst aus und reicht alle PHP-Aufrufe an PHP-FPM weiter (siehe Webserver).
Zuerst das SSL-Zertifikat besorgen. Wie das mit Certbot und Let's Encrypt geht, steht ausführlich im Kapitel Webserver; für eine feste Domain genügt:
sudo certbot certonly --nginx -d wiki.meine-domain.de
Dann die Konfigurationsdatei /etc/nginx/sites-available/mediawiki anlegen:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name wiki.meine-domain.de;
ssl_certificate /etc/letsencrypt/live/wiki.meine-domain.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wiki.meine-domain.de/privkey.pem;
root /var/www/mediawiki;
index index.php;
# Große Datei-Uploads zulassen (muss zu php.ini aus Schritt 1 passen)
client_max_body_size 100m;
# Kurze Adressen: /Seitenname wird an index.php übergeben
location / {
try_files $uri $uri/ @mediawiki;
}
location @mediawiki {
rewrite ^/(.*)$ /index.php?title=$1&$args;
}
# PHP-Dateien an PHP-FPM weiterreichen
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.5-fpm.sock;
}
# Interne Ordner und versteckte Dateien sperren
location ^~ /cache/ { deny all; }
location ^~ /images/deleted/ { deny all; }
location ^~ /maintenance/ { deny all; }
location ~ /\.(ht|git|svn) { deny all; }
location = /LocalSettings.php { deny all; }
}
server {
listen 80;
listen [::]:80;
server_name wiki.meine-domain.de;
# Alle unverschlüsselten Aufrufe auf HTTPS umleiten
return 301 https://$host$request_uri;
}
Die beiden location-Blöcke für die kurzen Adressen sind der Kern: Fragt der Browser eine echte Datei an (ein Bild, ein Stylesheet), liefert NGINX sie direkt. Fragt er einen Seitennamen an (/Sonnenblume), gibt es diese Datei nicht – dann greift @mediawiki und leitet die Anfrage intern auf index.php?title=Sonnenblume um. MediaWiki erzeugt daraufhin die Seite.
Die deny all-Blöcke schützen Ordner, die nie direkt aus dem Browser aufgerufen werden sollen – vor allem LocalSettings.php mit dem Datenbankpasswort.
Die Datei aktiv schalten, prüfen und übernehmen:
sudo ln -s /etc/nginx/sites-available/mediawiki /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Damit MediaWiki die kurzen Adressen auch selbst so schreibt, gehören zwei Zeilen in die LocalSettings.php (Weg A trägt $wgScriptPath bereits ein):
$wgScriptPath = "";
$wgArticlePath = "/$1";
$wgUsePathInfo = false;
Mit $wgArticlePath = "/$1" liegen die Artikel direkt unter der Domain: https://wiki.meine-domain.de/Sonnenblume. Der einzige Haken dabei: Ein Artikel darf nicht so heißen wie eine echte Datei im Wiki-Ordner (etwa „index.php"). Wer das ausschließen will, stellt den Artikeln ein festes Kürzel voran – dann lautet die Zeile $wgArticlePath = "/wiki/$1"; und im NGINX-Block wird aus location / ein location /wiki/.
Jetzt ist das Wiki unter https://wiki.meine-domain.de/ erreichbar.
Schritt 7: LocalSettings.php ergänzen
Ein paar Einstellungen lohnen sich von Anfang an. Sie werden am Ende der LocalSettings.php eingetragen:
# Hochladen von Bildern und Dateien erlauben
$wgEnableUploads = true;
# Zwischenspeicher im Arbeitsspeicher nutzen (aus php-apcu, Schritt 1)
$wgMainCacheType = CACHE_ACCEL;
# Hintergrundaufgaben nicht bei jedem Seitenaufruf abarbeiten,
# sondern über einen eigenen Zeitplan (Schritt 8)
$wgJobRunRate = 0;
Nach jeder Änderung an LocalSettings.php empfiehlt sich ein Blick auf die Wartungsseite Special:Version im Wiki – sie zeigt, ob alles fehlerfrei geladen wird.
Schritt 8: Wartungsaufgaben über einen Zeitplan
MediaWiki hat Aufgaben, die im Hintergrund laufen: Verweise auf umbenannte Seiten nachziehen, Vorschaubilder erzeugen, E-Mails verschicken. Wird $wgJobRunRate = 0 gesetzt (Schritt 7), muss ein Zeitplan diese Aufgaben regelmäßig anstoßen. Dafür wird ein Eintrag in der Zeitplan-Tabelle von www-data angelegt:
sudo -u www-data crontab -e
Und dort diese Zeile einfügen – sie arbeitet einmal pro Minute anstehende Aufgaben ab:
* * * * * /usr/bin/php /var/www/mediawiki/maintenance/run.php runJobs --maxjobs 20 > /dev/null 2>&1
Nach einem Versionswechsel (etwa von 1.46 auf 1.47) muss außerdem einmalig die Datenbank an die neue Ausgabe angepasst werden:
cd /var/www/mediawiki
sudo -u www-data php maintenance/run.php update
Sicherung und Wiederherstellung
Zu einem Wiki-Betrieb gehört eine regelmäßige, automatische Sicherung an einen zweiten Ort. Es gibt zwei Arten von Sicherung, die sich ergänzen.
Die vollständige Sicherung: pg_dump und der Bilder-Ordner
Der verlässlichste Weg ist ein vollständiger Export der PostgreSQL-Datenbank zusammen mit dem Ordner images/. Der Datenbank-Export enthält wirklich alles: Seiten, Versionen, Benutzerkonten, Einstellungen. Der Ordner images/ enthält die hochgeladenen Dateien, die nicht in der Datenbank liegen.
# Datenbank exportieren
sudo -u postgres pg_dump wiki > /home/thorsten/backup/wiki-$(date +%F).sql
# Hochgeladene Dateien sichern
sudo tar -czf /home/thorsten/backup/wiki-images-$(date +%F).tar.gz \
-C /var/www/mediawiki images
Beide Dateien gehören anschließend an einen anderen Ort – auf einen zweiten Server, in einen Objektspeicher oder in ein privates Git-Repository. Wie sich ein solcher Export über einen Zeitplan automatisieren lässt, steht im Kapitel Datenbank.
Die inhaltliche Sicherung: der XML-Export
MediaWiki kann zusätzlich alle Seiten samt Versionsgeschichte als eine einzige XML-Datei ausgeben. Diese Datei enthält nur die Texte – keine Benutzerkonten, keine hochgeladenen Bilder, keine Einstellungen. Sie ist dafür gut lesbar, versionierbar und lässt sich in jede andere MediaWiki-Installation einspielen.
cd /var/www/mediawiki
sudo -u www-data php maintenance/run.php dumpBackup --full > /home/thorsten/backup/seiten.xml
Betreibt man mehrere Wikis auf demselben Server (jedes in einem eigenen Ordner unter /var/www/), wird dieser Befehl für jedes Wiki einzeln ausgeführt.
Wiederherstellen
Eine vollständige Sicherung wird zurückgespielt, indem die Datenbank neu angelegt und der pg_dump-Export eingelesen wird:
sudo -u postgres dropdb wiki
sudo -u postgres createdb -E UTF8 -O wiki wiki
sudo -u postgres psql -d wiki -f /home/thorsten/backup/wiki-2026-09-06.sql
Anschließend den Bilder-Ordner aus dem tar-Archiv an seinen Platz zurücklegen.
Einen reinen XML-Export spielt man dagegen in eine bereits eingerichtete Installation ein. Danach müssen einige Verzeichnisse neu aufgebaut werden, die sich aus den Seiten ableiten:
cd /var/www/mediawiki
sudo -u www-data php maintenance/run.php importDump < /home/thorsten/backup/seiten.xml
sudo -u www-data php maintenance/run.php rebuildrecentchanges
sudo -u www-data php maintenance/run.php initSiteStats
sudo -u www-data php maintenance/run.php refreshLinks
importDumpliest die Seiten und ihre Versionen ein.rebuildrecentchangesbaut die Liste der letzten Änderungen neu auf.initSiteStatszählt Seiten und Bearbeitungen neu.refreshLinkserneuert die Verweise zwischen den Seiten und die Kategorien.
Für dieses Buch
MediaWiki läuft direkt auf dem Server (ohne Container, siehe Containerisierung von Software): PHP-FPM, PostgreSQL und NGINX nebeneinander, MediaWiki als Ordner unter /var/www/. Empfohlen wird die Einrichtung über die Textkonsole (Weg A in Schritt 5), weil dabei nie eine ungeschützte Einrichtungsseite im Netz steht.
Zwei Dinge gehören von Anfang an dazu: ein Zeitplan-Eintrag für die Hintergrundaufgaben (Schritt 8) und eine regelmäßige, automatische Sicherung – ein pg_dump der Datenbank plus der Ordner images/, an einen zweiten Ort.
Die schnelle Wortsuche über einen eigenen Suchdienst (Meilisearch oder Typesense) und die Bedeutungssuche mit pgvector sind eigene Bausteine; ihre Einrichtung und die Anbindung an MediaWiki über die passende Erweiterung sind im Kapitel Datenbank beschrieben.
Fazit
MediaWiki besteht aus vier zusammenspielenden Teilen: der Laufzeitumgebung PHP-FPM, der Datenbank PostgreSQL, einem Webserver davor und dem MediaWiki-Code selbst. Die Einrichtung läuft in klaren Schritten: PHP und seine Erweiterungen installieren, in PostgreSQL eine leere Datenbank anlegen, MediaWiki als fertiges Archiv herunterladen, die Dateirechte setzen, mit dem Konsolen-Programm install die LocalSettings.php erzeugen und zuletzt NGINX als verschlüsselten Zugang davorstellen. Weil Ubuntu 26.04 PHP 8.5 mitbringt, ist die Ausgabe 1.46 die richtige Wahl, bis 1.47 LTS erscheint. PostgreSQL wird von MediaWiki nur zweitrangig unterstützt – wer die PostgreSQL-Erweiterungen dieses Buchs nicht braucht, kann MediaWiki ebenso gut mit MariaDB betreiben.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
XWiki einrichten
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Das Kapitel Wissenssystem grenzt die Auswahl auf zwei Programme ein: MediaWiki und XWiki. XWiki ist die passende Wahl, wenn die Datenbank fest auf PostgreSQL steht (siehe Datenbank) oder wenn die Sammlung neben Fließtext auch feste Datenfelder führen soll – etwa eine Liste von Geräten mit Hersteller, Baujahr und Standort.
Dieses Kapitel zeigt Schritt für Schritt, wie XWiki auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) eingerichtet wird: von der Paketquelle über die Datenbank und die Ersteinrichtung bis zum öffentlichen Zugang über einen Webserver. Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen.
Was bei XWiki zusammenspielt
XWiki ist in der Programmiersprache Java geschrieben. Ein Java-Webprogramm läuft nicht allein, sondern braucht einen Anwendungsserver – ein Programm, das das Webprogramm lädt, am Laufen hält und Anfragen an es weiterreicht. Für XWiki ist das Apache Tomcat. Man kann sich Tomcat wie einen Motorraum vorstellen: XWiki ist der Motor, Tomcat das Gehäuse mit Halterungen, Anschlüssen und Anlasser drumherum.
Vier Teile arbeiten also zusammen:
- Java – die Laufzeitumgebung, die den Programmcode ausführt (siehe Laufzeitumgebung).
- Tomcat – der Anwendungsserver, der XWiki hält und auf einem Netzwerk-Port lauscht.
- PostgreSQL – die Datenbank, in der alle Seiten, Versionen und Einstellungen liegen (siehe Datenbank).
- Ein Webserver davor – nimmt die Anfragen aus dem Internet entgegen, verschlüsselt die Verbindung (HTTPS) und reicht sie an Tomcat weiter (siehe Webserver). In diesem Buch ist das NGINX.
Die XWiki-Pakete des Projekts bringen Java und Tomcat als Abhängigkeiten mit; man muss sie nicht getrennt installieren. PostgreSQL und den Webserver richtet man wie in den genannten Kapiteln beschrieben ein.
Voraussetzungen
Bevor es losgeht, sollte Folgendes vorhanden sein:
- Ein Server mit Ubuntu 26.04 und mindestens 2 GB freiem Arbeitsspeicher allein für XWiki. Weniger führt im Betrieb zu Abstürzen.
- PostgreSQL ist eingerichtet (siehe Datenbank). Falls die Datenbank für XWiki noch fehlt, legt der Installationsassistent sie in Schritt 3 selbst an.
- Eine Domain, die auf die IP-Adresse des Servers zeigt, zum Beispiel
wiki.meine-domain.de. Sie wird für das SSL-Zertifikat und den Webserver gebraucht. - NGINX ist installiert (siehe Webserver).
Schritt 1: Die Paketquelle von XWiki eintragen
XWiki wird nicht aus den normalen Ubuntu-Paketquellen installiert, sondern aus einer eigenen Paketquelle, die das XWiki-Projekt selbst betreibt. Damit apt diese Quelle nutzen kann, sind zwei Dateien nötig: ein digitaler Schlüssel, mit dem Ubuntu die Echtheit der Pakete prüft, und eine Datei mit der Adresse der Quelle.
sudo wget https://maven.xwiki.org/xwiki-keyring.gpg -O /usr/share/keyrings/xwiki-keyring.gpg
sudo wget "https://maven.xwiki.org/stable/xwiki-stable.list" -O /etc/apt/sources.list.d/xwiki-stable.list
Die Quelle stable enthält alle fertigen Versionen ohne Vorabausgaben. Wer lieber eine Version mit besonders langer Pflegezusage möchte, ersetzt in beiden Zeilen stable durch lts (englisch für „Long Term Support", also Langzeitunterstützung).
Danach die Paketliste neu einlesen, damit die neue Quelle bekannt wird:
sudo apt update
Schritt 2: Nach verfügbaren Versionen sehen
Ein kurzer Blick zeigt, welche XWiki-Pakete jetzt zur Auswahl stehen:
apt-cache search xwiki
Und welche Version das Paket für PostgreSQL mitbringt:
apt-cache policy xwiki-tomcat10-pgsql
Das Paket xwiki-tomcat10-pgsql ist ein Sammelpaket: Es zieht XWiki selbst, den Anwendungsserver Tomcat 10, die Java-Laufzeit und die Anbindung an PostgreSQL in einem Rutsch nach.
Schritt 3: XWiki installieren
sudo apt install xwiki-tomcat10-pgsql
Während der Installation stellt der Assistent einige Fragen zur Datenbank:
- Ob die Datenbank automatisch eingerichtet werden soll – hier Ja wählen.
- Den Namen der Datenbank und des Datenbankbenutzers (Vorschlag: beides
xwiki). - Ein Passwort für diesen Datenbankbenutzer. Es wird gleich zweimal abgefragt und danach automatisch in die XWiki-Konfiguration eingetragen.
Sind die Angaben gemacht, legt der Assistent die leere Datenbank an, verbindet XWiki damit und startet Tomcat. Für die nächsten Schritte wird Tomcat zunächst wieder angehalten:
sudo systemctl stop tomcat10
Nach der Installation liegen die wichtigsten Dateien an diesen Stellen:
| Datei oder Ordner | Inhalt |
|---|---|
/etc/xwiki/ | Konfiguration von XWiki (unter anderem die Datenbankverbindung) |
/etc/tomcat10/server.xml | Einstellungen des Anwendungsservers, zum Beispiel der Port |
/etc/default/tomcat10 | Starteinstellungen für Tomcat, zum Beispiel der Arbeitsspeicher |
/var/lib/xwiki/ | Daten von XWiki, etwa hochgeladene Dateien |
Schritt 4: Arbeitsspeicher für Tomcat festlegen
Java teilt sich seinen Arbeitsspeicher nicht nach Bedarf zu, sondern bekommt eine feste Obergrenze vorgegeben. Ist sie zu niedrig, bricht XWiki unter Last ab. Für eine kleine bis mittlere Sammlung sind 2 GB ein guter Startwert. Die Grenze wird in der Datei /etc/default/tomcat10 gesetzt:
sudo nano /etc/default/tomcat10
Dort die Zeile mit JAVA_OPTS suchen oder ergänzen, sodass sie so aussieht:
JAVA_OPTS="-Xms512m -Xmx2048m -XX:+UseG1GC"
-Xms512mist der Speicher, den Java gleich beim Start belegt.-Xmx2048mist die Obergrenze – hier 2048 MB, also 2 GB. Auf einem größeren Server darf dieser Wert höher liegen, aber nie an die Grenze des gesamten Arbeitsspeichers reichen; das Betriebssystem und PostgreSQL brauchen ebenfalls Platz.-XX:+UseG1GCwählt ein Aufräumverfahren, das für Programme mit vielen gleichzeitigen Zugriffen gut geeignet ist.
Schritt 5: Tomcat nur auf den eigenen Server hören lassen
Von Haus aus lauscht Tomcat auf Port 8080 und nimmt Verbindungen aus dem ganzen Netz an. Beides wird geändert: Der Port wird auf 9000 gelegt (damit er nicht mit anderen Diensten kollidiert), und Tomcat soll nur noch auf 127.0.0.1 hören – das ist der Rechner selbst, von außen nicht erreichbar.
Der Grund für die zweite Einschränkung: Beim allerersten Aufruf zeigt XWiki einen Einrichtungsassistenten („Distribution Wizard"), der das Administratorkonto anlegt. Solange dieser Assistent nicht durchlaufen ist, darf die Seite auf keinen Fall öffentlich erreichbar sein. Statt den Port kurz in der Firewall zu öffnen, bleibt er komplett auf dem Server und wird für die Ersteinrichtung über einen verschlüsselten Tunnel erreicht (Schritt 6).
sudo nano /etc/tomcat10/server.xml
In der Datei den folgenden Abschnitt suchen:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
Und ihn so ändern – der Port wird zu 9000, und das neue Attribut address bindet den Dienst an den eigenen Rechner:
<Connector address="127.0.0.1" port="9000" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
Die Bindung an 127.0.0.1 bleibt dauerhaft bestehen. NGINX läuft auf demselben Server und erreicht Tomcat über diese lokale Adresse; ein Zugang von außen über Port 9000 ist im normalen Betrieb nie nötig.
Schritt 6: Die Ersteinrichtung über einen SSH-Tunnel
Jetzt Tomcat starten:
sudo systemctl start tomcat10
XWiki läuft nun, ist aber nur vom Server selbst erreichbar. Um den Einrichtungsassistenten trotzdem im Browser des eigenen Rechners zu öffnen, wird ein SSH-Tunnel aufgebaut. Der folgende Befehl wird auf dem eigenen Rechner eingegeben, nicht auf dem Server:
ssh -L 9000:127.0.0.1:9000 admin@SERVER-IP
Der Teil -L 9000:127.0.0.1:9000 heißt „Local Forwarding", auf Deutsch etwa „örtliche Weiterleitung". Er öffnet auf dem eigenen Rechner den Port 9000 und verbindet ihn durch die verschlüsselte SSH-Verbindung mit Port 9000 auf dem Server. Solange dieses SSH-Fenster offen ist, landet jeder Aufruf von http://localhost:9000/ im Browser des eigenen Rechners bei Tomcat auf dem Server.
Nun im Browser http://localhost:9000/ aufrufen. Der Einrichtungsassistent erscheint. Er führt durch drei Punkte:
- Ein Passwort für das Administratorkonto festlegen.
- Die Grundausstattung („Flavor") installieren – die Standardauswahl übernehmen.
- Am Ende bestätigen, dass die Einrichtung abgeschlossen ist.
Danach das SSH-Fenster schließen; der Tunnel wird nicht mehr gebraucht.
Schritt 7: NGINX als Reverse Proxy einrichten
Damit die Wissenssammlung öffentlich und verschlüsselt erreichbar ist, kommt NGINX davor. Es nimmt die Anfragen auf Port 443 (HTTPS) entgegen und reicht sie an Tomcat auf Port 9000 weiter. Diese Rolle heißt Reverse Proxy (siehe Webserver).
Zuerst das SSL-Zertifikat besorgen. Wie das mit Certbot und Let's Encrypt geht, steht ausführlich im Kapitel Webserver; für eine feste Domain genügt:
sudo certbot certonly --nginx -d wiki.meine-domain.de
Dann die Konfigurationsdatei /etc/nginx/sites-available/xwiki anlegen:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name wiki.meine-domain.de;
ssl_certificate /etc/letsencrypt/live/wiki.meine-domain.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wiki.meine-domain.de/privkey.pem;
# Große Anhänge zulassen
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:9000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
listen [::]:80;
server_name wiki.meine-domain.de;
# Alle unverschlüsselten Aufrufe auf HTTPS umleiten
return 301 https://$host$request_uri;
}
Die vier proxy_set_header-Zeilen geben Tomcat weiter, wer die Anfrage ursprünglich gestellt hat und dass sie über HTTPS kam. Ohne sie baut XWiki falsche Links und hält jeden Besucher für den Server selbst.
Die Datei aktiv schalten, prüfen und übernehmen:
sudo ln -s /etc/nginx/sites-available/xwiki /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Jetzt ist die Wissenssammlung unter https://wiki.meine-domain.de/ erreichbar.
Schritt 8: Port 9000 in der Firewall sperren
Die Bindung an 127.0.0.1 aus Schritt 5 schützt Port 9000 bereits auf Netzwerkebene. Als zweite, unabhängige Absicherung wird der Port zusätzlich in der Firewall gesperrt – für den Fall, dass die Bindung später versehentlich wieder geöffnet wird. Ubuntu bringt dafür UFW mit („Uncomplicated Firewall", also unkomplizierte Firewall):
sudo ufw allow "Nginx Full"
sudo ufw deny 9000/tcp
sudo ufw enable
sudo ufw status verbose
Nginx Fullöffnet die Ports 80 und 443 für den Webserver.deny 9000/tcpschließt Port 9000 ausdrücklich. Bei der UFW-Standardeinstellung (alles Eingehende ist ohnehin gesperrt) ist diese Regel technisch überflüssig, macht die Absicht aber inufw statussichtbar.
Für spätere Wartungszugriffe direkt auf Port 9000 – etwa zur Fehlersuche ohne NGINX – eignet sich weiterhin der SSH-Tunnel aus Schritt 6, ohne dass ein Port geöffnet werden muss.
Noch strikter: ein Unix-Socket statt eines Ports
Statt eines Netzwerk-Ports kann Tomcat auch über eine Socket-Datei ansprechbar sein – einen sogenannten Unix-Socket. Das ist ein besonderer Eintrag im Dateisystem, über den zwei Programme auf demselben Rechner miteinander reden, ganz ohne Netzwerk. Der Vorteil: Es gibt keinen Port, der aus Versehen geöffnet werden könnte, und die Zugriffsrechte regelt das Dateisystem.
In Tomcat wird dazu in /etc/tomcat10/server.xml der <Connector> ohne Port, aber mit einem Pfad zur Socket-Datei angelegt:
<Connector protocol="HTTP/1.1"
unixDomainSocketPath="/var/lib/tomcat10/xwiki.sock"
unixDomainSocketPathPermissions="rw-rw----"
connectionTimeout="20000" />
Damit NGINX (das als Benutzer www-data läuft) die Socket-Datei benutzen darf, wird dieser Benutzer in die Gruppe tomcat aufgenommen:
sudo usermod -aG tomcat www-data
sudo systemctl restart tomcat10 nginx
In NGINX verweist proxy_pass dann auf die Socket-Datei statt auf eine Adresse:
location / {
proxy_pass http://unix:/var/lib/tomcat10/xwiki.sock:/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Auch die Ersteinrichtung lässt sich über einen Tunnel zu dieser Socket-Datei erledigen. SSH kann einen lokalen Port mit einer entfernten Socket-Datei verbinden. Der Befehl auf dem eigenen Rechner lautet dann:
ssh -L 9000:/var/lib/tomcat10/xwiki.sock admin@SERVER-IP
Der Unterschied zu Schritt 6: Hinter dem lokalen Port 9000 steht diesmal kein entfernter Port, sondern der Pfad /var/lib/tomcat10/xwiki.sock auf dem Server. Im Browser wird weiterhin http://localhost:9000/ aufgerufen; die Anfrage läuft durch den Tunnel und endet an der Socket-Datei, an der Tomcat lauscht.
Der Socket-Weg ist etwas aufwendiger einzurichten und bei der Fehlersuche unhandlicher (man kann nicht eben mit einem Browser auf einen Port schauen). Wer es einfach halten will, bleibt bei Port 9000 auf 127.0.0.1 aus Schritt 5. Wer jede Möglichkeit eines offenen Ports ausschließen möchte, nimmt den Socket.
Für dieses Buch
XWiki bringt eine eigene Volltextsuche mit (auf Basis von Apache Solr); der separate Suchdienst Meilisearch oder Typesense aus dem Kapitel Datenbank ist auf MediaWiki gemünzt und für XWiki nicht nötig. Die Bedeutungssuche mit pgvector bleibt möglich, ist bei XWiki aber ein eigenes Zusatzprojekt und kein fertiger Baustein.
Empfohlen wird der Betrieb direkt auf dem Server (ohne Container, siehe Containerisierung von Software): Java, Tomcat, XWiki und PostgreSQL laufen nebeneinander, NGINX steht davor. Für den Zugang von außen genügt Port 9000 auf 127.0.0.1; der Unix-Socket ist die strengere, aber aufwendigere Alternative.
Zwei Dinge gehören von Anfang an zum Betrieb dazu: eine ausreichend hohe Speichergrenze für Tomcat (Schritt 4) und eine regelmäßige, automatische Sicherung der PostgreSQL-Datenbank an einen zweiten Ort (pg_dump, siehe Datenbank).
Fazit
XWiki besteht aus vier zusammenspielenden Teilen: der Java-Laufzeit, dem Anwendungsserver Tomcat, der Datenbank PostgreSQL und einem Webserver davor. Die Installation läuft über die eigene Paketquelle des XWiki-Projekts; das Sammelpaket xwiki-tomcat10-pgsql bringt alles Nötige mit und fragt bei der Einrichtung die Datenbankdaten ab. Tomcat wird auf Port 9000 gelegt und an 127.0.0.1 gebunden, sodass die unfertige Installation nicht öffentlich erreichbar ist; die einmalige Kontoanlage im Einrichtungsassistenten geschieht über einen SSH-Tunnel. Anschließend stellt NGINX als Reverse Proxy die verschlüsselte, öffentliche Adresse bereit, und die Firewall sperrt Port 9000 zusätzlich ab. Wer den Port ganz vermeiden will, lässt Tomcat über eine Unix-Socket-Datei sprechen.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Content-Management-System
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Ein Content-Management-System (kurz CMS, wörtlich „System zur Verwaltung von Inhalten") ist ein fertiges Programm, mit dem man die Texte, Bilder und Seiten einer Webseite pflegt, ohne sie programmieren zu müssen. Es ist – wie das Wissenssystem – die oberste Schicht des Web Stacks: Der Besucher sieht nur die fertige Webseite, darunter arbeiten die Datenbank, in der alle Inhalte dauerhaft liegen, und der Webserver, der die Seiten ausliefert.
Der Unterschied zum Wissenssystem liegt im Zweck. Ein Wiki wie MediaWiki ist auf viele gleichberechtigte Bearbeiter und verlinkten Fließtext ausgelegt. Ein CMS ist auf eine Redaktion ausgelegt: Wenige Personen mit festen Rollen pflegen Seiten, die einem Freigabeweg folgen und in einem festen Seitenaufbau erscheinen – eine Firmenseite, ein Nachrichtenportal, ein Behördenauftritt. Dieses Kapitel trifft die Wahl für den Fall, dass die Seite im Kern ein solcher redaktioneller Auftritt ist. Der Begriff CMS ist im Kapitel Webframework bereits kurz gegen die Begriffe „Anwendung" und „Framework" abgegrenzt.
Die Ausgangsfrage des Autors ist dieselbe wie beim Wissenssystem: Welches CMS ist industrietauglich, sehr robust, verwaltet eine Million Texteinträge mit verschiedenen Inhaltstypen und Datensätzen, geht dabei nicht kaputt, ist schnell und lässt sich vergleichend messen, hat den höchsten Reifegrad und läuft direkt auf dem Server – wobei als Datenbank ausschließlich PostgreSQL vorgesehen ist und die Software quelloffen sein soll, auch im Sinne quelloffener Software mit einem Unternehmen dahinter.
Was schon feststeht
Vier Dinge sind durch die vorigen Kapitel bereits entschieden und schränken die Auswahl ein:
- Die Datenbank ist PostgreSQL. Das Kapitel Datenbank richtet PostgreSQL samt der Erweiterungen für die Suche ein. Ein CMS, das PostgreSQL nicht unterstützt, scheidet aus – auch dann, wenn es sonst gut passen würde.
- Es läuft „auf dem Metall". Das Programm wird direkt auf dem Server installiert, ohne Zwischenschicht wie einen Container (siehe Containerisierung von Software). Es muss sich also als normales Paket oder als entpacktes Archiv auf Ubuntu einrichten lassen.
- Es wird selbst betrieben. Die Inhalte bleiben auf dem eigenen Server. Bezahldienste in fremder Hand kommen nicht in Frage.
- Es ist quelloffen. Der Quelltext muss offenliegen. Ein Unternehmen im Hintergrund, das mit einer kostenpflichtigen Zusatzausgabe oder mit Betreuung Geld verdient, ist ausdrücklich in Ordnung – solange die selbst betriebene Fassung frei nutzbar bleibt. Bei einigen jüngeren Programmen ist genau dieser Punkt inzwischen die entscheidende Frage; dazu unten mehr.
Die Kriterien der Frage
Die Begriffe der Ausgangsfrage sind im Kapitel Wissenssystem bereits im Einzelnen eingeordnet; sie gelten für ein CMS unverändert. Eine Million Einträge sind für ein ausgereiftes System eine kleine bis mittlere Größe. „Industrietauglich" und „höchster Reifegrad" meinen: seit vielen Jahren ohne Unterbrechung gepflegt, Sicherheitslücken zügig geschlossen, geregelter Versionsumstieg, genug andere Betreiber. „Robust" heißt: Ein Absturz zerreißt keine Daten, ein Programmfehler legt nicht alles lahm.
Ein Punkt verdient für ein CMS besondere Beachtung: „verschiedene Inhaltstypen und Datensätze". Bei einem CMS ist das keine Randfunktion, sondern die eigentliche Kerndisziplin. Ein Inhaltstyp ist eine Vorlage mit festen Feldern – etwa „Gerät" mit den Feldern Hersteller, Baujahr und Standort –, aus der sich sortierbare und filterbare Listen bauen lassen. An diesem Punkt unterscheiden sich die Kandidaten am stärksten.
Die Kandidaten im Überblick
Für eine große, selbst betriebene Webseite kommen die folgenden Systeme in Frage. Entscheidend ist die Spalte „Datenbank".
| System | Technik | Datenbank | Seit | Stärke |
|---|---|---|---|---|
| WordPress | PHP | nur MySQL/MariaDB | 2003 | mit Abstand verbreitetstes CMS, riesiges Erweiterungsangebot |
| Drupal | PHP | PostgreSQL, MySQL/MariaDB, SQLite | 2001 | strukturierte Inhalte von Haus aus, auf große Auftritte ausgelegt |
| TYPO3 | PHP | PostgreSQL, MySQL/MariaDB u. a. | 1998 | im deutschsprachigen Raum verbreitetes Unternehmens-CMS, feste LTS-Pflege |
| Joomla | PHP | MySQL/MariaDB; PostgreSQL nur eingeschränkt | 2005 | Mittelweg zwischen WordPress und Drupal |
| Plone | Python | eigene Objektdatenbank (ZODB) | 2001 | strenge Rechteverwaltung, im Behördenumfeld verbreitet |
| Strapi | JavaScript (Node.js) | PostgreSQL (empfohlen), MySQL, SQLite | 2015 | größtes Ökosystem unter den „Headless"-Systemen |
| Directus | JavaScript (Node.js) | PostgreSQL, MySQL u. a. | 2015 | legt sich über eine bestehende SQL-Datenbank |
| Payload | JavaScript (Node.js) | PostgreSQL, SQLite, MongoDB | 2022 | eng mit dem Frontend-Werkzeug Next.js verzahnt |
Die letzten drei sind Headless-Systeme (englisch „kopflos"). Ein solches CMS liefert nur die Inhalte über eine Schnittstelle und keine fertige Webseite; die Anzeigeseite ist ein eigenes Programm, das man mit einem Webframework selbst baut oder als statische Seite erzeugt (siehe Docs-as-Code).
Kandidaten, die ausscheiden
- WordPress unterstützt offiziell nur MySQL oder MariaDB. Für PostgreSQL gibt es nur eine Zusatzerweiterung, die nicht mit den aktuellen WordPress-Versionen Schritt hält, und sehr viele Erweiterungen setzen MySQL-eigene Befehle voraus. Mit der Festlegung auf PostgreSQL ist WordPress damit außen vor – so verbreitet es auch ist.
- Plone benutzt keine übliche relationale Datenbank, sondern legt seine Inhalte als Objekte in einer eigenen Ablage (ZODB) ab. Man kann diese Ablage zwar in PostgreSQL speichern lassen, doch dann ist PostgreSQL nur ein Behälter für Plones eigenes Format und keine Datenbank, die man normal abfragen kann. Das passt nicht zu einem Aufbau, der bewusst auf PostgreSQL setzt.
- Joomla kann PostgreSQL seit einigen Jahren, doch die Unterstützung gilt als lückenhaft und wird wenig getestet; empfohlen sind MySQL oder MariaDB. Das ist dasselbe Problem wie bei MediaWiki im Kapitel Wissenssystem: ein wenig begangener Weg, bei dem man vor jeder Erweiterung prüfen muss, ob sie mitspielt.
Der Filter „nur PostgreSQL"
Übrig bleiben Drupal, TYPO3, Strapi, Directus und Payload. Hier ist ein genauer Blick nötig.
- Drupal unterstützt PostgreSQL gleichwertig zu MySQL; die aktuelle Hauptversion setzt PostgreSQL 16 oder neuer voraus. Für die eingebaute Suche erwartet Drupal die Erweiterung
pg_trgm– dieselbe, die das Kapitel Datenbank ohnehin einrichtet. - TYPO3 spricht die Datenbank über eine Zwischenschicht an (Doctrine DBAL) und unterstützt PostgreSQL 13 und neuer. Das funktioniert zuverlässig, ist aber etwas seltener anzutreffen als der Weg über MySQL.
- Strapi, Directus und Payload sind von Grund auf für PostgreSQL gebaut. Strapi und Payload laufen zusätzlich auf anderen Datenbanken; Directus ist ausdrücklich dafür gemacht, sich direkt auf eine bestehende SQL-Datenbank zu setzen und deren Tabellen zu lesen.
Der Filter „industrietauglich, höchster Reifegrad"
- Drupal wird seit 2001 entwickelt, betreibt Auftritte von Regierungen, Universitäten und großen Nachrichtenseiten, hat einen festen Veröffentlichungsplan, ein eigenes Sicherheitsteam und einen dokumentierten Weg für den Versionsumstieg.
- TYPO3 wird seit 1998 entwickelt und ist das verbreitete Unternehmens-CMS im deutschsprachigen Raum. Es hat einen besonders strengen LTS-Plan – die Version 14 LTS erschien im April 2026 und wird mehrere Jahre mit kostenlosen Aktualisierungen und danach optional gegen Bezahlung weiter gepflegt – sowie ein dichtes Netz an Agenturen und die TYPO3 GmbH für kommerzielle Betreuung.
Strapi ist das ausgereifteste der Headless-Systeme: ein Unternehmen im Hintergrund, ein quelloffener Kern und eine große Gemeinschaft. Es ist aber jünger und hat für sehr große Sammlungen einen kürzeren Erfolgsnachweis. Directus ist solide, Payload ist mit Baujahr 2022 das jüngste und am wenigsten erprobte.
Der eigentliche Unterschied: Wie entstehen die Inhaltstypen?
An diesem Punkt entscheidet sich die Wahl, denn hier greift das Kriterium „verschiedene Inhaltstypen und Datensätze".
- Drupal nennt sie „Inhaltstypen" und „Felder". Man legt im Browser einen Typ „Gerät" mit den Feldern Hersteller, Baujahr und Standort an und baut daraus mit dem eingebauten Werkzeug „Views" sortierbare und filterbare Listen – ohne eine Zeile Programmcode. Das ist Drupals Kernstärke und deckt sich fast wörtlich mit der Anforderung.
- TYPO3 kann dasselbe, braucht dafür aber etwas mehr Einrichtung (über die eingebauten „Content Blocks" oder eine Erweiterung).
- Die Headless-Systeme Strapi, Directus und Payload sind vollständig um Inhaltstypen herum gebaut: Man beschreibt sie in der Verwaltungsoberfläche oder im Code und bekommt sofort eine Schnittstelle darauf. Nur bekommt man daraus keine Webseite – die Anzeigeseite muss man selbst bauen.
Daraus folgt eine klare Trennlinie: Soll die Seite ein sofort nutzbarer redaktioneller Auftritt mit strukturierten Inhalten sein, ist Drupal die natürliche Wahl. Ist die Anzeigeseite ohnehin ein eigenes Programm – ein Shop, eine App, eine statisch gebaute Seite –, ist ein Headless-System mit Strapi der sauberere Schnitt.
Zur Geschwindigkeit: Was Vergleichsmessungen taugen
Für CMS gilt dasselbe wie für Wissenssysteme und Webframeworks: Vergleichsmessungen sagen wenig über den Alltag aus. Eine Million Seiten sind für PostgreSQL eine normale Größe. Über die Antwortzeit entscheiden drei Dinge, die alle unterhalb des CMS liegen:
- Die richtigen Indizes in der Datenbank – der Unterschied ist oft der Faktor Tausend.
- Ein Zwischenspeicher für fertige Seiten, entweder im CMS selbst, in einem vorgeschalteten Zwischenspeicher (etwa Varnish) oder direkt im Webserver. Ist eine Seite einmal erzeugt und wird kurz vorgehalten, spielt die Geschwindigkeit von CMS und Datenbank für den nächsten Abruf keine Rolle mehr.
- Sparsames Laden – Listen seitenweise holen statt alles auf einmal.
Drupal wie TYPO3 bringen einen mehrstufigen Zwischenspeicher von Haus aus mit. Was ein CMS-Vergleich am Ende misst, ist meist nur, wie beherzt jedes System im Auslieferungszustand zwischenspeichert – nicht die eigentliche Geschwindigkeit.
Für dieses Buch
Der Web Stack dieses Buchs läuft auf MediaWiki – einem Wiki, keinem CMS –, weil die Sammlung im Kern ein gemeinsam bearbeitetes Nachschlagewerk ist. Ein CMS wird erst zum Thema, wenn daneben ein zweiter, redaktioneller Auftritt entsteht: eine Firmenseite, ein Blog, ein Portal.
Für diesen Fall gilt, mit der Festlegung auf PostgreSQL:
- Drupal ist die Empfehlung: PostgreSQL wird offiziell und gleichwertig unterstützt (mit der Erweiterung
pg_trgm, die im Kapitel Datenbank ohnehin eingerichtet wird), strukturierte Inhaltstypen sind eingebaut, und das System ist seit 2001 ausgereift. Drupal läuft auf derselben PHP-Laufzeitumgebung, die MediaWiki ohnehin braucht. - TYPO3 ist die Alternative, besonders wenn deutschsprachige Agenturbetreuung wichtig ist.
- Strapi (Headless) ist die Wahl, wenn die Anzeigeseite ein eigenes Programm ist.
- WordPress, Joomla und Plone scheiden an der Festlegung auf PostgreSQL aus.
Ein Blick auf die Lizenzen lohnt sich: Drupal, TYPO3 und WordPress stehen unter der GPL und sind vollständig frei. Strapi hat einen quelloffenen Kern (MIT-Lizenz) und eine kostenpflichtige Zusatzausgabe. Directus hat 2023 und erneut 2025 die Lizenz gewechselt: Die selbst betriebene Fassung ist für kleinere Betreiber (unter einer festgelegten Umsatz- und Mitarbeitergrenze) kostenlos, jede Version wird nach vier Jahren vollständig frei – aber oberhalb der Grenze ist eine kostenpflichtige Lizenz nötig. Wer Directus einsetzen will, sollte die aktuellen Bedingungen vorher prüfen.
Fazit
Ein CMS ist die oberste Schicht des Web Stacks für einen redaktionellen Auftritt – im Unterschied zum Wiki, das für gemeinsam bearbeiteten Fließtext gedacht ist. Die Festlegung auf PostgreSQL, auf den Betrieb direkt auf dem Server und auf höchsten Reifegrad grenzt die Auswahl auf zwei Systeme ein: Drupal und TYPO3. Drupal ist die Wahl, wenn die Seite ein sofort nutzbarer Auftritt mit strukturierten Inhaltstypen sein soll; TYPO3 ist die Alternative im deutschsprachigen Unternehmensumfeld. Ist die Anzeigeseite ein eigenes Programm, ist ein Headless-System mit Strapi der klarere Schnitt. WordPress, Joomla und Plone scheiden an PostgreSQL aus. Eine Million Einträge sind für alle verbliebenen Systeme unproblematisch; ob die Seite schnell bleibt, entscheidet nicht das CMS, sondern die Indizes in der Datenbank und ein Zwischenspeicher für fertige Seiten.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Drupal einrichten
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Das Kapitel Content-Management-System grenzt die Auswahl für einen redaktionellen Webauftritt mit der Festlegung auf PostgreSQL auf zwei Systeme ein und empfiehlt für den Regelfall Drupal: PostgreSQL wird offiziell und gleichwertig unterstützt, strukturierte Inhaltstypen sind eingebaut, und das System ist seit 2001 ausgereift. Drupal läuft zudem auf derselben PHP-Laufzeitumgebung, die MediaWiki für die Wissenssammlung ohnehin braucht.
Dieses Kapitel zeigt Schritt für Schritt, wie Drupal auf einem Server mit Ubuntu 26.04 LTS (siehe Betriebssystem) eingerichtet wird: von der Laufzeitumgebung über die Datenbank und die Installation ohne Browser bis zum öffentlichen, verschlüsselten Zugang über einen Webserver. Alle Befehle werden in der Textkonsole des Servers eingegeben. Das vorangestellte sudo bedeutet: mit Verwaltungsrechten ausführen.
Die Beispiele gehen davon aus, dass neben der Wissenssammlung ein zweiter, redaktioneller Auftritt entstehen soll – etwa ein Portal oder ein Nachrichtenbereich – und dieser unter einer eigenen Unterdomain wie portal.meine-domain.de erreichbar ist.
Was bei Drupal zusammenspielt
Drupal ist eine Sammlung von Dateien in der Programmiersprache PHP. PHP-Code läuft nicht allein, sondern braucht ein Programm auf dem Server, das ihn ausführt – die Laufzeitumgebung (siehe Laufzeitumgebung). Drupal selbst speichert nichts dauerhaft; es baut Seiten zusammen und legt alle Inhalte in einer Datenbank ab.
Fünf Teile arbeiten zusammen:
- PHP-FPM – die Laufzeitumgebung, die den Drupal-Code ausführt. „FPM" steht für „FastCGI Process Manager": PHP läuft als Hintergrunddienst, an den der Webserver die Anfragen weiterreicht (siehe Laufzeitumgebung).
- Composer – das Paketwerkzeug von PHP. Drupal wird nicht als fertiges Archiv heruntergeladen, sondern von Composer aus vielen Einzelbausteinen zusammengestellt. Composer hält diese Bausteine später auch aktuell.
- PostgreSQL – die Datenbank, in der alle Seiten, alle früheren Fassungen, alle Benutzerkonten und die gesamte Konfiguration liegen (siehe Datenbank). Fällt sie aus, ist die Seite leer.
- Ein Webserver davor – nimmt die Anfragen aus dem Internet entgegen, verschlüsselt die Verbindung (HTTPS) und reicht die Seiten an PHP-FPM weiter (siehe Webserver). In diesem Buch ist das NGINX.
- Drush – die Kommandozeilen-Shell für Drupal. Damit wird Drupal ohne Browser eingerichtet, aktualisiert und gesichert. „Drush" ist die Kurzform von „Drupal Shell".
Welche Version
Drupal bringt etwa jedes halbe Jahr eine neue Nebenausgabe heraus und alle zwei Jahre eine neue Hauptausgabe. Die aktuelle Hauptausgabe ist Drupal 11 (erschienen im August 2024); zum Zeitpunkt dieses Kapitels ist 11.4 die neueste Nebenausgabe.
Wie bei MediaWiki gibt es einen Zusammenhang mit der PHP-Fassung, den man kennen sollte:
- Drupal 11 verlangt mindestens PHP 8.3; als beste Wahl gilt PHP 8.4. Die Fassung 11.4 läuft auch mit dem PHP 8.5, das Ubuntu 26.04 mitbringt (siehe Laufzeitumgebung) – alle Bestandteile von Drupal 11.4 sind für PHP 8.5 vorbereitet.
- Drupal 12 wird PHP 8.5 und PostgreSQL 18 zur Pflicht machen – genau die Fassungen, die auf dem hier beschriebenen Server ohnehin laufen. Drupal 12 ist ab Mitte September 2026 als Testfassung verfügbar; die fertige Ausgabe wird zum Jahresende 2026 erwartet. Drupal 11 wird danach noch bis mindestens Mitte 2028 mit Sicherheitskorrekturen versorgt.
Daraus ergibt sich für dieses Buch: mit der aktuellen Ausgabe Drupal 11 starten und auf Drupal 12 wechseln, sobald diese fertig erschienen ist. Der Umstieg ist dann klein, weil Server, PHP und Datenbank die Anforderungen von Drupal 12 bereits erfüllen. Wer strikt auf der offiziell empfohlenen PHP-Fassung bleiben möchte, richtet zusätzlich PHP 8.4 über die Paketquelle packages.sury.org ein und lässt Drupal über einen eigenen PHP-FPM-Pool auf dieser Fassung laufen (Schritt 6).
Bei der Datenbank gibt es keinen Konflikt: Drupal 11 verlangt PostgreSQL 16 oder neuer, und das Kapitel Datenbank richtet ohnehin PostgreSQL 18 ein.
Voraussetzungen
Bevor es losgeht, sollte Folgendes vorhanden sein:
- Ein Server mit Ubuntu 26.04 und Zugang über SSH, mit mindestens 1 GB freiem Arbeitsspeicher für Drupal.
- PostgreSQL ist eingerichtet (siehe Datenbank). Die leere Datenbank für Drupal wird in Schritt 3 angelegt.
- Composer ist eingerichtet (siehe Laufzeitumgebung, Abschnitt „Composer").
- Eine Domain oder Unterdomain, die auf die IP-Adresse des Servers zeigt, zum Beispiel
portal.meine-domain.de. Sie wird für das SSL-Zertifikat und den Webserver gebraucht. - NGINX ist installiert (siehe Webserver).
Schritt 1: PHP-FPM und die benötigten Erweiterungen installieren
Drupal braucht PHP-FPM und eine Reihe von PHP-Erweiterungen. Jede Erweiterung erledigt eine Teilaufgabe: php-pgsql verbindet PHP mit PostgreSQL, php-mbstring behandelt Texte mit Umlauten korrekt, php-gd verkleinert hochgeladene Bilder, php-intl sorgt für die richtige Sortierung fremdsprachiger Namen, php-xml und php-curl werden für den Datenaustausch gebraucht.
sudo apt update
sudo apt install php-fpm php-cli \
php-pgsql php-mbstring php-xml php-curl php-gd php-intl php-zip \
php-apcu php-opcache \
git unzip
# Zeigt die installierte Version zur Kontrolle an
php -v
php-apcu und php-opcache sind Zwischenspeicher im Arbeitsspeicher; Drupal wird damit spürbar schneller. git und unzip braucht Composer, um die Bausteine herunterzuladen.
Zwei Einstellungen in PHP sollten für Drupal angehoben werden: die Obergrenze für den Arbeitsspeicher eines einzelnen Aufrufs und die maximale Größe eines Datei-Uploads. Beides steht in der Datei /etc/php/8.5/fpm/php.ini:
sudo nano /etc/php/8.5/fpm/php.ini
Dort diese Werte suchen und anpassen:
memory_limit = 256M
upload_max_filesize = 100M
post_max_size = 100M
Danach PHP-FPM neu starten, damit die Änderungen greifen:
sudo systemctl restart php8.5-fpm
Schritt 2: Datenbank und Datenbankbenutzer in PostgreSQL anlegen
PostgreSQL legt bei der Installation einen Systembenutzer postgres an, der die Datenbank verwaltet. Über ihn werden ein eigener Datenbankbenutzer für Drupal und eine leere Datenbank angelegt, die ihm gehört. Die Namen (hier drupal) sind frei wählbar, müssen aber später bei der Installation genau so angegeben werden.
# Datenbankbenutzer anlegen, dabei nach einem Passwort fragen
sudo -u postgres createuser --pwprompt drupal
# Datenbank mit UTF-8-Zeichensatz anlegen, Eigentümer ist "drupal"
sudo -u postgres createdb -E UTF8 -O drupal drupal
UTF8 ist der Zeichensatz, der alle Buchstaben und Zeichen der Welt kennt – wichtig für Umlaute, Anführungszeichen und fremdsprachige Inhalte.
Drupal setzt bei PostgreSQL zwingend die Erweiterung pg_trgm voraus. Sie findet ähnlich geschriebene Wörter, indem sie jedes Wort in Dreier-Gruppen von Buchstaben zerlegt und diese vergleicht – dieselbe Erweiterung, die das Kapitel Datenbank für die Ähnlichkeitssuche ohnehin nutzt. Der Drupal-Installationsassistent würde versuchen, sie selbst einzuschalten; sicherer ist es, das vorab als Verwalter zu erledigen:
sudo -u postgres psql -d drupal -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
Die Tabellen legt die Installation in Schritt 5 selbst an; ein eigenes Datenbankschema muss nicht von Hand eingerichtet werden.
Schritt 3: Drupal mit Composer zusammenstellen
Drupal wird aus dem offiziellen Projektgerüst drupal/recommended-project erzeugt. Es bringt Drupal Core und die sinnvollen Standard-Abhängigkeiten mit. Damit Composer nicht mit Verwaltungsrechten läuft (davon rät Composer ausdrücklich ab), gehört das Projektverzeichnis zunächst dem angemeldeten Benutzer:
sudo mkdir -p /var/www/drupal
sudo chown "$USER":"$USER" /var/www/drupal
# Projekt in das vorhandene, leere Verzeichnis erzeugen
composer create-project drupal/recommended-project /var/www/drupal
cd /var/www/drupal
# Drush als Kommandozeilen-Shell ergänzen
composer require drush/drush
Nach diesem Schritt liegt der eigentliche Webinhalt im Unterordner web/ – dieser Ordner wird später das Wurzelverzeichnis des Webservers. Die Bausteine liegen in vendor/, der Drush-Befehl unter vendor/bin/drush.
Schritt 4: Dateirechte setzen
Der Webserver und PHP-FPM laufen unter dem Benutzer www-data. Dieser Benutzer soll den Drupal-Code lesen dürfen, aber nur zwei Stellen beschreiben: den Ordner für hochgeladene Dateien und – während der Installation – den Ordner, in den die zentrale Einstellungsdatei geschrieben wird.
# Alles gehört www-data, mit Lese- und Ausführungsrechten für die Gruppe
sudo chown -R www-data:www-data /var/www/drupal
sudo find /var/www/drupal -type d -exec chmod 755 {} \;
sudo find /var/www/drupal -type f -exec chmod 644 {} \;
# Der Ordner für hochgeladene Dateien muss beschreibbar sein
sudo mkdir -p /var/www/drupal/web/sites/default/files
sudo chmod -R 775 /var/www/drupal/web/sites/default/files
# Verzeichnis für die exportierte Konfiguration (außerhalb von web/)
sudo mkdir -p /var/www/drupal/config/sync
sudo chown -R www-data:www-data /var/www/drupal/config
Schritt 5: Drupal ohne Browser installieren
Anders als bei XWiki oder MediaWikis grafischem Assistenten braucht Drupal für die Ersteinrichtung keinen Zugang über den Browser und keinen SSH-Tunnel. Der Befehl drush site:install erledigt die komplette Einrichtung nichtinteraktiv auf der Kommandozeile: Er legt die Tabellen an, schreibt die Einstellungsdatei und richtet das Administratorkonto ein.
Damit Drush die Einstellungsdatei settings.php schreiben kann, muss ihr Ordner kurz beschreibbar sein:
sudo chmod 775 /var/www/drupal/web/sites/default
cd /var/www/drupal
sudo -u www-data php vendor/bin/drush site:install standard \
--db-url='pgsql://drupal:DATENBANKPASSWORT@localhost/drupal' \
--site-name="Portal Ahrensburg" \
--account-name=admin \
--account-pass='ADMINPASSWORT' \
--yes
standardist die mitgelieferte Grundausstattung mit den üblichen Funktionen.--db-urlenthält alle Angaben aus Schritt 2: Benutzer, Passwort, Server (localhost) und Datenbankname.pgsqlwählt PostgreSQL.--account-nameund--account-passsind Name und Passwort des ersten Administratorkontos.
Danach die Rechte an der Einstellungsdatei wieder einschränken, sodass www-data sie nur noch lesen kann:
sudo chmod 644 /var/www/drupal/web/sites/default/settings.php
sudo chmod 755 /var/www/drupal/web/sites/default
Zwei Zeilen gehören noch an das Ende von /var/www/drupal/web/sites/default/settings.php. Die erste legt fest, unter welchem Domainnamen die Seite antworten darf (das schützt vor gefälschten Anfragen). Die zweite legt das Verzeichnis für die exportierte Konfiguration fest:
$settings['trusted_host_patterns'] = ['^portal\.meine\-domain\.de$'];
$settings['config_sync_directory'] = '../config/sync';
Schritt 6: Ein eigener PHP-FPM-Pool für Drupal
Auf dem Server läuft mit MediaWiki bereits eine zweite PHP-Anwendung. Damit beide sich nicht gegenseitig den Arbeitsspeicher wegnehmen und sich getrennt einstellen lassen, bekommt Drupal einen eigenen PHP-FPM-Pool mit einer eigenen Socket-Datei. Eine Socket-Datei ist ein besonderer Eintrag im Dateisystem, über den der Webserver und PHP auf demselben Rechner miteinander reden.
Dazu die Datei /etc/php/8.5/fpm/pool.d/drupal.conf anlegen:
[drupal]
user = www-data
group = www-data
listen = /run/php/php8.5-fpm-drupal.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[memory_limit] = 256M
[drupal]ist der Name des Pools.listenist die Socket-Datei, über die NGINX diesen Pool erreicht – eine andere als die von MediaWiki.- Die
pm.*-Zeilen steuern, wie viele PHP-Arbeiter gleichzeitig bereitstehen.
Danach PHP-FPM neu starten:
sudo systemctl restart php8.5-fpm
# Zur Kontrolle: die neue Socket-Datei sollte jetzt da sein
ls /run/php/
Wer strikt auf PHP 8.4 bleiben möchte (siehe Abschnitt „Welche Version"), legt diesen Pool stattdessen unter /etc/php/8.4/fpm/pool.d/ an und passt den Pfad der Socket-Datei entsprechend an.
Schritt 7: NGINX als Webserver einrichten
Damit die Seite öffentlich und verschlüsselt erreichbar ist, kommt NGINX davor. Es liefert die festen Dateien (Bilder, Stylesheets) selbst aus und reicht alle PHP-Aufrufe an den Drupal-Pool aus Schritt 6 weiter (siehe Webserver).
Zuerst das SSL-Zertifikat besorgen. Wie das mit Certbot und Let's Encrypt geht, steht ausführlich im Kapitel Webserver; für eine feste Domain genügt:
sudo certbot certonly --nginx -d portal.meine-domain.de
Dann die Konfigurationsdatei /etc/nginx/sites-available/drupal anlegen:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name portal.meine-domain.de;
ssl_certificate /etc/letsencrypt/live/portal.meine-domain.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/portal.meine-domain.de/privkey.pem;
root /var/www/drupal/web;
index index.php;
# Große Datei-Uploads zulassen (muss zu php.ini aus Schritt 1 passen)
client_max_body_size 100m;
# Kurze Adressen: alles, was keine echte Datei ist, geht an Drupal
location / {
try_files $uri /index.php?$query_string;
}
# PHP nur für index.php und update.php ausführen
location ~ ^/(index|update)\.php(/|$) {
include snippets/fastcgi-php.conf;
fastcgi_param HTTPS on;
fastcgi_pass unix:/run/php/php8.5-fpm-drupal.sock;
}
# Einstellungsdateien, den privaten Bereich und versteckte Dateien sperren
location ~ ^/sites/[^/]+/(settings|services).*\.(php|yml)$ { deny all; }
location ~ ^/sites/[^/]+/files/.*\.php$ { deny all; }
location ~ ^/sites/.+/private/ { deny all; }
location ~ /\.(ht|git) { deny all; }
# Feste Dateien lange im Browser zwischenspeichern lassen;
# noch nicht erzeugte Vorschaubilder gehen an Drupal
location ~ \.(css|js|gif|jpe?g|png|svg|webp|woff2?)$ {
try_files $uri @rewrite;
expires max;
log_not_found off;
}
location @rewrite {
rewrite ^ /index.php;
}
}
server {
listen 80;
listen [::]:80;
server_name portal.meine-domain.de;
# Alle unverschlüsselten Aufrufe auf HTTPS umleiten
return 301 https://$host$request_uri;
}
Der Kern ist der Block location /: Fragt der Browser eine echte Datei an (ein Bild, ein Stylesheet), liefert NGINX sie direkt. Fragt er eine Seitenadresse an, gibt es diese Datei nicht – dann übergibt try_files die Anfrage an /index.php, und Drupal erzeugt die Seite. Der PHP-Block führt bewusst nur index.php und update.php aus; jede andere PHP-Datei im Verzeichnis bleibt unausgeführt und kann nicht als Einfallstor dienen.
Die Datei aktiv schalten, prüfen und übernehmen:
sudo ln -s /etc/nginx/sites-available/drupal /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Jetzt ist die Seite unter https://portal.meine-domain.de/ erreichbar. Die Anmeldung am Administratorbereich erfolgt unter /user mit den Zugangsdaten aus Schritt 5.
Schritt 8: Wartungsaufgaben über einen Zeitplan
Drupal hat Aufgaben, die regelmäßig im Hintergrund laufen müssen: Zwischenspeicher aufräumen, Suchindex aktualisieren, E-Mails verschicken, nach Sicherheitsaktualisierungen sehen. Angestoßen werden sie über einen Zeitplan-Eintrag des Benutzers www-data:
sudo -u www-data crontab -e
Dort diese Zeile einfügen – sie arbeitet alle 15 Minuten die anstehenden Aufgaben ab:
*/15 * * * * cd /var/www/drupal && /usr/bin/php vendor/bin/drush core:cron >/dev/null 2>&1
Betreibt man auf demselben Server auch MediaWiki, steht dessen Zeile für runJobs bereits in dieser Tabelle; beide Einträge stören sich nicht.
Aktualisieren
Drupal wird komplett über Composer aktuell gehalten. Vor einer Aktualisierung immer erst eine Sicherung anlegen (siehe unten). Die Schritte laufen im Projektverzeichnis als der Benutzer, dem die Dateien gehören:
cd /var/www/drupal
# Neue Fassungen von Drupal Core und Abhängigkeiten holen
sudo -u www-data composer update "drupal/core-*" --with-all-dependencies
# Datenbank an die neue Fassung anpassen und Zwischenspeicher leeren
sudo -u www-data php vendor/bin/drush updatedb --yes
sudo -u www-data php vendor/bin/drush cache:rebuild
Der Wechsel auf Drupal 12 läuft genauso, nur wird dabei die geforderte Hauptversion angehoben:
sudo -u www-data composer require "drupal/core-recommended:^12" "drupal/core-composer-scaffold:^12" --update-with-all-dependencies
sudo -u www-data php vendor/bin/drush updatedb --yes
sudo -u www-data php vendor/bin/drush cache:rebuild
Sicherung und Wiederherstellung
Zu einem Drupal-Betrieb gehört eine regelmäßige, automatische Sicherung an einen zweiten Ort. Drei Dinge müssen gesichert werden:
# 1. Die Datenbank – sie enthält Inhalte, Konten und Konfiguration
sudo -u postgres pg_dump drupal > /home/thorsten/backup/drupal-$(date +%F).sql
# 2. Die hochgeladenen Dateien
sudo tar -czf /home/thorsten/backup/drupal-files-$(date +%F).tar.gz \
-C /var/www/drupal/web/sites/default files
# 3. Die Konfiguration als lesbare Textdateien (zusätzlich zur Datenbank)
cd /var/www/drupal
sudo -u www-data php vendor/bin/drush config:export --yes
Der Konfigurations-Export nach config/sync/ ist besonders nützlich: Diese Textdateien lassen sich in einem Git-Repository versionieren, sodass jede Änderung an der Seitenstruktur nachvollziehbar bleibt. Wie sich der Datenbank-Export über einen Zeitplan automatisieren lässt, steht im Kapitel Datenbank.
Für die Wiederherstellung wird die Datenbank neu angelegt und der Export eingelesen, danach der Datei-Ordner zurückgelegt:
sudo -u postgres dropdb drupal
sudo -u postgres createdb -E UTF8 -O drupal drupal
sudo -u postgres psql -d drupal -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
sudo -u postgres psql -d drupal -f /home/thorsten/backup/drupal-2026-09-06.sql
sudo tar -xzf /home/thorsten/backup/drupal-files-2026-09-06.tar.gz \
-C /var/www/drupal/web/sites/default
sudo chown -R www-data:www-data /var/www/drupal/web/sites/default/files
Schnell ausprobieren ohne Webserver
Für einen kurzen Test – etwa um zu prüfen, ob die Installation überhaupt läuft – bringt Drush einen eigenen kleinen Webserver mit:
cd /var/www/drupal
sudo -u www-data php vendor/bin/drush runserver 127.0.0.1:8888
Die Adresse 127.0.0.1 sorgt dafür, dass dieser Testserver nur vom Server selbst erreichbar ist. Um ihn trotzdem im Browser des eigenen Rechners zu öffnen, wird wie im Kapitel XWiki einrichten ein SSH-Tunnel aufgebaut:
# Auf dem eigenen Rechner ausführen
ssh -L 8888:127.0.0.1:8888 admin@SERVER-IP
Danach http://localhost:8888/ im Browser aufrufen. Für den Dauerbetrieb ist dieser Weg nicht gedacht – dafür ist NGINX aus Schritt 7 zuständig.
Für dieses Buch
Der Web Stack dieses Buchs läuft im Kern auf MediaWiki. Drupal kommt als zweiter, redaktioneller Auftritt hinzu, wenn neben der gemeinsam gepflegten Wissenssammlung eine Seite mit fester Redaktion und strukturierten Inhaltstypen entstehen soll (siehe Content-Management-System).
Empfohlen wird der Betrieb direkt auf dem Server (ohne Container, siehe Containerisierung von Software): PHP-FPM, PostgreSQL und NGINX laufen nebeneinander, Drupal liegt als Composer-Projekt unter /var/www/drupal. Damit Drupal und MediaWiki sich nicht behindern, bekommt Drupal einen eigenen PHP-FPM-Pool (Schritt 6).
Als Ausgangsfassung dient Drupal 11; der Wechsel auf Drupal 12 ist vorgesehen, sobald diese erschienen ist – Server, PHP 8.5 und PostgreSQL 18 erfüllen deren Anforderungen bereits. Zwei Dinge gehören von Anfang an zum Betrieb: der Zeitplan-Eintrag für die Wartungsaufgaben (Schritt 8) und eine regelmäßige, automatische Sicherung von Datenbank, Datei-Ordner und Konfiguration an einen zweiten Ort.
Fazit
Drupal besteht aus fünf zusammenspielenden Teilen: der Laufzeitumgebung PHP-FPM, dem Paketwerkzeug Composer, der Datenbank PostgreSQL, einem Webserver davor und der Kommandozeilen-Shell Drush. Die Einrichtung läuft in klaren Schritten: PHP und seine Erweiterungen installieren, in PostgreSQL eine leere Datenbank mit der Erweiterung pg_trgm anlegen, Drupal mit Composer aus dem Projektgerüst drupal/recommended-project zusammenstellen, die Dateirechte setzen, mit drush site:install ohne Browser installieren, einen eigenen PHP-FPM-Pool einrichten und zuletzt NGINX als verschlüsselten Zugang davorstellen. Weil Drupal 11.4 mit dem PHP 8.5 von Ubuntu 26.04 zurechtkommt und PostgreSQL 18 die Anforderungen übertrifft, ist der spätere Wechsel auf Drupal 12 unkritisch.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
IDE und GUI
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Wer eine App für Mobilgeräte mit dem Betriebssystem Android schreiben will – also für die meisten Smartphones und Tablets außerhalb der Apple-Welt –, steht am Anfang vor zwei Fragen: In welchem Programm schreibt man den Code? Und wie baut man die sichtbare Oberfläche, die der Nutzer auf dem Bildschirm antippt? Dieses Kapitel beantwortet beide für die heute übliche Programmiersprache Kotlin.
Kotlin ist eine vergleichsweise junge Sprache der Firma JetBrains. Google hat sie 2017 offiziell für Android zugelassen und 2019 zur bevorzugten Sprache erklärt: Neue Anleitungen, Beispiele und Werkzeuge gehen seither von Kotlin aus, die ältere Sprache Java bleibt weiter möglich. Kotlin-Code läuft auf derselben Laufzeitumgebung wie Java (siehe Programmiersprachen), ist aber kürzer und fängt eine häufige Fehlerquelle – den Zugriff auf einen „leeren“ Wert – schon beim Übersetzen ab.
Als Grundlage dient wie im übrigen Buch Ubuntu. Ein Terminal ist ein Fenster, in das man Anweisungen als Text tippt; ein vorangestelltes sudo bedeutet: mit Verwaltungsrechten ausführen, das System fragt dann nach dem Passwort.
Android Studio – die IDE für Android
Eine IDE („Integrated Development Environment“, integrierte Entwicklungsumgebung) ist ein Programm, in dem Editor, Fehlersuche, Versionsverwaltung und Werkzeuge zum Ausführen von Code in einem Fenster zusammenstecken (siehe IDE). Für Android gibt es dafür einen klaren Standard: Android Studio.
Android Studio wird von Google herausgegeben, ist kostenlos und läuft auf Windows, macOS und Linux. Es baut auf IntelliJ IDEA von JetBrains auf – der IDE aus dem Kapitel IDE – und ergänzt sie um alles, was für Android nötig ist:
- das Android SDK („Software Development Kit“), also die fertigen Bausteine und Werkzeuge, aus denen eine Android-App gebaut wird;
- einen Emulator, ein am Bildschirm nachgebildetes Smartphone, auf dem sich die App ohne echtes Gerät ausprobieren lässt;
- eine Vorschau der Oberfläche, die Änderungen sofort anzeigt;
- das Bauwerkzeug Gradle, das den Weg vom Quellcode zur fertigen App-Datei steuert und Bausteine aus dem Internet nachlädt.
Kotlin ist von Haus aus eingebaut; eine gesonderte Installation der Sprache ist für die App-Entwicklung nicht nötig.
Installation auf Ubuntu
Am einfachsten geht es über ein Snap – ein Paketformat von Canonical, bei dem das Programm stärker vom übrigen System abgeschottet läuft:
sudo snap install android-studio --classic
--classic hebt die Abschottung so weit auf, dass die IDE den vollen Zugriff auf das System bekommt, den sie zum Bauen und Ausführen braucht.
Wer die Toolbox App von JetBrains bereits nutzt (siehe IDE), kann Android Studio auch darüber installieren und aktuell halten. Ein dritter Weg ist das Archiv von der offiziellen Seite developer.android.com/studio:
# Archiv nach /opt entpacken (dort liegen zusätzlich installierte Programme)
sudo tar -xzf android-studio-*.tar.gz -C /opt
# Einmalig starten; danach trägt sich Android Studio ins Anwendungsmenü ein
/opt/android-studio/bin/studio.sh
Beim ersten Start lädt ein Assistent das Android SDK herunter – mehrere Gigabyte – und richtet ein erstes Emulator-Gerät ein.
Den Emulator beschleunigen
Der Emulator ist deutlich schneller, wenn er die Virtualisierungs-Unterstützung des Prozessors nutzt. Unter Linux läuft das über KVM. Ob der eigene Rechner das kann, zeigt:
sudo apt install cpu-checker
kvm-ok
Meldet der Befehl fehlende Rechte, wird der eigene Benutzer der Gruppe kvm hinzugefügt; danach einmal ab- und wieder anmelden:
sudo adduser "$USER" kvm
Alternativ testet man die App auf einem echten Telefon, das per USB-Kabel angeschlossen ist. Dazu müssen auf dem Telefon einmalig die „Entwickleroptionen“ und darin das „USB-Debugging“ eingeschaltet werden.
Andere Editoren
IntelliJ IDEA kann mit dem Android-Zusatzmodul dasselbe wie Android Studio – kein Wunder, da Android Studio darauf aufbaut. Android Studio hat jedoch alles vorkonfiguriert und ist der Weg, den die Google-Anleitungen beschreiben.
Visual Studio Code (siehe IDE) hat Erweiterungen für Kotlin und eignet sich für kleine Änderungen. Für die volle Android-Entwicklung fehlen aber Emulator, Oberflächen-Vorschau und die vorbereitete Verzahnung mit dem Android SDK. Als Hauptwerkzeug für Android ist es nicht zu empfehlen.
GUI – die sichtbare Oberfläche bauen
GUI steht für „Graphical User Interface“, grafische Benutzeroberfläche: die Knöpfe, Textfelder, Listen und Bilder, die der Nutzer sieht und antippt. Auf Android gibt es dafür zwei Wege, die beide aus Kotlin heraus benutzbar sind.
XML-Layouts mit Views – der klassische Weg
Bei diesem Weg wird die Oberfläche in XML-Dateien beschrieben. XML ist ein Textformat aus verschachtelten Marken (Tags); jedes Bedienelement – ein Knopf, ein Textfeld, ein Bild – ist eine solche Marke und heißt im Android-Sprachgebrauch View. Der Kotlin-Code füllt diese Elemente dann mit Inhalt und reagiert auf Berührungen.
Dieser Weg ist seit den Anfängen von Android da. Dadurch gibt es sehr viele Anleitungen und Beispiele, und jede Android-Version unterstützt ihn. Der Nachteil: Oberfläche und Ablauf-Logik liegen an zwei getrennten Stellen – in der XML-Datei und im Kotlin-Code –, und es fällt vergleichsweise viel gleichförmiger Verbindungscode an.
Jetpack Compose – der heutige Standard
Jetpack Compose ist der neuere Ansatz von Google, seit 2021 einsatzreif. Hier gibt es keine XML-Dateien mehr: Die Oberfläche wird direkt in Kotlin geschrieben, als besondere Funktionen (im Fachjargon „composable functions“).
Compose arbeitet beschreibend (deklarativ). Statt Schritt für Schritt anzuweisen, wie sich die Anzeige ändern soll, beschreibt man nur, wie der Bildschirm bei einem bestimmten Zustand aussehen soll – etwa „Liste mit diesen fünf Einträgen“. Ändert sich der Zustand, zeichnet Compose die betroffenen Teile von selbst neu. Das ergibt spürbar weniger Code als der XML-Weg, und Android Studio zeigt eine Live-Vorschau direkt neben dem Editor. Für neue Apps empfiehlt Google heute Compose.
Beide Wege lassen sich mischen. In eine bestehende XML-App kann man einzelne Compose-Bereiche einsetzen und so nach und nach umstellen, ohne alles auf einmal neu zu schreiben.
Material Design – die Gestaltungsbausteine
Material Design ist kein dritter Weg, sondern eine Ergänzung: Googles Gestaltungssammlung liefert fertige Elemente – Knöpfe, Karten, Dialoge, Menüs – in einem einheitlichen, aufeinander abgestimmten Aussehen. Es gibt sie sowohl für den XML-Weg als auch für Compose, sodass eine App nicht jedes Bedienelement selbst entwerfen muss.
Compose Multiplatform – eine Oberfläche für mehrere Systeme
Compose Multiplatform ist eine Erweiterung von JetBrains, die Jetpack Compose über Android hinaus öffnet. Zusammen mit Kotlin Multiplatform – der Technik, mit der sich Kotlin-Code für mehrere Betriebssysteme übersetzen lässt – läuft derselbe in Kotlin geschriebene Oberflächencode auf Android, auf dem iPhone (iOS), auf dem Desktop (Windows, macOS, Linux) und im Browser. Die Oberfläche für iOS gilt seit Mai 2025 als stabil.
Das lohnt sich, wenn dieselbe App mehrere Plattformen bedienen soll und man sie nur einmal schreiben möchte. Für eine reine Android-App ist der Zusatzaufwand nicht nötig.
Nicht Kotlin: Flutter und React Native
Zwei bekannte Baukästen für plattformübergreifende Apps arbeiten nicht mit Kotlin: Flutter von Google nutzt die Sprache Dart, React Native nutzt JavaScript beziehungsweise TypeScript. Sie sind nur eine Überlegung wert, wenn man sich nicht auf Kotlin festlegen will, und werden hier genannt, damit die Auswahl vollständig ist.
Kurzvergleich
| Ansatz | Sprache | Oberfläche beschrieben in | Wann geeignet |
|---|---|---|---|
| XML-Layouts mit Views | Kotlin | XML-Dateien, getrennt vom Code | Arbeit an einer bestehenden App, die es schon so nutzt |
| Jetpack Compose | Kotlin | direkt in Kotlin, beschreibend | neue Android-Apps (Empfehlung von Google) |
| Compose Multiplatform | Kotlin | direkt in Kotlin, beschreibend | eine Oberfläche für Android, iOS, Desktop und Web zugleich |
| Flutter | Dart | direkt in Dart, beschreibend | plattformübergreifend, ohne Festlegung auf Kotlin |
| React Native | JavaScript / TypeScript | direkt im Code, beschreibend | plattformübergreifend, mit Web-Kenntnissen im Team |
Für dieses Buch
Die Entwicklung einer eigenen Android-App ist nicht Kern dieses Handbuchs. Entsteht aber eine App als Ergänzung – etwa als mobiler Zugang zur Wissenssammlung (siehe Wissenssystem) –, dann ist der Weg klar: Android Studio als IDE, installiert über Snap, und Jetpack Compose für die Oberfläche. Den XML-Weg wählt man nur, wenn man an einer vorhandenen App mitarbeitet, die bereits darauf aufbaut. Compose Multiplatform kommt in Frage, sobald neben Android auch das iPhone aus einem gemeinsamen Code bedient werden soll.
Fazit
Für Android-Apps mit Kotlin ist Android Studio die passende IDE: kostenlos, von Google, auf IntelliJ IDEA aufgebaut und mit Android SDK, Emulator und Bauwerkzeug fertig eingerichtet. Auf Ubuntu wird es am einfachsten über ein Snap installiert; der Emulator läuft flüssig, sobald KVM freigeschaltet ist. Für die sichtbare Oberfläche gibt es zwei Kotlin-Wege: den klassischen über XML-Layouts mit Views und den heutigen Standard Jetpack Compose, bei dem die Oberfläche beschreibend direkt in Kotlin entsteht. Für neue Apps ist Compose die erste Wahl; Compose Multiplatform dehnt denselben Code auf iOS, Desktop und Web aus. Baukästen wie Flutter oder React Native sind nur ohne Festlegung auf Kotlin eine Alternative.
Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).
Impressum
Anbieter dieser Website
- Thorsten Klöhn
- Gerhardstraße 2
- 22926 Ahrensburg
Vertreten durch:
Thorsten Klöhn
Kontakt:
- Telefon: 04102-2 17 40 07
- E-Mail: thorstenkloehn@gmail.com
Lizenz und externe Links
Die selbst erstellten Inhalte dieses Wikis stehen unter der Creative-Commons-Lizenz CC BY-SA 4.0, sofern auf einer Seite nichts anderes angegeben ist. Verlinkte externe Angebote werden von ihren jeweiligen Anbietern verantwortet. Hinweise auf rechtswidrige oder fehlerhafte Inhalte können an die oben genannte E-Mail-Adresse gesendet werden.
Ausführliche Informationen zur Urheberrechtsprüfung, zu Lizenzierungen und zum Umgang mit fremden Inhalten stehen auf der Seite Urheberrecht und Duplicate Content.
KI-Transparenzhinweis
Die Texte dieser Wissensdatenbank wurden ursprünglich mithilfe eines KI-Sprachmodells erstellt und anschließend redaktionell durch den Seitenbetreiber auf sachliche Richtigkeit überprüft und korrigiert. Dieser Hinweis dient der Transparenz gemäß Art. 50 der EU-Verordnung über Künstliche Intelligenz (AI Act).
Datenschutz
Informationen zur Verarbeitung personenbezogener Daten enthält die Datenschutzerklärung.
Datenschutzerklärung
Verantwortliche Stelle im Sinne der Datenschutzgesetze, insbesondere der EU-Datenschutzgrundverordnung (DSGVO), ist:
- Thorsten Klöhn
- Gerhardstraße 2
- 22926 Ahrensburg
- Telefon: 04102-2 17 40 07
- E-Mail: thorstenkloehn@gmail.com
Hosting und Server-Logfiles
Diese Website ist eine statische Seite (erstellt mit mdBook) und wird über GitHub Pages ausgeliefert. Anbieter ist GitHub, Inc., 88 Colin P. Kelly Jr. Street, San Francisco, CA 94107, USA, für Nutzer in der EU vertreten durch GitHub B.V., Prins Bernhardplein 200, 1097 JB Amsterdam, Niederlande.
Beim Aufruf der Seite verarbeitet GitHub automatisch technische Zugriffsdaten (Server-Logfiles), z. B. IP-Adresse, Datum und Uhrzeit des Zugriffs, aufgerufene Seite und verwendeter Browser. Diese Verarbeitung erfolgt auf Grundlage unseres berechtigten Interesses an einer sicheren und funktionsfähigen Bereitstellung der Website (Art. 6 Abs. 1 lit. f DSGVO) und liegt außerhalb unseres Einflussbereichs. Näheres regelt die Datenschutzerklärung von GitHub: https://docs.github.com/site-policy/privacy-policies/github-general-privacy-statement.
Soweit GitHub Daten außerhalb der EU/des EWR verarbeitet, stützt sich der Transfer auf Standardvertragsklauseln bzw., soweit anwendbar, auf das EU-US Data Privacy Framework (DPF), dem GitHub, Inc. beigetreten ist. Das frühere „EU-US Privacy Shield“ ist seit dem Schrems-II-Urteil des EuGH (2020) nicht mehr gültig und wurde durch das DPF ersetzt.
Keine Cookies, kein Tracking, keine Nutzerkonten
Diese Website ist eine rein statische Wissensdatenbank ohne eigenes Content-Management-System. Wir setzen keine eigenen Cookies, binden keine Analyse- oder Tracking-Dienste ein und bieten keine Registrierung oder Benutzerkonten an. Eine Bearbeitung der Inhalte durch Besucher ist über die Website selbst nicht möglich. Da keine technisch nicht notwendigen Cookies oder vergleichbaren Technologien zum Einsatz kommen, ist eine Einwilligung nach § 25 TTDSG nicht erforderlich.
Externe Links
Auf einigen Seiten verweisen wir mit gewöhnlichen Hyperlinks auf externe Angebote, z. B. auf YouTube-Playlists von Schwesterprojekten. Diese Links öffnen die Zielseite lediglich; es findet keine Einbettung (kein iFrame-/Embed) statt, sodass beim Aufruf unserer Seite selbst keine Daten an die verlinkten Anbieter übertragen werden. Erst wenn Sie einen Link aktiv anklicken, gelten die Datenschutzbestimmungen des jeweiligen Anbieters, z. B. für YouTube die der Google Ireland Limited: https://policies.google.com/privacy.
Ihre Betroffenenrechte
Unter den oben angegebenen Kontaktdaten können Sie jederzeit folgende Rechte ausüben:
- Auskunft über Ihre bei uns gespeicherten Daten und deren Verarbeitung (Art. 15 DSGVO),
- Berichtigung unrichtiger personenbezogener Daten (Art. 16 DSGVO),
- Löschung Ihrer bei uns gespeicherten Daten (Art. 17 DSGVO),
- Einschränkung der Datenverarbeitung, sofern wir Ihre Daten aufgrund gesetzlicher Pflichten noch nicht löschen dürfen (Art. 18 DSGVO),
- Widerspruch gegen die Verarbeitung Ihrer Daten bei uns (Art. 21 DSGVO) und
- Datenübertragbarkeit, sofern Sie in die Datenverarbeitung eingewilligt haben oder einen Vertrag mit uns abgeschlossen haben (Art. 20 DSGVO).
Sofern Sie uns eine Einwilligung erteilt haben, können Sie diese jederzeit mit Wirkung für die Zukunft widerrufen.
Sie können sich jederzeit mit einer Beschwerde an eine Aufsichtsbehörde wenden, z. B. an die für Schleswig-Holstein zuständige Behörde, das Unabhängige Landeszentrum für Datenschutz Schleswig-Holstein (ULD): https://www.datenschutzzentrum.de/, oder an die Aufsichtsbehörde Ihres eigenen Wohnsitzes.
KI-generierte Inhalte
Einige Inhalte dieser Website wurden mit Hilfe von KI-Tools (u. a. Sprachmodellen wie GitHub Copilot) erstellt und redaktionell überarbeitet. Die fertigen Textinhalte werden ausschließlich im Rahmen dieses Repositorys verwaltet und als statische Seite über GitHub Pages veröffentlicht. Eine gesonderte Speicherung oder Verarbeitung personenbezogener Besucherdaten durch die eingesetzten KI-Anbieter findet nicht statt, da diese Tools nur redaktionell bei der Texterstellung eingesetzt werden und keinen Zugriff auf Besucherdaten der veröffentlichten Website haben.
Änderung dieser Datenschutzerklärung
Wir behalten uns vor, diese Datenschutzerklärung anzupassen, damit sie stets den aktuellen rechtlichen Anforderungen entspricht oder um Änderungen an der Website umzusetzen, z. B. bei der Einführung neuer Funktionen. Für Ihren erneuten Besuch gilt dann die neue Datenschutzerklärung.
Fragen zum Datenschutz
Wenn Sie Fragen zum Datenschutz haben, schreiben Sie uns bitte eine E-Mail an die oben genannte Adresse.
Diese Datenschutzerklärung basiert auf dem Datenschutzerklärungs-Generator der activeMind AG und wurde für den tatsächlichen Betrieb dieser Website (statisches mdBook auf GitHub Pages, Stand 2026) angepasst.