Einleitung

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Dieses Buch sammelt Schritt-für-Schritt-Anleitungen, um Programme auf einem Ubuntu-Rechner zu installieren.

  • System: Ubuntu 26.04 LTS, x86_64 (amd64)
  • Jede Anleitung erklärt jeden Schritt, zeigt, wie man die Installation prüft, und wie man das Programm wieder entfernt.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

nginx

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

nginx ist ein schneller Webserver. Auf dem Entwicklungsrechner dient er dazu, Webseiten und Webanwendungen lokal unter http://localhost zu testen.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von nginx aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. nginx installieren

Installiert nginx aus den offiziellen Ubuntu-Paketquellen. Der Dienst wird dabei automatisch gestartet.

sudo apt install nginx

Prüfen: Die Versionsnummer wird angezeigt.

nginx -v

3. Prüfen, ob der Dienst läuft

nginx läuft als Hintergrunddienst (systemd). Hier siehst du, ob er gestartet ist.

systemctl status nginx

Prüfen: In der Ausgabe steht Active: active (running). Mit q verlässt du die Anzeige.

4. Startseite im Browser aufrufen

Zeigt, dass nginx Anfragen beantwortet.

curl -I http://localhost

Prüfen: Die erste Zeile lautet HTTP/1.1 200 OK. Im Browser erscheint unter http://localhost die Seite „Welcome to nginx!“.

Eigene Entwicklungsseite einrichten

5. Ordner für die Seite anlegen

Die Dateien kommen nach /var/www/dev. Der Ordner gehört deinem Benutzer, damit du ohne sudo darin arbeiten kannst. Das Home-Verzeichnis eignet sich nicht, weil nginx (Benutzer www-data) dort keine Leserechte hat.

sudo mkdir -p /var/www/dev
sudo chown "$USER":"$USER" /var/www/dev

6. Testseite anlegen

Eine einfache HTML-Datei, um die Einrichtung zu prüfen.

nano /var/www/dev/index.html

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<h1>Entwicklung läuft</h1>

7. Konfiguration für die Seite anlegen

Die Seite läuft auf Port 8081, damit sie die Standardseite auf Port 80 nicht stört. Port 8080 bleibt frei für Apache (siehe nginx als Proxy vor Apache). listen 127.0.0.1 sorgt dafür, dass nur dein eigener Rechner darauf zugreifen kann.

sudo nano /etc/nginx/sites-available/dev

Die Datei hat schon Inhalt, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 127.0.0.1:8081;
    server_name localhost;

    root /var/www/dev;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

8. Seite aktivieren

nginx lädt nur Konfigurationen aus sites-enabled. Ein Link dorthin schaltet die Seite ein.

sudo ln -s /etc/nginx/sites-available/dev /etc/nginx/sites-enabled/dev

9. Konfiguration testen

Findet Tippfehler, bevor nginx neu geladen wird.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

10. nginx neu laden

Übernimmt die neue Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

Prüfen: Die Testseite wird angezeigt.

curl http://localhost:8081

Die Ausgabe ist <h1>Entwicklung läuft</h1>. Im Browser: http://localhost:8081.

Optional: Autostart ausschalten

Auf einem Entwicklungsrechner muss nginx nicht bei jedem Systemstart laufen.

Autostart ausschalten:

sudo systemctl disable nginx

Bei Bedarf von Hand starten und stoppen:

sudo systemctl start nginx
sudo systemctl stop nginx

Deinstallieren

1. Entwicklungsseite entfernen

Löscht die Konfiguration und die Dateien der Seite. Achtung: Alles in /var/www/dev geht verloren.

sudo rm /etc/nginx/sites-enabled/dev /etc/nginx/sites-available/dev
sudo rm -r /var/www/dev

2. nginx entfernen

purge entfernt auch die Konfigurationsdateien unter /etc/nginx.

sudo apt purge nginx nginx-common

3. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für nginx installiert wurden.

sudo apt autoremove

Prüfen: Der Befehl wird nicht mehr gefunden.

nginx -v

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

nginx auf dem Produktionsserver

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Auf einem Server im Internet liefert nginx Websites dauerhaft und verschlüsselt an Besucher aus. Diese Anleitung richtet nginx auf einem frischen Ubuntu-Server für den echten Betrieb ein: mit Firewall, automatischen Sicherheitsupdates, Wildcard-Zertifikat von Let's Encrypt und einer abgesicherten Grundkonfiguration. Als Beispiel dient die Domain wissen-ahrensburg.de.

Vorbemerkungen

  • Unterschied zur Anleitung nginx: Dort läuft nginx auf dem eigenen Rechner zum Testen. Hier ist der Server aus dem Internet erreichbar. Deshalb kommen Firewall, HTTPS und Schutz vor fremden Anfragen dazu.
  • Voraussetzungen:
    • Ein Server mit Ubuntu 26.04 LTS, auf den du per SSH mit einem Benutzer mit sudo-Rechten zugreifst.
    • Die Domain wissen-ahrensburg.de zeigt per A-Eintrag (IPv4) und, falls vorhanden, AAAA-Eintrag (IPv6) auf den Server. Dasselbe gilt für www oder für *, wenn beliebige Subdomains auf den Server zeigen sollen.
  • Eigene Domain: Ersetze wissen-ahrensburg.de in allen Befehlen und Dateien durch deine Domain.
  • apt statt Snap: Certbot gibt es auch als Snap-Paket. Ubuntu 26.04 bringt Certbot aber selbst mit. Das apt-Paket bekommt Sicherheitsupdates zusammen mit dem restlichen System, und snapd wird dafür nicht gebraucht.
  • Alle Befehle laufen auf dem Server, also in der SSH-Sitzung, nicht auf deinem eigenen Rechner.

System vorbereiten

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aller Pakete kennt.

sudo apt update

2. Installierte Pakete aktualisieren

Ein Server im Internet sollte vor der Einrichtung auf dem neuesten Stand sein, damit keine bekannten Sicherheitslücken offen sind.

sudo apt upgrade

Prüfen: Die Frage nach der Installation mit J bzw. Y bestätigen. Meldet apt danach, dass ein Neustart nötig ist (Datei /var/run/reboot-required existiert), starte den Server mit sudo reboot neu und melde dich wieder an.

3. Automatische Sicherheitsupdates installieren

unattended-upgrades spielt Sicherheitsupdates jeden Tag von selbst ein, auch für nginx und Certbot. Auf Ubuntu-Servern ist das Paket meist schon vorhanden, der Befehl schadet dann nicht.

sudo apt install unattended-upgrades

4. Automatische Updates einschalten

Der Dialog fragt, ob Updates automatisch installiert werden sollen. Wähle Ja.

sudo dpkg-reconfigure -plow unattended-upgrades

Prüfen: Die Datei enthält zwei Zeilen, die beide mit "1"; enden.

cat /etc/apt/apt.conf.d/20auto-upgrades

nginx installieren

5. nginx installieren

Installiert nginx aus den Ubuntu-Paketquellen. Der Dienst startet sofort und beim Hochfahren des Servers automatisch.

sudo apt install nginx

Prüfen: Die Versionsnummer wird angezeigt.

nginx -v

6. Autostart prüfen

Auf einem Produktionsserver muss nginx nach jedem Neustart von selbst laufen.

systemctl is-enabled nginx

Prüfen: Die Ausgabe lautet enabled. Steht dort disabled, schalte den Autostart mit sudo systemctl enable nginx ein.

7. Standardseite ausschalten

Die mitgelieferte Seite „Welcome to nginx!“ würde sonst jedem angezeigt, der die IP-Adresse des Servers aufruft. Gelöscht wird nur der Link in sites-enabled. Das Original in sites-available bleibt als Vorlage erhalten.

sudo rm /etc/nginx/sites-enabled/default

Firewall einrichten

8. SSH in der Firewall erlauben

Wichtig: Dieser Schritt muss vor dem Einschalten der Firewall kommen. Sonst sperrt ufw die laufende SSH-Verbindung, und du kommst nicht mehr auf den Server.

sudo ufw allow OpenSSH

9. HTTP und HTTPS in der Firewall erlauben

Das Profil Nginx Full wurde mit nginx installiert und öffnet Port 80 (HTTP) und Port 443 (HTTPS).

sudo ufw allow 'Nginx Full'

10. Firewall einschalten

Ab jetzt sind nur noch SSH, HTTP und HTTPS von außen erreichbar. Die Rückfrage mit y bestätigen.

sudo ufw enable

Prüfen: Die Liste enthält OpenSSH und Nginx Full, jeweils mit ALLOW.

sudo ufw status

Grundkonfiguration absichern

11. Eigene Einstellungen für alle Websites anlegen

Dateien in /etc/nginx/conf.d/ gelten für alle Websites auf dem Server. Eine eigene Datei ist besser, als nginx.conf direkt zu ändern, weil ein Update von nginx sie nicht anfasst.

  • server_tokens off blendet die Versionsnummer von nginx in Fehlerseiten und im Header Server aus. Angreifer sehen so nicht sofort, welche Version läuft.
  • client_max_body_size begrenzt, wie groß hochgeladene Daten sein dürfen. 10m reicht für Formulare und kleine Uploads.
  • Die gzip-Zeilen komprimieren Text, CSS, JavaScript und JSON. Seiten laden dadurch schneller. gzip on steht bei Ubuntu schon in nginx.conf und fehlt deshalb hier.
sudo nano /etc/nginx/conf.d/produktion.conf

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Gilt für alle Websites auf diesem Server
server_tokens off;
client_max_body_size 10m;

gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml image/svg+xml;

12. Konfiguration testen

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful. Meldet nginx "gzip_types" directive is duplicate (oder eine andere gzip-Zeile), ist diese Zeile in /etc/nginx/nginx.conf schon aktiv. Lösche sie dann in produktion.conf.

Wildcard-Zertifikat holen

Die Einzelheiten zum Nachweis über DNS stehen in der Anleitung Wildcard-Zertifikat mit Certbot. Hier folgt die Kurzfassung für den Server.

13. Certbot installieren

certbot beantragt das Zertifikat, bind9-dnsutils liefert den Befehl dig zum Prüfen der DNS-Einträge.

sudo apt install certbot bind9-dnsutils

Prüfen: Die Version wird angezeigt.

certbot --version

14. Zertifikat anfordern

nginx muss dafür nicht gestoppt werden. Der Nachweis läuft über TXT-Einträge im DNS und nicht über den Webserver. Anhalten müsste man nginx nur beim Verfahren --standalone, bei dem Certbot selbst Port 80 belegt.

  • --cert-name legt den Ordner fest: /etc/letsencrypt/live/wissen-ahrensburg.de/.
  • '*.wissen-ahrensburg.de' steht in einfachen Anführungszeichen, damit die Shell den Stern nicht als Dateimuster auswertet.
sudo certbot certonly --manual --preferred-challenges dns --cert-name wissen-ahrensburg.de -d wissen-ahrensburg.de -d '*.wissen-ahrensburg.de'

Beim ersten Aufruf fragt Certbot nach einer E-Mail-Adresse und den Nutzungsbedingungen (mit Y zustimmen).

15. Die beiden TXT-Einträge anlegen

Certbot zeigt nacheinander zwei Werte für den Namen _acme-challenge.wissen-ahrensburg.de. Lege beim Domain-Anbieter für jeden Wert einen eigenen TXT-Eintrag mit dem Namen _acme-challenge an. Beide Einträge müssen gleichzeitig bestehen. Drücke nach dem zweiten Wert noch nicht Enter.

16. TXT-Einträge prüfen

In einem zweiten Terminal (zweite SSH-Sitzung) fragst du einen öffentlichen DNS-Server, ob die Einträge schon sichtbar sind.

dig +short TXT _acme-challenge.wissen-ahrensburg.de @1.1.1.1

Prüfen: Beide Werte erscheinen. Wenn nicht, einige Minuten warten und erneut fragen. Danach im ersten Terminal Enter drücken.

Prüfen: Certbot meldet Successfully received certificate. Die TXT-Einträge kannst du danach beim Anbieter wieder löschen.

17. Zertifikat als Baustein anlegen

Die Pfade zum Zertifikat kommen in eine eigene Datei. Jede Website unter der Domain bindet sie mit einer Zeile ein.

sudo nano /etc/nginx/snippets/ssl-wissen-ahrensburg.de.conf

Füge diesen Inhalt ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Wildcard-Zertifikat für wissen-ahrensburg.de und *.wissen-ahrensburg.de
ssl_certificate     /etc/letsencrypt/live/wissen-ahrensburg.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wissen-ahrensburg.de/privkey.pem;

18. Sicherheits-Header als Baustein anlegen

Diese Header weisen den Browser an, sich vorsichtiger zu verhalten:

  • Strict-Transport-Security (HSTS): Der Browser ruft die Domain ein Jahr lang nur noch über HTTPS auf, auch wenn jemand http:// eintippt. Achtung: Diese Zusage lässt sich nicht einfach zurücknehmen. Lass den Header weg, solange HTTPS noch nicht zuverlässig läuft.
  • X-Content-Type-Options: Der Browser hält sich an den angegebenen Dateityp und rät nicht selbst.
  • X-Frame-Options: Fremde Seiten dürfen deine Seite nicht in einem Rahmen einbetten (Schutz vor untergeschobenen Klicks).
  • Referrer-Policy: Beim Klick auf fremde Links wird nur die Domain weitergegeben, nicht die ganze Adresse.

always sorgt dafür, dass die Header auch bei Fehlerseiten mitgeschickt werden.

sudo nano /etc/nginx/snippets/sicherheitsheader.conf

Füge diesen Inhalt ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Hinweis: Steht in einem location-Block eine eigene add_header-Zeile, gelten dort die Header aus dem server-Block nicht mehr. Binde den Baustein dann zusätzlich in diesem location-Block ein.

Fremde Anfragen abweisen

19. Standard-Server anlegen

Viele automatische Scanner rufen Server nur über die IP-Adresse oder mit erfundenen Domainnamen auf. Ohne passenden Eintrag würde nginx ihnen die erste Website zeigen. Dieser Standard-Server fängt alle Anfragen ab, deren Name zu keiner deiner Websites passt:

  • Auf Port 80 beendet return 444 die Verbindung ohne Antwort.
  • Auf Port 443 lehnt ssl_reject_handshake on die verschlüsselte Verbindung ab, bevor ein Zertifikat gezeigt wird. So verrät der Server nicht, welche Domains auf ihm liegen.

Die 000 am Anfang des Dateinamens sorgt dafür, dass die Datei als Erstes geladen wird und leicht zu finden ist.

sudo nano /etc/nginx/sites-available/000-standard

Füge diesen Inhalt ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Anfragen ohne bekannten Domainnamen abweisen
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    return 444;
}

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;

    ssl_reject_handshake on;
}

20. Standard-Server einschalten

sudo ln -s /etc/nginx/sites-available/000-standard /etc/nginx/sites-enabled/000-standard

Website einrichten

21. Ordner für die Website anlegen

Die Dateien der Website liegen im Unterordner html. Der Ordner gehört deinem Benutzer, damit du ohne sudo Dateien hochladen kannst. nginx braucht nur Leserechte.

sudo mkdir -p /var/www/wissen-ahrensburg.de/html
sudo chown -R "$USER":"$USER" /var/www/wissen-ahrensburg.de

22. Startseite anlegen

Eine einfache Seite zum Testen. Später ersetzt du sie durch die echte Website.

nano /var/www/wissen-ahrensburg.de/html/index.html

Füge diese Zeile ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

<h1>wissen-ahrensburg.de läuft</h1>

23. Konfiguration der Website anlegen

Die Datei enthält drei server-Blöcke:

  • Der erste leitet alle HTTP-Anfragen für die Domain und jede Subdomain dauerhaft auf HTTPS um.
  • Der zweite leitet www.wissen-ahrensburg.de auf die Adresse ohne www um. So hat jede Seite genau eine Adresse, was auch Suchmaschinen bevorzugen.
  • Der dritte ist die eigentliche Website. http2 on schaltet das schnellere Protokoll HTTP/2 ein. Eigene Log-Dateien pro Website erleichtern die Fehlersuche.
sudo nano /etc/nginx/sites-available/wissen-ahrensburg.de

Füge diesen Inhalt ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

# HTTP: alles auf HTTPS umleiten
server {
    listen 80;
    listen [::]:80;
    server_name wissen-ahrensburg.de *.wissen-ahrensburg.de;

    return 301 https://$host$request_uri;
}

# HTTPS: www auf die Adresse ohne www umleiten
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name www.wissen-ahrensburg.de;

    include snippets/ssl-wissen-ahrensburg.de.conf;

    return 301 https://wissen-ahrensburg.de$request_uri;
}

# HTTPS: die Website
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name wissen-ahrensburg.de;

    include snippets/ssl-wissen-ahrensburg.de.conf;
    include snippets/sicherheitsheader.conf;

    root /var/www/wissen-ahrensburg.de/html;
    index index.html;

    access_log /var/log/nginx/wissen-ahrensburg.de.access.log;
    error_log  /var/log/nginx/wissen-ahrensburg.de.error.log;

    location / {
        try_files $uri $uri/ =404;
    }

    # Versteckte Dateien wie .git oder .env nie ausliefern
    location ~ /\. {
        deny all;
    }
}

24. Website einschalten

sudo ln -s /etc/nginx/sites-available/wissen-ahrensburg.de /etc/nginx/sites-enabled/wissen-ahrensburg.de

25. Konfiguration testen und nginx neu laden

&& sorgt dafür, dass nginx nur neu geladen wird, wenn der Test erfolgreich war. Eine fehlerhafte Konfiguration legt die laufenden Websites so nicht lahm.

sudo nginx -t && sudo systemctl reload nginx

Prüfen: Die Ausgabe enthält test is successful. Meldet nginx cannot load certificate, stimmt der Pfad in Schritt 17 nicht mit dem Ordner unter /etc/letsencrypt/live/ überein.

Testen

Diese Befehle funktionieren auf dem Server und auf jedem anderen Rechner mit Internetzugang.

26. Umleitung auf HTTPS prüfen

curl -sI http://wissen-ahrensburg.de/ | grep -E '^HTTP|^Location'

Prüfen: Die Ausgabe lautet HTTP/1.1 301 Moved Permanently und Location: https://wissen-ahrensburg.de/.

27. Umleitung von www prüfen

curl -sI https://www.wissen-ahrensburg.de/ | grep -E '^HTTP|^location'

Prüfen: Die Ausgabe lautet HTTP/2 301 und location: https://wissen-ahrensburg.de/.

28. Website und Header prüfen

curl -sI https://wissen-ahrensburg.de/

Prüfen: Die erste Zeile lautet HTTP/2 200. Die Zeile server: zeigt nur nginx ohne Versionsnummer. Außerdem stehen dort die vier Header aus Schritt 18, z. B. strict-transport-security: max-age=31536000.

29. Abweisung über die IP-Adresse prüfen

Ersetze 203.0.113.10 durch die IPv4-Adresse deines Servers.

curl -sI http://203.0.113.10/

Prüfen: Es kommt keine Ausgabe. Ohne -s meldet curl Empty reply from server. Der Standard-Server aus Schritt 19 hat die Verbindung beendet.

30. Log-Dateien ansehen

Hier siehst du jeden Aufruf der Website. Mit Strg+C beendest du die Anzeige. Die Log-Dateien werden von logrotate täglich gewechselt und nach 14 Tagen gelöscht, damit die Festplatte nicht voll läuft.

sudo tail -f /var/log/nginx/wissen-ahrensburg.de.access.log

Zertifikat verlängern

Ein manuell beantragtes Zertifikat verlängert sich nicht von selbst. Es gilt derzeit 90 Tage. Trage dir etwa 30 Tage vor Ablauf einen Termin ein. Das genaue Vorgehen steht in der Anleitung Wildcard-Zertifikat mit Certbot im Abschnitt „Verlängern“: Schritt 14 wiederholen, neue TXT-Einträge setzen und danach nginx neu laden.

sudo systemctl reload nginx

Prüfen: Das Ablaufdatum steht bei Expiry Date.

sudo certbot certificates

Prüfen der Installation

nginx -v
systemctl is-active nginx
sudo ufw status

Prüfen: Der erste Befehl zeigt die Version, der zweite active, der dritte OpenSSH und Nginx Full mit ALLOW.

Deinstallieren

1. Websites ausschalten und Konfiguration löschen

sudo rm /etc/nginx/sites-enabled/wissen-ahrensburg.de /etc/nginx/sites-available/wissen-ahrensburg.de
sudo rm /etc/nginx/sites-enabled/000-standard /etc/nginx/sites-available/000-standard

2. Bausteine und eigene Einstellungen löschen

sudo rm /etc/nginx/snippets/ssl-wissen-ahrensburg.de.conf /etc/nginx/snippets/sicherheitsheader.conf /etc/nginx/conf.d/produktion.conf

3. Dateien der Website löschen

Achtung: Alles in /var/www/wissen-ahrensburg.de geht verloren. Sichere die Website vorher, wenn du sie noch brauchst.

sudo rm -r /var/www/wissen-ahrensburg.de

4. Zertifikat löschen

Entfernt Zertifikat und Schlüssel unter /etc/letsencrypt. Certbot fragt zur Sicherheit nach.

sudo certbot delete --cert-name wissen-ahrensburg.de

5. HTTP und HTTPS in der Firewall schließen

Die Regel für SSH bleibt bestehen, sonst sperrst du dich aus.

sudo ufw delete allow 'Nginx Full'

6. nginx und Certbot entfernen

purge entfernt auch die Konfigurationsdateien unter /etc/nginx.

sudo apt purge nginx nginx-common certbot

7. Nicht mehr benötigte Pakete entfernen

sudo apt autoremove

Prüfen: Der Befehl wird nicht mehr gefunden.

nginx -v

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

nginx als Proxy vor Apache

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

nginx nimmt die Anfragen auf Port 80 an und reicht sie an Apache weiter. Apache lauscht dabei nur lokal auf Port 8080. So laufen beide Webserver auf demselben Rechner, und Programme, die Apache brauchen (z. B. der Tileserver mit mod_tile), sind trotzdem ohne :8080 in der Adresse erreichbar.

Browser ──► nginx (Port 80) ──► Apache (127.0.0.1:8080)

Voraussetzung: nginx ist installiert und läuft (siehe nginx).

Warum kein Unix-Socket? Apache kann nur auf TCP-Ports lauschen, nicht auf einem Unix-Socket. Die Anweisung Listen nimmt nur eine IP-Adresse und einen Port an. Mit 127.0.0.1 ist Apache trotzdem nur vom eigenen Rechner aus erreichbar.

Apache auf Port 8080 einrichten

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von Apache aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Apache installieren

Ist Apache schon installiert (z. B. durch den Tileserver), meldet apt nur, dass das Paket bereits die neueste Version hat.

sudo apt install apache2

Belegt nginx schon Port 80, kann Apache nach der Installation nicht starten. Dann erscheint Address already in use. Das ist an dieser Stelle normal und wird in den nächsten Schritten behoben.

3. Apache nur lokal auf Port 8080 lauschen lassen

Ändert in ports.conf die Zeile Listen 80 (oder Listen 8080) zu Listen 127.0.0.1:8080. Danach ist Port 80 für nginx frei, und Apache nimmt nur noch Verbindungen vom eigenen Rechner an. Von außen kommt man nur noch über nginx an Apache heran.

sudo nano /etc/apache2/ports.conf

Suche mit Strg+W nach Listen und drücke Enter. Die erste Fundstelle ist die Zeile Listen 80 oder Listen 8080, die Zeilen mit Listen 443 weiter unten bleiben unverändert. Ändere die gefundene Zeile so, dass sie lautet:

Listen 127.0.0.1:8080

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Ausgabe lautet Listen 127.0.0.1:8080.

grep '^Listen' /etc/apache2/ports.conf

4. Die Standardseite von Apache auf Port 8080 umstellen

Der VirtualHost muss zum neuen Port passen. Sonst findet Apache für Anfragen auf Port 8080 keine passende Seite.

sudo nano /etc/apache2/sites-available/000-default.conf

Suche mit Strg+W nach VirtualHost und drücke Enter. Steht dort schon *:8080, ist nichts zu tun. Ändere die gefundene Zeile so, dass sie lautet:

<VirtualHost *:8080>

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Ausgabe lautet <VirtualHost *:8080>.

grep '<VirtualHost' /etc/apache2/sites-available/000-default.conf

5. Das Modul remoteip einschalten

Alle Anfragen kommen jetzt von nginx, also von 127.0.0.1. Ohne dieses Modul stünde in Apaches Logdateien bei jeder Anfrage diese Adresse. Mit remoteip übernimmt Apache die echte Adresse des Besuchers, die nginx mitschickt.

sudo a2enmod remoteip

6. remoteip konfigurieren

RemoteIPHeader gibt an, in welchem Header nginx die echte Adresse mitschickt. Wegen RemoteIPInternalProxy glaubt Apache diesem Header nur, wenn die Anfrage von 127.0.0.1 kommt. Sonst könnte jeder Besucher eine falsche Adresse vortäuschen.

sudo nano /etc/apache2/conf-available/remoteip.conf

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1

7. Die Konfiguration einbinden

Schaltet die Datei aus Schritt 6 ein. Apache liest nur Dateien aus conf-enabled.

sudo a2enconf remoteip

8. Die Apache-Konfiguration testen

Findet Tippfehler, bevor Apache neu startet.

sudo apache2ctl configtest

Prüfen: Die Ausgabe endet mit Syntax OK.

9. Apache neu starten

Erst nach einem Neustart gilt die neue Listen-Adresse. reload reicht dafür nicht.

sudo systemctl restart apache2

Prüfen: In der Ausgabe steht 127.0.0.1:8080 (nicht *:8080 oder 0.0.0.0:8080) mit dem Prozess apache2.

sudo ss -tlnp | grep ':8080'

10. Apache direkt aufrufen

Zeigt, dass Apache auf Port 8080 antwortet, noch ohne nginx.

curl -I http://127.0.0.1:8080

Prüfen: Die erste Zeile lautet HTTP/1.1 200 OK, weiter unten steht Server: Apache.

nginx als Proxy einrichten

11. Proxy-Einstellungen als Baustein anlegen

Die Einstellungen kommen in eine eigene Datei unter snippets. So kann man sie in jedem location-Block mit einer einzigen Zeile einbinden.

  • proxy_pass gibt an, wohin nginx die Anfrage weiterreicht.
  • Die proxy_set_header-Zeilen schicken den ursprünglichen Hostnamen, die Adresse des Besuchers und das Protokoll (http oder https) an Apache mit. Ohne diese Zeilen sähe Apache nur 127.0.0.1.
  • proxy_read_timeout lässt Apache bis zu 120 Sekunden Zeit für eine Antwort. Der Standardwert von 60 Sekunden reicht nicht immer, zum Beispiel wenn der Tileserver eine Kachel erst noch zeichnen muss.
sudo nano /etc/nginx/snippets/apache-proxy.conf

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
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;
proxy_read_timeout 120s;

12. Die Standardseite von nginx öffnen

In dieser Datei legt man fest, welche Adressen nginx an Apache weiterreicht.

sudo nano /etc/nginx/sites-available/default

13. Die Weiterleitung eintragen

Suche im Block server { … } den Abschnitt location / { … }. Es gibt zwei Möglichkeiten.

Variante A – alles an Apache: Ersetze die Zeile try_files $uri $uri/ =404; durch die include-Zeile. nginx liefert danach selbst keine Dateien mehr aus, sondern reicht jede Anfrage an Apache weiter.

	location / {
		include snippets/apache-proxy.conf;
	}

Variante B – nur einen Pfad an Apache: Lass location / { … } unverändert und füge darunter einen eigenen Block ein. Nur Adressen, die mit diesem Pfad beginnen, gehen an Apache, alles andere liefert nginx wie bisher selbst aus. Beim Tileserver ist das der Kachelpfad /osm/.

	location /osm/ {
		include snippets/apache-proxy.conf;
	}

Speichern mit Strg+O und Enter, beenden mit Strg+X.

14. Die nginx-Konfiguration testen

Findet Tippfehler, bevor nginx neu geladen wird.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

15. nginx neu laden

Übernimmt die neue Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

Prüfen

16. Eine Anfrage über nginx schicken

Die Anfrage geht an Port 80, also an nginx. Bei Variante B hängst du den Pfad an, beim Tileserver zum Beispiel http://localhost/osm/0/0/0.png.

curl -I http://localhost/

Prüfen: Die erste Zeile lautet HTTP/1.1 200 OK, und bei Server: steht nginx, denn nach außen antwortet immer nginx.

17. Im Log von Apache nachsehen

Hier sieht man, ob die Anfrage aus Schritt 16 wirklich bei Apache angekommen ist.

sudo tail -n 3 /var/log/apache2/access.log

Prüfen: Die letzte Zeile enthält die Anfrage aus Schritt 16 (z. B. "HEAD / HTTP/1.1") mit curl als Programmnamen. Am Zeilenanfang steht die Adresse des Besuchers, die nginx mitgeschickt hat. Bei einem Test auf dem eigenen Rechner ist das ::1 oder 127.0.0.1, bei einem anderen Rechner im Netz dessen IP-Adresse. Fehlt sie, hat nginx die Anfrage selbst beantwortet. Dann den location-Block aus Schritt 13 prüfen.

18. Prüfen, dass Apache von außen nicht erreichbar ist

Ersetze 192.168.1.10 durch die IP-Adresse deines Rechners im Netzwerk (anzeigen mit hostname -I).

curl -I --max-time 5 http://192.168.1.10:8080

Prüfen: Der Befehl meldet Connection refused oder Failed to connect. Apache ist also nur über nginx erreichbar.

Fehlersuche

  • 502 Bad Gateway: nginx erreicht Apache nicht. Meist läuft Apache nicht oder lauscht auf einem anderen Port. Prüfen mit systemctl status apache2 und sudo ss -tlnp | grep ':8080'.
  • 504 Gateway Timeout: Apache antwortet zu langsam. Den Wert proxy_read_timeout in /etc/nginx/snippets/apache-proxy.conf erhöhen, danach nginx neu laden.
  • Port 8080 ist schon belegt: Apache startet nicht und meldet Address already in use. Ein anderes Programm lauscht dann schon auf 8080. Welches, zeigt sudo ss -tlnp | grep ':8080'. Dann für Apache einen freien Port wählen und ihn in ports.conf, 000-default.conf und apache-proxy.conf eintragen.

Rückgängig machen

1. Die Weiterleitung aus nginx entfernen

Öffne die Datei wieder und mache die Änderung aus Schritt 13 rückgängig: Bei Variante A kommt try_files $uri $uri/ =404; zurück an die Stelle der include-Zeile, bei Variante B wird der zusätzliche location-Block gelöscht.

sudo nano /etc/nginx/sites-available/default

2. Den Proxy-Baustein löschen

Die Datei wird nicht mehr gebraucht.

sudo rm /etc/nginx/snippets/apache-proxy.conf

3. nginx testen und neu laden

sudo nginx -t && sudo systemctl reload nginx

4. remoteip in Apache ausschalten

Ohne nginx davor wird das Modul nicht mehr gebraucht.

sudo a2disconf remoteip && sudo a2dismod remoteip
sudo rm /etc/apache2/conf-available/remoteip.conf

5. Apache wieder auf allen Adressen lauschen lassen

Apache bleibt auf Port 8080, ist aber wieder aus dem Netzwerk erreichbar. Port 80 bleibt für nginx frei.

sudo nano /etc/apache2/ports.conf

Suche mit Strg+W nach Listen 127 und drücke Enter. Ändere die gefundene Zeile so, dass sie lautet:

Listen 8080

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

sudo systemctl restart apache2

Prüfen: In der Ausgabe steht *:8080.

sudo ss -tlnp | grep ':8080'

Soll Apache ganz verschwinden: sudo apt purge apache2 und danach sudo apt autoremove. Das aber nur, wenn kein anderes Programm (z. B. der Tileserver) Apache noch braucht.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Statische Website mit nginx

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

nginx liefert eine statische Website (HTML, CSS, Bilder, JavaScript ohne Server-Programm) sehr schnell und mit wenig Speicher aus. Diese Anleitung richtet als Beispiel die Website start.de ein.

Voraussetzung: nginx ist installiert und läuft (siehe nginx).

Zum Beispiel start.de: Die Domain ist nur ein Beispiel. Ersetze start.de in allen Befehlen durch deine eigene Domain. Zum Ausprobieren auf dem eigenen Rechner zeigt Schritt 11, wie der Rechner start.de auf sich selbst umleitet. Die echte Website unter diesem Namen ist dann auf diesem Rechner nicht mehr erreichbar, bis der Eintrag wieder entfernt ist.

Dateien der Website anlegen

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von nginx kennt, falls es noch nachinstalliert oder aktualisiert werden muss.

sudo apt update

2. Ordner für die Website anlegen

Jede Website bekommt einen eigenen Ordner unter /var/www. Der Unterordner html enthält nur die Dateien, die Besucher sehen dürfen. Andere Dateien (z. B. Notizen oder Quelldateien) kann man daneben in /var/www/start.de ablegen, ohne dass nginx sie ausliefert.

sudo mkdir -p /var/www/start.de/html

3. Den Ordner deinem Benutzer geben

So kannst du die Dateien der Website ohne sudo bearbeiten. nginx läuft als Benutzer www-data und braucht nur Leserechte, die es über die normalen Rechte (755 für Ordner, 644 für Dateien) bekommt.

sudo chown -R "$USER":"$USER" /var/www/start.de

Prüfen: Als Besitzer steht dein Benutzername.

ls -ld /var/www/start.de/html

4. Startseite anlegen

index.html ist die Seite, die nginx zeigt, wenn nur die Domain aufgerufen wird. Sie bindet ein Stylesheet ein, damit man später sieht, dass auch weitere Dateien ausgeliefert werden.

nano /var/www/start.de/html/index.html

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>start.de</title>
  <link rel="stylesheet" href="/style.css">
</head>
<body>
  <h1>Willkommen auf start.de</h1>
  <p>Diese Seite liefert nginx als statische Datei aus.</p>
</body>
</html>

5. Stylesheet anlegen

Eine kleine CSS-Datei als Beispiel für zusätzliche Dateien wie Bilder oder Skripte.

nano /var/www/start.de/html/style.css

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

body { font-family: sans-serif; max-width: 40rem; margin: 3rem auto; padding: 0 1rem; }
h1 { color: #2a6f4f; }

6. Eigene Fehlerseite anlegen

Diese Seite erscheint, wenn jemand eine Adresse aufruft, die es nicht gibt. Ohne sie zeigt nginx eine schlichte Standardseite.

nano /var/www/start.de/html/404.html

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<!DOCTYPE html>
<html lang="de">
<head><meta charset="utf-8"><title>Nicht gefunden</title><link rel="stylesheet" href="/style.css"></head>
<body><h1>Seite nicht gefunden</h1><p><a href="/">Zur Startseite</a></p></body>
</html>

nginx einrichten

7. Konfiguration für start.de anlegen

Jede Website bekommt in sites-available eine eigene Datei mit einem server-Block. Die wichtigsten Zeilen:

  • listen 80 und listen [::]:80 – nimmt Anfragen auf Port 80 an, über IPv4 und IPv6.
  • server_name – nginx wählt diesen Block nur, wenn der Browser start.de oder www.start.de aufruft. So können mehrere Websites denselben Port nutzen.
  • root – der Ordner, aus dem die Dateien kommen.
  • access_log und error_log – eigene Logdateien, damit die Einträge dieser Website nicht mit anderen vermischt sind.
  • try_files – liefert die angefragte Datei oder den Ordner aus. Gibt es beides nicht, antwortet nginx mit dem Fehler 404.
  • error_page 404 – zeigt dann die Fehlerseite aus Schritt 6.
  • expires 7d – der Browser darf CSS, Skripte, Bilder und Schriften sieben Tage zwischenspeichern und lädt sie nicht bei jedem Seitenaufruf neu.
sudo nano /etc/nginx/sites-available/start.de

Steht aus einer anderen Anleitung schon Inhalt in der Datei, lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 80;
    listen [::]:80;
    server_name start.de www.start.de;

    root /var/www/start.de/html;
    index index.html;

    access_log /var/log/nginx/start.de.access.log;
    error_log  /var/log/nginx/start.de.error.log;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;

    location ~* \.(css|js|png|jpe?g|gif|svg|webp|ico|woff2?)$ {
        expires 7d;
    }
}

Mehr zum Aufbau der Konfiguration, zu späteren Änderungen und zur Fehlersuche steht in der Anleitung nginx-Konfiguration mit nano bearbeiten.

8. Website einschalten

nginx lädt nur Konfigurationen aus sites-enabled. Ein Link dorthin schaltet die Website ein. Die Datei selbst bleibt in sites-available, so kann man die Website später durch Löschen des Links wieder ausschalten.

sudo ln -s /etc/nginx/sites-available/start.de /etc/nginx/sites-enabled/start.de

9. Konfiguration testen

Findet Tippfehler, bevor nginx neu geladen wird.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

10. nginx neu laden

Übernimmt die neue Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

Auf dem eigenen Rechner testen

11. start.de auf den eigenen Rechner umleiten

Normalerweise fragt der Rechner im Internet (DNS) nach, wohin start.de gehört. Ein Eintrag in /etc/hosts hat Vorrang und schickt die Anfragen stattdessen an den eigenen Rechner (127.0.0.1). So lässt sich die Website testen, bevor die Domain wirklich auf einen Server zeigt.

sudo nano /etc/hosts

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile diesen Eintrag ein. Speichere mit Strg+O und Enter und beende nano mit Strg+X:

127.0.0.1 start.de www.start.de

Prüfen: Als Adresse erscheint 127.0.0.1.

getent hosts start.de

12. Startseite abrufen

curl http://start.de

Prüfen: Die Ausgabe enthält <h1>Willkommen auf start.de</h1>. Im Browser: http://start.de. Die Überschrift ist dort grün, das Stylesheet wird also mitgeladen.

13. Zwischenspeichern für CSS prüfen

-I zeigt nur die Kopfzeilen der Antwort.

curl -I http://start.de/style.css

Prüfen: In der Ausgabe stehen Content-Type: text/css und Cache-Control: max-age=604800 (sieben Tage in Sekunden).

14. Fehlerseite prüfen

Ruft eine Adresse auf, die es nicht gibt.

curl -i http://start.de/gibt-es-nicht

Prüfen: Die erste Zeile lautet HTTP/1.1 404 Not Found, darunter folgt der Inhalt der eigenen Fehlerseite mit Seite nicht gefunden.

15. Die Logdatei ansehen

Hier steht jede Anfrage an start.de mit Zeit, Adresse und Statuscode.

sudo tail -n 5 /var/log/nginx/start.de.access.log

Website ändern

Neue oder geänderte Dateien einfach in /var/www/start.de/html ablegen. nginx liefert sie sofort aus, ein Neuladen ist nicht nötig. Neu laden (Schritte 9 und 10) muss man nur nach Änderungen an /etc/nginx/sites-available/start.de.

Der Browser kann CSS- und Bilddateien bis zu sieben Tage aus seinem Zwischenspeicher nehmen. Nach einer Änderung an style.css im Browser deshalb mit Strg+Shift+R neu laden.

Optional: Im Internet veröffentlichen

Ein Zertifikat, das auch für alle Subdomains wie blog.start.de gilt, beschreibt die Anleitung Wildcard-Zertifikat mit Certbot.

Diese Schritte gehen nur auf einem Server, der aus dem Internet erreichbar ist, und nur mit einer Domain, die dir gehört.

1. Den Testeintrag entfernen

Der Eintrag aus Schritt 11 würde sonst weiter auf den eigenen Rechner zeigen.

sudo nano /etc/hosts

Suche mit Strg+W nach start.de und drücke Enter. Lösche die Zeile 127.0.0.1 start.de www.start.de mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

2. Die Domain auf den Server zeigen lassen

Beim Anbieter der Domain für start.de und www.start.de je einen A-Eintrag mit der öffentlichen IPv4-Adresse des Servers anlegen (bei IPv6 zusätzlich einen AAAA-Eintrag). Das geschieht in der Weboberfläche des Anbieters, nicht auf dem Server.

Prüfen: Nach einigen Minuten bis Stunden erscheint die IP-Adresse des Servers.

getent hosts start.de

3. Die Firewall für nginx öffnen

Nur nötig, wenn die Firewall ufw eingeschaltet ist. Nginx Full öffnet die Ports 80 (HTTP) und 443 (HTTPS).

sudo ufw allow 'Nginx Full'

4. Certbot installieren

Certbot holt kostenlose HTTPS-Zertifikate von Let's Encrypt. Das Zusatzpaket für nginx trägt die Zertifikate auch gleich in die Konfiguration ein.

sudo apt install certbot python3-certbot-nginx

5. Zertifikat holen und HTTPS einschalten

Certbot fragt beim ersten Aufruf nach einer E-Mail-Adresse und den Nutzungsbedingungen. Danach ergänzt es die Datei /etc/nginx/sites-available/start.de um HTTPS und leitet HTTP-Aufrufe auf HTTPS um.

sudo certbot --nginx -d start.de -d www.start.de

Prüfen: Die erste Zeile lautet HTTP/2 200 oder HTTP/1.1 200 OK.

curl -I https://start.de

Das Zertifikat gilt 90 Tage. Das Paket richtet eine automatische Verlängerung ein. Ob sie funktioniert, zeigt ein Probelauf:

sudo certbot renew --dry-run

Prüfen der Installation

nginx -v
sudo nginx -T 2>/dev/null | grep 'server_name start.de'

Prüfen: Der erste Befehl zeigt die Version von nginx, der zweite die Zeile server_name start.de www.start.de;.

Deinstallieren

nginx selbst bleibt installiert. Wie man nginx ganz entfernt, steht in der Anleitung nginx.

1. Website ausschalten

Löscht den Link in sites-enabled. nginx lädt die Konfiguration danach nicht mehr.

sudo rm /etc/nginx/sites-enabled/start.de

2. Konfiguration löschen

sudo rm /etc/nginx/sites-available/start.de

3. nginx testen und neu laden

sudo nginx -t && sudo systemctl reload nginx

4. Dateien der Website löschen

Achtung: Alles in /var/www/start.de geht verloren. Vorher bei Bedarf sichern.

sudo rm -r /var/www/start.de

5. Logdateien löschen

sudo rm /var/log/nginx/start.de.*

6. Testeintrag aus /etc/hosts entfernen

Nur nötig, wenn der Eintrag aus Schritt 11 noch besteht. Danach ist die echte Website start.de wieder erreichbar.

sudo nano /etc/hosts

Suche mit Strg+W nach start.de und drücke Enter. Lösche die Zeile 127.0.0.1 start.de www.start.de mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Es erscheint nicht mehr 127.0.0.1.

getent hosts start.de

7. Zertifikat löschen

Nur nötig, wenn im optionalen Teil ein Zertifikat geholt wurde.

sudo certbot delete --cert-name start.de

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

nginx-Konfiguration mit nano bearbeiten

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Diese Anleitung zeigt, wie man die Konfiguration einer statischen Website von Hand im Terminal-Editor GNU nano anlegt und ändert, am Beispiel start.de. Dabei geht es auch um den Aufbau einer nginx-Konfiguration und darum, Tippfehler anhand der Meldungen von nginx -t zu finden.

Voraussetzung: nginx ist installiert (siehe nginx), und die Dateien der Website liegen in /var/www/start.de/html. Wie man sie anlegt, zeigen die Schritte 2 bis 6 der Anleitung Statische Website mit nginx. Dort wird die fertige Konfiguration nur eingefügt. Hier geht es ausführlicher um ihren Aufbau, um spätere Änderungen und um die Fehlersuche.

Vorbereitung

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von nano kennt.

sudo apt update

2. nano installieren

Unter Ubuntu ist nano meist schon vorhanden. Dann meldet apt das nur.

sudo apt install nano

Prüfen: Die Versionsnummer wird angezeigt, z. B. GNU Nano, Version 8.7.1.

nano --version

3. Vorhandene Konfiguration sichern

Nur nötig, wenn es die Datei /etc/nginx/sites-available/start.de schon gibt, z. B. aus der Anleitung Statische Website mit nginx. Die Kopie liegt bewusst außerhalb von sites-available und sites-enabled. So kann nginx sie nicht versehentlich als zweite Website laden. -p behält Rechte und Zeitstempel bei.

sudo cp -p /etc/nginx/sites-available/start.de /root/start.de.sicherung

Prüfen: Ohne vorhandene Datei meldet cp Datei oder Verzeichnis nicht gefunden. Das ist dann in Ordnung, es gibt nichts zu sichern.

So ist eine nginx-Konfiguration aufgebaut

Bevor du tippst, lohnt ein Blick auf die Schreibregeln. nginx ist dabei streng. Ein einziges fehlendes Zeichen verhindert, dass die neue Konfiguration geladen wird.

RegelBeispiel
Jede Einstellung (Anweisung) steht meist in einer eigenen Zeile: vorne das Stichwort, dahinter ein oder mehrere Werte. Den Schluss bildet immer ein ;root /var/www/start.de/html;
Ein Block fasst Anweisungen in geschweiften Klammern zusammen. Jede { braucht eine passende }. Nach } steht kein ;server { … }
Der server-Block beschreibt eine Websiteserver { listen 80; … }
Ein location-Block gilt nur für bestimmte Adressen innerhalb der Websitelocation / { … }
Mit # beginnen Kommentare: Notizen für Menschen, die nginx beim Lesen einfach überspringt. Sie dürfen auch hinter einer Anweisung stehenexpires 7d; # eine Woche
Einrückungen sind für nginx egal, machen die Datei aber lesbar. Üblich sind vier Leerzeichen pro Ebene

Konfiguration in nano anlegen

4. Datei in nano öffnen

sudo ist nötig, weil Dateien unter /etc/nginx dem Benutzer root gehören. -l zeigt links Zeilennummern an. Die braucht man später, weil nginx -t Fehler mit Zeilennummer meldet.

sudo nano -l /etc/nginx/sites-available/start.de

Prüfen: Unten steht Neue Datei, wenn es die Datei noch nicht gab. Sonst zeigt nano ihren Inhalt und meldet z. B. 28 Zeilen gelesen.

5. Vorhandenen Inhalt löschen

Nur nötig, wenn die Datei schon Text enthält. Drücke so oft Strg+K, bis die Datei leer ist. Jeder Druck schneidet eine Zeile aus. Die gesicherte Kopie aus Schritt 3 bleibt davon unberührt.

6. Konfiguration eingeben

Tippe den folgenden Text ab oder kopiere ihn und füge ihn im Terminal mit Strg+Umschalt+V ein. Die Bedeutung der Zeilen:

  • listen – Port 80, über IPv4 und IPv6
  • server_name – der Block gilt nur für Anfragen an start.de und www.start.de
  • root – Ordner mit den Dateien der Website, index – Startdatei eines Ordners
  • access_log, error_log – eigene Logdateien für diese Website
  • location / – liefert die angefragte Datei aus, sonst Fehler 404
  • error_page – eigene Fehlerseite statt der schlichten Seite von nginx
  • zweiter location-Block – CSS, Skripte, Bilder und Schriften darf der Browser 7 Tage zwischenspeichern
# Statische Website start.de
server {
    listen 80;
    listen [::]:80;
    server_name start.de www.start.de;

    root /var/www/start.de/html;
    index index.html;

    access_log /var/log/nginx/start.de.access.log;
    error_log  /var/log/nginx/start.de.error.log;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;

    location ~* \.(css|js|png|jpe?g|gif|svg|webp|ico|woff2?)$ {
        expires 7d;
    }
}

Beim Einfügen rückt nano manchmal zusätzlich ein. Das stört nginx nicht.

Prüfen: Links stehen die Zeilennummern 1 bis 22. Die letzte Zeile ist } ganz am Zeilenanfang.

7. Datei speichern

Drücke Strg+O. Unten fragt nano nach dem Dateinamen, der schon eingetragen ist. Bestätige mit Enter.

Prüfen: Unten erscheint 22 Zeilen geschrieben.

8. nano beenden

Drücke Strg+X. Fragt nano Geänderten Puffer speichern?, wurde nach dem Speichern noch etwas geändert. Dann mit J speichern oder mit N verwerfen.

9. Website einschalten

nginx lädt nur Dateien aus sites-enabled. Der Link schaltet die Website ein. Meldet der Befehl Die Datei existiert bereits, ist die Website schon eingeschaltet. Dann geht es mit dem nächsten Schritt weiter.

sudo ln -s /etc/nginx/sites-available/start.de /etc/nginx/sites-enabled/start.de

10. Konfiguration testen

nginx -t liest alle Konfigurationsdateien und prüft sie, ohne den laufenden Webserver zu verändern. Diesen Schritt nie auslassen: Bei einem Fehler würde nginx die Konfiguration beim Neuladen nicht übernehmen, und ein späterer Neustart würde scheitern.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful. Steht dort test failed, hilft der Abschnitt Fehler finden und beheben.

11. nginx neu laden

Übernimmt die neue Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

12. Website abrufen

Zum Test auf dem eigenen Rechner muss start.de auf 127.0.0.1 zeigen. Wie das geht, steht in Schritt 11 der Anleitung Statische Website mit nginx.

curl -I http://start.de/style.css

Prüfen: Die erste Zeile lautet HTTP/1.1 200 OK, weiter unten steht Cache-Control: max-age=604800 (7 Tage in Sekunden).

Konfiguration ändern

Als Beispiel werden zwei Einstellungen geändert: Der Browser soll CSS und Bilder 30 statt 7 Tage zwischenspeichern, und nginx soll CSS und JavaScript komprimiert übertragen.

13. Datei erneut öffnen

sudo nano -l /etc/nginx/sites-available/start.de

14. Die Stelle suchen

Drücke Strg+W, tippe expires und drücke Enter. Der Cursor springt zur ersten Fundstelle. Alt+W springt zur nächsten.

Prüfen: Der Cursor steht in der Zeile expires 7d;.

15. Wert ändern

Bewege den Cursor mit den Pfeiltasten auf die 7, lösche sie mit Entf und tippe 30. Die Zeile lautet danach expires 30d;. Das Semikolon am Ende muss stehen bleiben.

16. Komprimierung ergänzen

Ubuntu schaltet die Komprimierung in /etc/nginx/nginx.conf mit gzip on; ein, dort aber nur für HTML. Welche weiteren Dateitypen komprimiert werden, legt gzip_types fest. Die Einstellung gilt hier nur für diese Website.

Setze den Cursor an das Ende der Zeile index index.html;, drücke Enter und tippe:

    gzip_types text/css application/javascript image/svg+xml;

Prüfen: Die neue Zeile steht direkt unter index index.html; und endet mit ;.

17. Speichern und beenden

Strg+O, Enter, dann Strg+X.

Prüfen: Vor dem Beenden meldet nano 23 Zeilen geschrieben, eine Zeile mehr als vorher.

18. Testen und neu laden

Erst testen, dann laden. Das && sorgt dafür, dass nginx nur neu geladen wird, wenn der Test erfolgreich war.

sudo nginx -t && sudo systemctl reload nginx

Prüfen: Die Ausgabe enthält test is successful.

19. Änderungen prüfen

-H 'Accept-Encoding: gzip' teilt nginx mit, dass curl komprimierte Antworten versteht, so wie es jeder Browser tut.

curl -sI -H 'Accept-Encoding: gzip' http://start.de/style.css | grep -iE 'cache-control|content-encoding'

Prüfen: Die Ausgabe lautet Cache-Control: max-age=2592000 (30 Tage in Sekunden) und Content-Encoding: gzip.

Fehler finden und beheben

20. Fehlermeldung lesen

Schlägt nginx -t fehl, nennt die Meldung die Art des Fehlers, die Datei und nach dem Doppelpunkt die Zeile, zum Beispiel:

nginx: [emerg] invalid number of arguments in "root" directive in /etc/nginx/sites-enabled/start.de:8

Die häufigsten Meldungen:

MeldungUrsache
invalid number of arguments in "root" directiveMeist fehlt am Ende der Zeile davor das ;. nginx liest dann zwei Zeilen als eine Anweisung und meldet die Zeile, in der es das nächste ; findet. Im Beispiel steht der Fehler also in Zeile 7.
unknown directive "roott"Tippfehler im Namen einer Anweisung
unexpected end of file, expecting "}"Eine } fehlt. nginx bemerkt das erst am Dateiende.
unexpected "}"Eine } zu viel
conflicting server name "start.de" (Warnung)Zwei Dateien in sites-enabled beanspruchen dieselbe Domain, z. B. wenn eine Kopie der Konfiguration dort liegt

Der Pfad in der Meldung zeigt meist auf sites-enabled. Das ist nur der Link. Bearbeitet wird immer die Datei in sites-available.

21. Direkt zur gemeldeten Zeile springen

+8 öffnet die Datei und setzt den Cursor gleich in Zeile 8. Ersetze die Zahl durch die Zeile aus deiner Meldung. Bei invalid number of arguments schau auch in die Zeile darüber. In einer bereits geöffneten Datei springt Strg+_ zu einer Zeilennummer.

sudo nano -l +8 /etc/nginx/sites-available/start.de

Korrigiere den Fehler, speichere mit Strg+O, Enter, beende mit Strg+X und teste erneut mit sudo nginx -t.

22. Optional: Fehler zum Üben einbauen

Öffne die Datei wie in Schritt 13, lösche am Ende der Zeile root /var/www/start.de/html; das ;, speichere und teste mit sudo nginx -t. Die Meldung nennt die Zeile unter der geänderten Zeile. Setze das ; wieder ein, speichere und teste erneut, bis test is successful erscheint. Solange du nicht neu lädst, läuft nginx mit der alten, fehlerfreien Konfiguration einfach weiter.

Nützliche Tastenkürzel in nano

TastenWirkung
Strg+O, EnterSpeichern
Strg+XBeenden
Strg+WSuchen, Alt+W springt zum nächsten Treffer
Strg+_Zu einer Zeilennummer springen
Strg+K / Strg+UZeile ausschneiden / wieder einfügen, auch an anderer Stelle
Alt+U / Alt+ERückgängig / Wiederherstellen
Alt+3Aktuelle Zeile mit # aus- oder wieder einkommentieren. Praktisch, um eine Einstellung vorübergehend abzuschalten
Alt+NZeilennummern ein- und ausblenden
Strg+GHilfe mit allen Tastenkürzeln

Prüfen der Installation

nano --version
sudo nginx -T 2>/dev/null | grep -E 'expires|gzip_types'

Prüfen: Der erste Befehl zeigt die Version von nano, der zweite die Zeilen gzip_types … und expires 30d; aus der Konfiguration.

Rückgängig machen und deinstallieren

1. Alte Konfiguration zurückholen

Nur möglich, wenn in Schritt 3 eine Sicherung angelegt wurde. Überschreibt die Datei mit dem Stand vor dieser Anleitung.

sudo cp -p /root/start.de.sicherung /etc/nginx/sites-available/start.de

2. Oder: Website ganz entfernen

Gab es vorher keine Konfiguration, entfernst du Link und Datei. Die Dateien der Website und weitere Reste entfernt der Abschnitt „Deinstallieren“ der Anleitung Statische Website mit nginx.

sudo rm /etc/nginx/sites-enabled/start.de /etc/nginx/sites-available/start.de

3. nginx testen und neu laden

sudo nginx -t && sudo systemctl reload nginx

4. Sicherung löschen

sudo rm -f /root/start.de.sicherung

5. nano entfernen (nicht empfohlen)

nano ist unter Ubuntu der vorgegebene Editor, etwa für sudo visudo oder crontab -e. Entferne es nur, wenn ein anderer Editor eingerichtet ist. Die genauen Schritte stehen in der Anleitung GNU nano.

Prüfen: Nach Schritt 3 meldet sudo nginx -t wieder test is successful.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Drupal mit nginx unter eigener Domain

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Diese Anleitung macht eine vorhandene Drupal-Installation unter einer eigenen Domain erreichbar, hier am Beispiel start.de. nginx nimmt die Anfragen auf Port 80 an, führt PHP über PHP-FPM aus und leitet www.start.de auf start.de um.

Voraussetzung: Drupal ist nach der Anleitung Drupal vollständig eingerichtet (Dateien in /var/www/drupal, Datenbank installiert, Test unter http://localhost:8090 erfolgreich).

Zum Beispiel start.de: Die Domain ist nur ein Beispiel. Ersetze start.de in allen Befehlen durch deine eigene Domain. Zum Ausprobieren auf dem eigenen Rechner leitet Schritt 9 start.de auf den eigenen Rechner um. Die echte Website unter diesem Namen ist dann auf diesem Rechner nicht mehr erreichbar, bis der Eintrag wieder entfernt ist.

nginx einrichten

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von nginx und PHP-FPM kennt, falls sie noch aktualisiert werden müssen.

sudo apt update

2. Drupal-Regeln als Baustein anlegen

Die Regeln, die Drupal braucht, kommen in eine eigene Datei unter snippets. Der server-Block in Schritt 3 bindet sie mit einer einzigen include-Zeile ein. So lassen sich die Regeln auch für weitere Drupal-Websites wiederverwenden.

nginx prüft Blöcke mit regulären Ausdrücken (~) von oben nach unten und nimmt den ersten Treffer. Deshalb stehen die Sperren vor dem Block, der PHP ausführt:

  • Sperren: versteckte Dateien wie .git, interne Drupal-Dateien wie .yml und .twig sowie PHP-Dateien im Upload-Ordner sites/…/files. Eine hochgeladene Datei lässt sich so nie als Programm starten.
  • PHP: Alle .php-Dateien gehen an PHP-FPM, auch mit angehängtem Pfad wie /update.php/selection.
  • Bilder, CSS, JavaScript: Der Browser darf sie 30 Tage zwischenspeichern. Fehlt eine Datei, erzeugt Drupal sie, z. B. verkleinerte Bilder.
  • Alles andere: Adressen wie /node/1 beantwortet Drupal über index.php.
sudo nano /etc/nginx/snippets/drupal.conf

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Versteckte Dateien und Ordner sperren, außer .well-known (für HTTPS-Zertifikate)
location ~ /\.(?!well-known/) {
    return 403;
}

# Interne Drupal-Dateien sperren
location ~* \.(engine|inc|install|module|profile|theme|twig|yml|yaml|sql|lock|log|md)$ {
    return 403;
}

# Hochgeladene Dateien nie als PHP ausführen
location ~ ^/sites/[^/]+/files/.*\.php$ {
    return 403;
}

# PHP über PHP-FPM ausführen
location ~ \.php(/|$) {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php-fpm.sock;
}

# Statische Dateien zwischenspeichern, fehlende von Drupal erzeugen lassen
location ~* \.(css|js|png|jpe?g|gif|ico|svg|webp|woff2?)$ {
    try_files $uri /index.php?$query_string;
    expires 30d;
    access_log off;
}

# Alle übrigen Adressen beantwortet Drupal
location / {
    try_files $uri $uri/ /index.php?$query_string;
}

3. Konfiguration für start.de anlegen

Die Datei enthält zwei server-Blöcke:

  • Der erste beantwortet nur Anfragen an www.start.de und leitet sie dauerhaft (Status 301) auf start.de um. So gibt es jede Seite nur unter einer Adresse, was auch Suchmaschinen bevorzugen. $scheme behält http oder https bei, $request_uri den Pfad.
  • Der zweite ist die eigentliche Website. root zeigt auf den Ordner web der Drupal-Installation. client_max_body_size erlaubt Uploads bis 20 MB, ohne diese Zeile lehnt nginx alles über 1 MB ab. Die eigenen Logdateien halten die Einträge dieser Website getrennt.
sudo nano /etc/nginx/sites-available/start.de

Steht aus einer anderen Anleitung schon Inhalt in der Datei, lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 80;
    listen [::]:80;
    server_name www.start.de;

    return 301 $scheme://start.de$request_uri;
}

server {
    listen 80;
    listen [::]:80;
    server_name start.de;

    root /var/www/drupal/web;
    index index.php;

    client_max_body_size 20m;

    access_log /var/log/nginx/start.de.access.log;
    error_log  /var/log/nginx/start.de.error.log;

    include snippets/drupal.conf;
}

4. Website einschalten

nginx lädt nur Konfigurationen aus sites-enabled. Der Link schaltet die Website ein, die Datei selbst bleibt in sites-available.

sudo ln -s /etc/nginx/sites-available/start.de /etc/nginx/sites-enabled/start.de

5. Konfiguration testen

Findet Tippfehler in beiden neuen Dateien, bevor nginx neu geladen wird.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

6. nginx neu laden

Übernimmt die neue Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

Drupal einstellen

7. Erlaubte Hostnamen festlegen

Drupal beantwortet sonst Anfragen mit jedem beliebigen Hostnamen. Das nutzen Angreifer, um gefälschte Links zu erzeugen, etwa in E-Mails zum Zurücksetzen von Passwörtern. trusted_host_patterns legt fest, unter welchen Namen die Website antworten darf. localhost bleibt erlaubt, damit der Zugang über http://localhost:8090 aus der Drupal-Anleitung weiter funktioniert. Die Punkte sind mit \ geschützt, weil die Angaben reguläre Ausdrücke sind.

Die Datei settings.php ist nach der Installation schreibgeschützt. Mit sudo darf nano sie trotzdem speichern. Die erste Zeile des neuen Abschnitts ist ein Kommentar, an dem er sich beim Deinstallieren wiederfinden lässt.

sudo nano /var/www/drupal/web/sites/default/settings.php

Springe mit Strg+Ende ans Ende der Datei, füge nach einer Leerzeile diesen Abschnitt ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

// start.de: erlaubte Hostnamen
$settings['trusted_host_patterns'] = [
  '^start\.de$',
  '^www\.start\.de$',
  '^localhost$',
];

Prüfen: PHP meldet No syntax errors detected.

sudo php -l /var/www/drupal/web/sites/default/settings.php

8. Drupal-Zwischenspeicher leeren

Drupal liest settings.php zwar bei jeder Anfrage neu, hat aber fertige Seiten im Zwischenspeicher. Nach dem Leeren entstehen alle Seiten neu.

sudo -u www-data /var/www/drupal/vendor/bin/drush cache:rebuild --root=/var/www/drupal/web

Prüfen: Die Ausgabe lautet [success] Cache rebuild complete.

Auf dem eigenen Rechner testen

9. start.de auf den eigenen Rechner umleiten

Ein Eintrag in /etc/hosts hat Vorrang vor dem DNS im Internet und schickt die Anfragen an den eigenen Rechner. So lässt sich die Website testen, bevor die Domain auf einen Server zeigt.

sudo nano /etc/hosts

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile diesen Eintrag ein. Speichere mit Strg+O und Enter und beende nano mit Strg+X:

127.0.0.1 start.de www.start.de

Prüfen: Als Adresse erscheint 127.0.0.1.

getent hosts start.de

10. Startseite abrufen

-I zeigt nur die Kopfzeilen der Antwort.

curl -I http://start.de/

Prüfen: Die erste Zeile lautet HTTP/1.1 200 OK, weiter unten steht X-Generator: Drupal. Im Browser: http://start.de.

11. Anmeldeseite abrufen

Eine Adresse, die es nicht als Datei gibt. nginx muss sie an Drupal weiterreichen.

curl -sI http://start.de/user/login | head -n 1

Prüfen: Die Ausgabe lautet HTTP/1.1 200 OK. Im Browser kannst du dich unter http://start.de/user/login mit dem Administrator-Konto aus der Drupal-Anleitung anmelden.

12. Umleitung von www prüfen

curl -sI http://www.start.de/user/login | grep -E '^HTTP|^Location'

Prüfen: Die Ausgabe lautet HTTP/1.1 301 Moved Permanently und Location: http://start.de/user/login.

13. Sperren prüfen

Stichprobe, ob interne Dateien wirklich gesperrt sind. core.services.yml ist eine Einstellungsdatei aus dem Drupal-Kern.

curl -sI http://start.de/core/core.services.yml | head -n 1

Prüfen: Die Ausgabe lautet HTTP/1.1 403 Forbidden.

14. Erlaubte Hostnamen prüfen

Schickt eine Anfrage mit einem fremden Hostnamen an den Zugang auf Port 8090 aus der Drupal-Anleitung. Über Port 80 geht das nicht, weil nginx dort nur die Namen start.de und www.start.de an Drupal weitergibt.

curl -s -H 'Host: boese.example' http://127.0.0.1:8090/ | head -n 1

Prüfen: Drupal antwortet mit The provided host name is not valid for this server. Ohne Schritt 7 käme stattdessen die normale Startseite.

15. Logdatei ansehen

Hier steht jede Anfrage an start.de mit Zeit, Adresse und Statuscode.

sudo tail -n 5 /var/log/nginx/start.de.access.log

Optional: Im Internet veröffentlichen

Diese Schritte gehen nur auf einem Server, der aus dem Internet erreichbar ist, und nur mit einer Domain, die dir gehört.

1. Testeintrag entfernen

Sonst zeigt start.de auf diesem Rechner weiter auf 127.0.0.1.

sudo nano /etc/hosts

Suche mit Strg+W nach start.de und drücke Enter. Lösche die Zeile 127.0.0.1 start.de www.start.de mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

2. Domain auf den Server zeigen lassen

In der Weboberfläche des Domain-Anbieters für start.de und www.start.de je einen A-Eintrag mit der öffentlichen IPv4-Adresse des Servers anlegen, bei IPv6 zusätzlich einen AAAA-Eintrag.

Prüfen: Nach einigen Minuten bis Stunden erscheint die Adresse des Servers.

getent hosts start.de

3. Firewall öffnen

Nur nötig, wenn ufw eingeschaltet ist. Das Profil Nginx Full öffnet Port 80 und 443.

sudo ufw allow 'Nginx Full'

4. Certbot installieren

Certbot besorgt kostenlose Zertifikate von Let's Encrypt. Das Zusatzpaket trägt sie direkt in die nginx-Konfiguration ein.

sudo apt install certbot python3-certbot-nginx

5. HTTPS einschalten

Certbot fragt beim ersten Aufruf nach einer E-Mail-Adresse und den Nutzungsbedingungen. Danach ergänzt es beide server-Blöcke in /etc/nginx/sites-available/start.de um HTTPS und leitet HTTP auf HTTPS um. Drupal erkennt HTTPS selbst und erzeugt danach Links mit https://.

sudo certbot --nginx -d start.de -d www.start.de

Prüfen: Die erste Zeile lautet HTTP/2 200 oder HTTP/1.1 200 OK.

curl -sI https://start.de/ | head -n 1

Das Zertifikat gilt 90 Tage und wird automatisch verlängert. Einen Probelauf der Verlängerung startet dieser Befehl:

sudo certbot renew --dry-run

Prüfen der Installation

nginx -v
sudo nginx -T 2>/dev/null | grep 'include snippets/drupal.conf'

Prüfen: Der erste Befehl zeigt die Version von nginx, der zweite die include-Zeile aus Schritt 3.

Deinstallieren

Drupal selbst bleibt erhalten und ist weiter unter http://localhost:8090 erreichbar. Wie man Drupal ganz entfernt, steht in der Anleitung Drupal.

1. Website ausschalten

Löscht den Link in sites-enabled.

sudo rm /etc/nginx/sites-enabled/start.de

2. Konfiguration und Baustein löschen

sudo rm /etc/nginx/sites-available/start.de /etc/nginx/snippets/drupal.conf

3. nginx testen und neu laden

sudo nginx -t && sudo systemctl reload nginx

4. Erlaubte Hostnamen aus Drupal entfernen

Löscht den Abschnitt aus Schritt 7, vom Kommentar bis zur schließenden Klammer ];.

sudo nano /var/www/drupal/web/sites/default/settings.php

Suche mit Strg+W nach start.de: erlaubte Hostnamen und drücke Enter. Der Cursor steht in der Kommentarzeile. Drücke sechsmal Strg+K. Das entfernt den Kommentar, die Zeile mit trusted_host_patterns, die drei Namen und die schließende Klammer ];. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Ausgabe ist leer, und PHP meldet keinen Syntaxfehler.

sudo grep -n "start" /var/www/drupal/web/sites/default/settings.php
sudo php -l /var/www/drupal/web/sites/default/settings.php

5. Logdateien löschen

sudo rm /var/log/nginx/start.de.*

6. Testeintrag aus /etc/hosts entfernen

Nur nötig, wenn der Eintrag aus Schritt 9 noch besteht.

sudo nano /etc/hosts

Suche mit Strg+W nach start.de und drücke Enter. Lösche die Zeile 127.0.0.1 start.de www.start.de mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Es erscheint nicht mehr 127.0.0.1.

getent hosts start.de

7. Zertifikat löschen

Nur nötig, wenn im optionalen Teil ein Zertifikat geholt wurde.

sudo certbot delete --cert-name start.de

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

MediaWiki mit nginx unter eigener Domain

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Diese Anleitung macht ein vorhandenes MediaWiki unter einer eigenen Domain erreichbar, hier am Beispiel start.de. nginx nimmt die Anfragen auf Port 80 an, führt PHP über PHP-FPM aus und sorgt für kurze Adressen wie start.de/Hauptseite. Aufrufe von www.start.de leitet es auf start.de um.

Voraussetzung: MediaWiki ist nach der Anleitung MediaWiki vollständig eingerichtet (Dateien in /var/www/mediawiki, kurze Adressen eingeschaltet, Test unter http://localhost:8085 erfolgreich).

Zum Beispiel start.de: Die Domain ist nur ein Beispiel. Ersetze start.de in allen Befehlen durch deine eigene Domain. Zum Ausprobieren auf dem eigenen Rechner leitet Schritt 10 start.de auf den eigenen Rechner um. Die echte Website unter diesem Namen ist dann auf diesem Rechner nicht mehr erreichbar, bis der Eintrag wieder entfernt ist.

nginx einrichten

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von nginx und PHP-FPM kennt, falls sie noch aktualisiert werden müssen.

sudo apt update

2. MediaWiki-Regeln als Baustein anlegen

Die Regeln, die MediaWiki braucht, kommen in eine eigene Datei unter snippets. Der server-Block in Schritt 3 bindet sie mit einer include-Zeile ein.

nginx prüft Blöcke mit regulären Ausdrücken (~) von oben nach unten und nimmt den ersten Treffer. Deshalb stehen die Sperren vor dem Block, der PHP ausführt:

  • Sperren: versteckte Dateien wie .git, die internen Ordner von MediaWiki (z. B. includes, maintenance, vendor) und Dateien wie composer.json. Aus diesen Ordnern ruft der Browser nie etwas ab, sie enthalten nur Programmcode und Werkzeuge.
  • Upload-Ordner images: ^~ sorgt dafür, dass für Adressen unter /images/ keine der Regeln mit regulären Ausdrücken gilt, also auch nicht der PHP-Block. Der innere Block lehnt PHP-Dateien dort ausdrücklich ab. So lässt sich eine hochgeladene Datei nie als Programm starten.
  • PHP: index.php, load.php (liefert CSS und JavaScript) und die übrigen Einstiegsdateien von MediaWiki gehen an PHP-FPM.
  • Bilder, CSS, JavaScript: Der Browser darf sie 7 Tage zwischenspeichern. Gibt es eine solche Datei nicht, ist die Adresse eine Wiki-Seite, deren Name nur auf .png o. Ä. endet, z. B. die Dateiseite /Datei:Bild.png. Dann ist MediaWiki zuständig.
  • Kurze Adressen: /Hauptseite gibt es nicht als Datei. try_files übergibt solche Anfragen an index.php, hängt aber nichts an. nginx reicht die ursprüngliche Adresse als REQUEST_URI an PHP weiter. MediaWiki vergleicht sie mit $wgArticlePath = "/$1" aus der Anleitung MediaWiki und erkennt so, dass die Seite Hauptseite gemeint ist. Auch Seitennamen mit Sonderzeichen wie & kommen so unverändert an.
sudo nano /etc/nginx/snippets/mediawiki.conf

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Versteckte Dateien und Ordner sperren, außer .well-known (für HTTPS-Zertifikate)
location ~ /\.(?!well-known/) {
    return 403;
}

# Interne Ordner und Dateien von MediaWiki sperren
location ~ ^/(cache|includes|languages|maintenance|serialized|tests|vendor)/ {
    return 403;
}

location ~ \.(lock|json|yml|yaml|md)$ {
    return 403;
}

# Upload-Ordner: Dateien ausliefern, aber nie als PHP ausführen
location ^~ /images/ {
    location ~ \.php$ {
        return 403;
    }
}

# PHP über PHP-FPM ausführen
location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php-fpm.sock;
}

# Statische Dateien eine Woche im Browser zwischenspeichern.
# Gibt es die Datei nicht, ist es eine Wiki-Seite wie /Datei:Bild.png
location ~* \.(js|css|png|jpe?g|gif|ico|svg|webp|woff2?)$ {
    try_files $uri /index.php?$args;
    expires 7d;
    access_log off;
}

# Kurze Adressen: Was es nicht als Datei gibt, bekommt index.php.
# MediaWiki liest den Seitennamen selbst aus der ursprünglichen Adresse.
location / {
    try_files $uri $uri/ /index.php?$args;
}

3. Konfiguration für start.de anlegen

Die Datei enthält zwei server-Blöcke:

  • Der erste beantwortet nur Anfragen an www.start.de und leitet sie dauerhaft (Status 301) auf start.de um. $scheme behält http oder https bei, $request_uri den Pfad.
  • Der zweite ist das Wiki. root zeigt auf den MediaWiki-Ordner. client_max_body_size erlaubt hochgeladene Dateien bis 20 MB, ohne diese Zeile lehnt nginx alles über 1 MB ab. Eigene Logdateien halten die Einträge des Wikis getrennt.
sudo nano /etc/nginx/sites-available/start.de

Steht aus einer anderen Anleitung schon Inhalt in der Datei, lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 80;
    listen [::]:80;
    server_name www.start.de;

    return 301 $scheme://start.de$request_uri;
}

server {
    listen 80;
    listen [::]:80;
    server_name start.de;

    root /var/www/mediawiki;
    index index.php;

    client_max_body_size 20m;

    access_log /var/log/nginx/start.de.access.log;
    error_log  /var/log/nginx/start.de.error.log;

    include snippets/mediawiki.conf;
}

Achtung: Gibt es /etc/nginx/sites-available/start.de schon, z. B. aus der Anleitung Statische Website mit nginx oder Drupal mit nginx unter eigener Domain, ersetzt du damit ihren Inhalt und die bisherige Website ist unter start.de nicht mehr erreichbar. Eine Domain kann immer nur zu einer Website gehören.

4. Website einschalten

nginx lädt nur Konfigurationen aus sites-enabled. Der Link schaltet die Website ein. Meldet der Befehl File exists, ist die Website schon eingeschaltet.

sudo ln -s /etc/nginx/sites-available/start.de /etc/nginx/sites-enabled/start.de

5. Konfiguration testen

Findet Tippfehler in beiden neuen Dateien, bevor nginx neu geladen wird.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

6. nginx neu laden

Übernimmt die neue Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

MediaWiki einstellen

7. Einstellungsdatei sichern

Die nächsten Schritte ändern LocalSettings.php. Die Kopie erlaubt, jederzeit zum alten Stand zurückzukehren. -p übernimmt Besitzer und Rechte, damit auch die Kopie das Datenbank-Passwort schützt.

sudo cp -p /var/www/mediawiki/LocalSettings.php /var/www/mediawiki/LocalSettings.php.vor-start.de

8. Adresse des Wikis ändern

MediaWiki baut vollständige Adressen aus $wgServer zusammen, z. B. für die Weiterleitung von / auf die Hauptseite, für Links in E-Mails und für die Angabe der „kanonischen“ Adresse an Suchmaschinen. Bei der Installation wurde dort http://localhost:8085 eingetragen, jetzt kommt http://start.de hinein.

Die Datei gehört nach der Anleitung MediaWiki deinem Benutzer, deshalb ist sudo nicht nötig. nano schreibt beim Speichern in die vorhandene Datei, Gruppe www-data und Rechte bleiben erhalten.

nano /var/www/mediawiki/LocalSettings.php

Suche mit Strg+W nach $wgServer und drücke Enter. Die Zeile lautet $wgServer = "http://localhost:8085";. Ändere die gefundene Zeile so, dass sie lautet:

$wgServer = "http://start.de";

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Ausgabe lautet $wgServer = "http://start.de";, und die Gruppe ist weiterhin www-data.

grep '^\$wgServer' /var/www/mediawiki/LocalSettings.php
ls -l /var/www/mediawiki/LocalSettings.php

Das Wiki ist danach auch weiterhin über http://localhost:8085 erreichbar. Die Weiterleitung von / und alle vollständigen Links führen aber jetzt zu start.de.

9. Prüfen, ob die Datei gültig ist

Ein Tippfehler in LocalSettings.php legt das ganze Wiki lahm. MediaWiki leert seinen Seitenzwischenspeicher von selbst, sobald sich die Datei ändert.

sudo php -l /var/www/mediawiki/LocalSettings.php

Prüfen: Die Ausgabe lautet No syntax errors detected in /var/www/mediawiki/LocalSettings.php.

Auf dem eigenen Rechner testen

10. start.de auf den eigenen Rechner umleiten

Ein Eintrag in /etc/hosts hat Vorrang vor dem DNS im Internet und schickt die Anfragen an den eigenen Rechner. So lässt sich das Wiki testen, bevor die Domain auf einen Server zeigt. Steht der Eintrag schon aus einer anderen Anleitung in der Datei, diesen Schritt überspringen.

sudo nano /etc/hosts

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile diesen Eintrag ein. Speichere mit Strg+O und Enter und beende nano mit Strg+X:

127.0.0.1 start.de www.start.de

Prüfen: Als Adresse erscheint 127.0.0.1.

getent hosts start.de

11. Adresse des Wikis prüfen

Die Spezialseite „Zufällige Seite“ antwortet immer mit einer Weiterleitung auf eine vollständige Adresse. Daran lässt sich ablesen, ob MediaWiki die neue Adresse aus Schritt 8 verwendet. %C3%A4 ist die Schreibweise für ä in einer Adresse.

curl -sI http://start.de/Spezial:Zuf%C3%A4llige_Seite | grep -E '^HTTP|^Location'

Prüfen: Die erste Zeile enthält 302, und Location beginnt mit http://start.de/, z. B. Location: http://start.de/Hauptseite. Steht dort noch localhost:8085, hat Schritt 8 nicht gegriffen.

12. Hauptseite abrufen

Die kurze Adresse gibt es nicht als Datei. nginx muss sie an MediaWiki weiterreichen.

curl -sI http://start.de/Hauptseite | head -n 1

Prüfen: Die Ausgabe lautet HTTP/1.1 200 OK. Im Browser zeigt http://start.de die Hauptseite im Vector-Design. Oben rechts kannst du dich mit WikiAdmin anmelden.

13. Umleitung von www prüfen

curl -sI http://www.start.de/Hauptseite | grep -E '^HTTP|^Location'

Prüfen: Die Ausgabe lautet HTTP/1.1 301 Moved Permanently und Location: http://start.de/Hauptseite.

14. Sperren prüfen

Stichprobe für zwei gesperrte Bereiche: den Git-Ordner, der sonst die Versionsgeschichte preisgeben würde, und composer.json.

curl -sI http://start.de/.git/config | head -n 1
curl -sI http://start.de/composer.json | head -n 1

Prüfen: Beide Male lautet die Ausgabe HTTP/1.1 403 Forbidden.

15. Logdatei ansehen

Hier steht jede Anfrage an start.de mit Zeit, Adresse und Statuscode.

sudo tail -n 5 /var/log/nginx/start.de.access.log

Optional: Im Internet veröffentlichen

Diese Schritte gehen nur auf einem Server, der aus dem Internet erreichbar ist, und nur mit einer Domain, die dir gehört.

1. Testeintrag entfernen

Sonst zeigt start.de auf diesem Rechner weiter auf 127.0.0.1.

sudo nano /etc/hosts

Suche mit Strg+W nach start.de und drücke Enter. Lösche die Zeile 127.0.0.1 start.de www.start.de mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

2. Domain auf den Server zeigen lassen

In der Weboberfläche des Domain-Anbieters für start.de und www.start.de je einen A-Eintrag mit der öffentlichen IPv4-Adresse des Servers anlegen, bei IPv6 zusätzlich einen AAAA-Eintrag.

Prüfen: Nach einigen Minuten bis Stunden erscheint die Adresse des Servers.

getent hosts start.de

3. Firewall öffnen

Nur nötig, wenn ufw eingeschaltet ist. Das Profil Nginx Full öffnet Port 80 und 443.

sudo ufw allow 'Nginx Full'

4. Certbot installieren

Certbot besorgt kostenlose Zertifikate von Let's Encrypt und trägt sie direkt in die nginx-Konfiguration ein.

sudo apt install certbot python3-certbot-nginx

5. HTTPS einschalten

Certbot fragt beim ersten Aufruf nach einer E-Mail-Adresse und den Nutzungsbedingungen. Danach ergänzt es beide server-Blöcke um HTTPS und leitet HTTP auf HTTPS um.

sudo certbot --nginx -d start.de -d www.start.de

6. MediaWiki auf HTTPS umstellen

Anders als nginx weiß MediaWiki nichts vom neuen Zertifikat. Ohne diesen Schritt würden Weiterleitungen und vollständige Links weiter auf http:// zeigen.

nano /var/www/mediawiki/LocalSettings.php

Suche mit Strg+W nach $wgServer und drücke Enter. Ändere die gefundene Zeile so, dass sie lautet:

$wgServer = "https://start.de";

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Weiterleitung beginnt jetzt mit https://start.de/.

curl -sI https://start.de/Spezial:Zuf%C3%A4llige_Seite | grep -i '^location'

Das Zertifikat gilt 90 Tage und wird automatisch verlängert. Einen Probelauf der Verlängerung startet dieser Befehl:

sudo certbot renew --dry-run

Prüfen der Installation

nginx -v
sudo nginx -T 2>/dev/null | grep 'include snippets/mediawiki.conf'
grep '^\$wgServer' /var/www/mediawiki/LocalSettings.php

Prüfen: Der erste Befehl zeigt die Version von nginx, der zweite die include-Zeile aus Schritt 3, der dritte die Adresse start.de.

Deinstallieren

MediaWiki selbst bleibt erhalten und ist danach wieder wie vorher unter http://localhost:8085 erreichbar. Wie man MediaWiki ganz entfernt, steht in der Anleitung MediaWiki.

1. Website ausschalten

Löscht den Link in sites-enabled.

sudo rm /etc/nginx/sites-enabled/start.de

2. Konfiguration und Baustein löschen

sudo rm /etc/nginx/sites-available/start.de /etc/nginx/snippets/mediawiki.conf

3. nginx testen und neu laden

sudo nginx -t && sudo systemctl reload nginx

4. Alte Einstellungsdatei zurückholen

Ersetzt LocalSettings.php durch die Sicherung aus Schritt 7. Damit steht dort wieder http://localhost:8085. Hast du seit Schritt 7 weitere Einstellungen geändert, trage sie danach erneut ein. Alternativ änderst du nur die Zeile mit $wgServer von Hand zurück.

sudo mv /var/www/mediawiki/LocalSettings.php.vor-start.de /var/www/mediawiki/LocalSettings.php

Prüfen: Die Ausgabe lautet $wgServer = "http://localhost:8085";.

grep '^\$wgServer' /var/www/mediawiki/LocalSettings.php

5. Logdateien löschen

sudo rm /var/log/nginx/start.de.*

6. Testeintrag aus /etc/hosts entfernen

Nur nötig, wenn der Eintrag aus Schritt 10 noch besteht und keine andere Anleitung ihn braucht.

sudo nano /etc/hosts

Suche mit Strg+W nach start.de und drücke Enter. Lösche die Zeile 127.0.0.1 start.de www.start.de mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Es erscheint nicht mehr 127.0.0.1.

getent hosts start.de

7. Zertifikat löschen

Nur nötig, wenn im optionalen Teil ein Zertifikat geholt wurde.

sudo certbot delete --cert-name start.de

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

WordPress mit nginx unter eigener Domain

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

WordPress ist das meistgenutzte Programm für Websites und Blogs. Beiträge, Seiten, Bilder, Designs und Erweiterungen verwaltet man bequem im Browser. Diese Anleitung installiert WordPress mit nginx, PHP-FPM und MariaDB und macht es unter einer eigenen Domain erreichbar, hier am Beispiel start.de.

Vorbemerkungen

  • Voraussetzung: nginx und PHP mit PHP-FPM sind nach den jeweiligen Anleitungen installiert und laufen.
  • Warum nicht das apt-Paket? Ubuntu 26.04 enthält zwar ein Paket wordpress, aber nur in Version 6.7 aus dem Bereich „universe“, für den Ubuntu keine Sicherheitsupdates zusagt. Aktuell ist WordPress 7.1. Weil eine Website aus dem Internet erreichbar ist, installiert diese Anleitung das offizielle deutsche Paket von wordpress.org. WordPress hält sich danach selbst mit Sicherheitsupdates aktuell.
  • Datenbank: WordPress braucht MySQL oder MariaDB. PostgreSQL wird nicht unterstützt. MariaDB kommt aus den Ubuntu-Paketquellen.
  • Version: Die Befehle verwenden WordPress 7.1.2. Ist eine neuere Version erschienen, ersetzt du die Versionsnummer in den Schritten 8 und 9. Die aktuelle Version steht auf https://de.wordpress.org/download/.
  • Passwörter: geheimes_passwort ist ein Beispiel. Ersetze es durch ein eigenes Passwort.

Zum Beispiel start.de: Die Domain ist nur ein Beispiel. Ersetze start.de in allen Befehlen durch deine eigene Domain. Zum Ausprobieren auf dem eigenen Rechner leitet Schritt 19 start.de auf den eigenen Rechner um. Die echte Website unter diesem Namen ist dann auf diesem Rechner nicht mehr erreichbar, bis der Eintrag wieder entfernt ist.

Pakete installieren

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von MariaDB und den PHP-Modulen kennt.

sudo apt update

2. MariaDB installieren

Installiert den Datenbankserver. Der Dienst startet automatisch.

sudo apt install mariadb-server

Prüfen: Die Ausgabe lautet active.

systemctl is-active mariadb

3. PHP-Module für WordPress installieren

  • php-mysql – Verbindung zu MariaDB
  • php-gd und php-imagick – verkleinern hochgeladene Bilder und erzeugen Vorschaubilder
  • php-curl – Anfragen an andere Server, z. B. für Updates
  • php-intl, php-mbstring – Umgang mit Sprachen und Sonderzeichen
  • php-xml, php-zip – lesen XML-Daten und entpacken Updates, Designs und Erweiterungen
sudo apt install php-mysql php-gd php-imagick php-curl php-intl php-mbstring php-xml php-zip

4. Größere Uploads erlauben

PHP nimmt ohne weitere Einstellung nur Dateien bis 2 MB an. Für Fotos ist das zu wenig. Die Datei im Ordner conf.d hebt die Grenze für PHP-FPM auf 64 MB an. post_max_size muss mindestens so groß sein, weil die Datei im Formular mitgeschickt wird.

sudo nano /etc/php/8.5/fpm/conf.d/99-wordpress.ini

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

upload_max_filesize = 64M
post_max_size = 64M

5. PHP-FPM neu starten

PHP-FPM lädt neue Module und Einstellungen erst nach einem Neustart.

sudo systemctl restart php8.5-fpm

Prüfen: Die Liste enthält mysqli und imagick.

php -m | grep -E 'mysqli|imagick'

Datenbank anlegen

6. Datenbank erstellen

Legt die leere Datenbank wordpress an. utf8mb4 speichert alle Zeichen, auch Emojis. Unter Ubuntu meldet sich sudo mariadb ohne Passwort als Datenbank-Administrator an, weil MariaDB den Ubuntu-Benutzer root erkennt.

sudo mariadb -e "CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

7. Datenbankbenutzer anlegen

WordPress bekommt einen eigenen Benutzer, der nur auf diese eine Datenbank zugreifen darf. So kann eine Lücke in WordPress keine anderen Datenbanken gefährden.

sudo mariadb -e "CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'geheimes_passwort'; GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';"

Prüfen: Die Anmeldung mit dem neuen Benutzer klappt, und die Liste enthält wordpress.

mariadb -u wpuser -p'geheimes_passwort' -e "SHOW DATABASES;"

WordPress herunterladen

8. In den Download-Ordner wechseln

Das Paket wird hier abgelegt und nach dem Entpacken gelöscht.

cd ~/Downloads

9. Paket und Prüfsumme herunterladen

Lädt die deutsche Ausgabe von WordPress (etwa 43 MB) und die zugehörige SHA-1-Prüfsumme.

wget https://de.wordpress.org/wordpress-7.1.2-de_DE.tar.gz https://de.wordpress.org/wordpress-7.1.2-de_DE.tar.gz.sha1

10. Paket prüfen

Die .sha1-Datei enthält nur die Prüfsumme. sha1sum -c erwartet dahinter noch den Dateinamen, den echo ergänzt. So erkennst du, ob die Datei vollständig und unverändert angekommen ist.

echo "$(cat wordpress-7.1.2-de_DE.tar.gz.sha1)  wordpress-7.1.2-de_DE.tar.gz" | sha1sum -c

Prüfen: Die Ausgabe lautet wordpress-7.1.2-de_DE.tar.gz: OK. Bei FEHLSCHLAG die Datei löschen und neu herunterladen.

11. Entpacken

Das Archiv enthält einen Ordner wordpress, der direkt nach /var/www entpackt wird.

sudo tar -xzf wordpress-7.1.2-de_DE.tar.gz -C /var/www

Prüfen: Im Ordner liegen unter anderem wp-config-sample.php und wp-admin.

ls /var/www/wordpress

12. Heruntergeladene Dateien löschen

rm wordpress-7.1.2-de_DE.tar.gz wordpress-7.1.2-de_DE.tar.gz.sha1

13. Dateien dem Webserver übergeben

WordPress lädt Bilder hoch, installiert Designs und Erweiterungen und spielt Updates selbst ein. Dafür muss PHP-FPM, das als Benutzer www-data läuft, in den Ordner schreiben dürfen. Der Nachteil: Eine Lücke in einer Erweiterung könnte ebenfalls Dateien verändern. Halte WordPress und alle Erweiterungen deshalb immer aktuell.

sudo chown -R www-data:www-data /var/www/wordpress

nginx einrichten

14. WordPress-Regeln als Baustein anlegen

Die Regeln kommen in eine eigene Datei unter snippets, die der server-Block in Schritt 15 mit include einbindet. nginx prüft Blöcke mit regulären Ausdrücken (~) von oben nach unten und nimmt den ersten Treffer. Deshalb stehen die Sperren vor dem Block, der PHP ausführt:

  • Sperren: versteckte Dateien (z. B. .htaccess), PHP-Dateien im Upload-Ordner wp-content/uploads und xmlrpc.php. Diese alte Schnittstelle nutzen Angreifer gern, um Passwörter durchzuprobieren. Brauchst du sie, etwa für die WordPress-App auf dem Handy, lösche diesen Block.
  • PHP: Alle übrigen .php-Dateien gehen an PHP-FPM.
  • Bilder, CSS, JavaScript: Der Browser darf sie 30 Tage zwischenspeichern.
  • Alles andere: Schöne Adressen wie /hallo-welt/ gibt es nicht als Datei. try_files reicht sie an index.php weiter. WordPress liest die gewünschte Seite aus der ursprünglichen Adresse.
sudo nano /etc/nginx/snippets/wordpress.conf

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Versteckte Dateien sperren, außer .well-known (für HTTPS-Zertifikate)
location ~ /\.(?!well-known/) {
    return 403;
}

# Hochgeladene Dateien nie als PHP ausführen
location ~* ^/wp-content/uploads/.*\.php$ {
    return 403;
}

# Alte Schnittstelle, beliebtes Angriffsziel
location = /xmlrpc.php {
    return 403;
}

# PHP über PHP-FPM ausführen
location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php-fpm.sock;
}

# Statische Dateien 30 Tage im Browser zwischenspeichern
location ~* \.(css|js|png|jpe?g|gif|ico|svg|webp|avif|woff2?)$ {
    expires 30d;
    access_log off;
}

# Schöne Adressen an WordPress weiterreichen
location / {
    try_files $uri $uri/ /index.php?$args;
}

15. Konfiguration für start.de anlegen

  • Der erste Block leitet www.start.de dauerhaft (Status 301) auf start.de um. $scheme behält http oder https bei.
  • Der zweite Block ist die Website. client_max_body_size 64m passt zur PHP-Grenze aus Schritt 4. Ohne diese Zeile lehnt nginx Uploads über 1 MB ab, bevor PHP sie überhaupt sieht.
sudo nano /etc/nginx/sites-available/start.de

Steht aus einer anderen Anleitung schon Inhalt in der Datei, lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 80;
    listen [::]:80;
    server_name www.start.de;

    return 301 $scheme://start.de$request_uri;
}

server {
    listen 80;
    listen [::]:80;
    server_name start.de;

    root /var/www/wordpress;
    index index.php;

    client_max_body_size 64m;

    access_log /var/log/nginx/start.de.access.log;
    error_log  /var/log/nginx/start.de.error.log;

    include snippets/wordpress.conf;
}

Achtung: Gibt es /etc/nginx/sites-available/start.de schon aus einer anderen Anleitung dieses Buchs, ersetzt du damit ihren Inhalt und die bisherige Website ist unter start.de nicht mehr erreichbar. Eine Domain kann immer nur zu einer Website gehören.

16. Website einschalten

Der Link in sites-enabled schaltet die Website ein. Meldet der Befehl Die Datei existiert bereits, ist sie schon eingeschaltet.

sudo ln -s /etc/nginx/sites-available/start.de /etc/nginx/sites-enabled/start.de

17. Konfiguration testen

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

18. nginx neu laden

sudo systemctl reload nginx

WordPress einrichten

19. start.de auf den eigenen Rechner umleiten

Ein Eintrag in /etc/hosts hat Vorrang vor dem DNS im Internet. So lässt sich WordPress einrichten und testen, bevor die Domain auf einen Server zeigt. Steht der Eintrag schon aus einer anderen Anleitung in der Datei, diesen Schritt überspringen.

sudo nano /etc/hosts

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile diesen Eintrag ein. Speichere mit Strg+O und Enter und beende nano mit Strg+X:

127.0.0.1 start.de www.start.de

Prüfen: Als Adresse erscheint 127.0.0.1.

getent hosts start.de

20. Einrichtungsassistenten öffnen

WordPress merkt sich die Adresse, unter der es eingerichtet wird, als Adresse der Website. Rufe den Assistenten deshalb unbedingt über start.de auf und nicht über localhost.

xdg-open http://start.de

Prüfen: Es erscheint die Seite „Willkommen bei WordPress“ mit der Liste der benötigten Angaben.

21. Datenbank-Zugang eintragen

Klicke auf Los geht's! und trage ein:

FeldEingabe
Datenbank-Namewordpress
Benutzernamewpuser
Passwortdas Passwort aus Schritt 7
Datenbank-Hostlocalhost
Tabellen-Präfixwp_ (unverändert lassen)

Klicke auf Senden und dann auf Installation durchführen. WordPress schreibt dabei die Einstellungsdatei wp-config.php mit dem Datenbank-Zugang und zufälligen Sicherheitsschlüsseln.

22. Website und Administrator anlegen

Gib einen Titel der Website, einen Benutzernamen, ein starkes Passwort und deine E-Mail-Adresse ein. Nimm als Benutzernamen nicht admin, weil Angreifer diesen Namen zuerst ausprobieren. Klicke auf WordPress installieren.

Prüfen: Es erscheint „Installation erfolgreich“. Mit Anmelden gelangst du unter http://start.de/wp-admin/ in die Verwaltung.

23. Einstellungsdatei schützen

wp-config.php enthält das Datenbank-Passwort. Mit 640 darf nur www-data sie lesen und schreiben, alle anderen Benutzer des Rechners haben keinen Zugriff.

sudo chmod 640 /var/www/wordpress/wp-config.php

Prüfen: Die Rechte lauten -rw-r-----, Besitzer ist www-data.

ls -l /var/www/wordpress/wp-config.php

24. Schöne Adressen einschalten

Öffne in der Verwaltung Einstellungen → Permalinks, wähle Beitragsname und klicke auf Änderungen speichern. Beiträge heißen danach z. B. /hallo-welt/ statt /?p=1. Anders als bei Apache ist dafür keine Datei .htaccess nötig, das erledigt der location /-Block aus Schritt 14.

Testen

25. Startseite abrufen

curl -sI http://start.de/ | head -n 1

Prüfen: Die Ausgabe lautet HTTP/1.1 200 OK. Im Browser zeigt http://start.de die Website mit dem Beispielbeitrag „Hallo Welt!“.

26. Schöne Adresse abrufen

Der Beispielbeitrag ist nach Schritt 24 unter /hallo-welt/ erreichbar. Die Adresse gibt es nicht als Datei, nginx muss sie an WordPress weiterreichen.

curl -sI http://start.de/hallo-welt/ | head -n 1

Prüfen: Die Ausgabe lautet HTTP/1.1 200 OK.

27. Umleitung von www prüfen

curl -sI http://www.start.de/hallo-welt/ | grep -E '^HTTP|^Location'

Prüfen: Die Ausgabe lautet HTTP/1.1 301 Moved Permanently und Location: http://start.de/hallo-welt/.

28. Sperren prüfen

curl -sI http://start.de/xmlrpc.php | head -n 1

Prüfen: Die Ausgabe lautet HTTP/1.1 403 Forbidden.

29. Website-Zustand in WordPress prüfen

Öffne in der Verwaltung Werkzeuge → Website-Zustand. WordPress prüft dort unter anderem PHP-Module, Upload-Grenze und Verbindungen.

Prüfen: Unter Info → Medienverarbeitung steht bei der maximalen Upload-Dateigröße 64 MB. Hinweise zu HTTPS verschwinden erst mit dem optionalen Teil unten.

Optional: Im Internet veröffentlichen

Diese Schritte gehen nur auf einem Server, der aus dem Internet erreichbar ist, und nur mit einer Domain, die dir gehört.

1. Testeintrag entfernen

sudo nano /etc/hosts

Suche mit Strg+W nach start.de und drücke Enter. Lösche die Zeile 127.0.0.1 start.de www.start.de mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

2. Domain auf den Server zeigen lassen

In der Weboberfläche des Domain-Anbieters für start.de und www.start.de je einen A-Eintrag mit der öffentlichen IPv4-Adresse des Servers anlegen, bei IPv6 zusätzlich einen AAAA-Eintrag.

Prüfen: Nach einigen Minuten bis Stunden erscheint die Adresse des Servers.

getent hosts start.de

3. Firewall öffnen

Nur nötig, wenn ufw eingeschaltet ist. Das Profil Nginx Full öffnet Port 80 und 443.

sudo ufw allow 'Nginx Full'

4. Certbot installieren

sudo apt install certbot python3-certbot-nginx

5. HTTPS einschalten

Certbot fragt nach einer E-Mail-Adresse und den Nutzungsbedingungen, holt ein Zertifikat von Let's Encrypt und ergänzt beide server-Blöcke um HTTPS.

sudo certbot --nginx -d start.de -d www.start.de

6. WordPress auf HTTPS umstellen

WordPress speichert seine Adresse in der Datenbank und erzeugt sonst weiter Links mit http://. Öffne Einstellungen → Allgemein und ändere bei WordPress-Adresse (URL) und Website-Adresse (URL) jeweils http:// in https://. Nach dem Speichern meldet WordPress dich ab. Melde dich unter https://start.de/wp-admin/ neu an.

Prüfen: Die erste Zeile lautet HTTP/2 200 oder HTTP/1.1 200 OK.

curl -sI https://start.de/ | head -n 1

Das Zertifikat gilt 90 Tage und wird automatisch verlängert. Einen Probelauf startet dieser Befehl:

sudo certbot renew --dry-run

Aktualisieren

WordPress spielt Sicherheitsupdates von selbst ein. Größere Updates, Designs und Erweiterungen aktualisierst du in der Verwaltung unter Dashboard → Aktualisierungen. MariaDB, PHP und nginx kommen aus apt und werden mit sudo apt upgrade aktualisiert.

Prüfen der Installation

grep "wp_version =" /var/www/wordpress/wp-includes/version.php
sudo nginx -T 2>/dev/null | grep 'include snippets/wordpress.conf'

Prüfen: Der erste Befehl zeigt die Version von WordPress, z. B. $wp_version = '7.1.2';, der zweite die include-Zeile aus Schritt 15.

Deinstallieren

1. Website ausschalten

sudo rm /etc/nginx/sites-enabled/start.de

2. nginx-Konfiguration löschen

sudo rm /etc/nginx/sites-available/start.de /etc/nginx/snippets/wordpress.conf

3. nginx testen und neu laden

sudo nginx -t && sudo systemctl reload nginx

4. WordPress-Dateien löschen

Achtung: Löscht auch alle hochgeladenen Bilder und Dateien in wp-content/uploads. Vorher bei Bedarf sichern.

sudo rm -rf /var/www/wordpress

5. Datenbank und Benutzer löschen

Achtung: Alle Beiträge, Seiten, Kommentare und Einstellungen gehen verloren.

sudo mariadb -e "DROP DATABASE wordpress; DROP USER 'wpuser'@'localhost';"

6. PHP-Einstellung entfernen und PHP-FPM neu starten

sudo rm /etc/php/8.5/fpm/conf.d/99-wordpress.ini
sudo systemctl restart php8.5-fpm

7. Logdateien löschen

sudo rm /var/log/nginx/start.de.*

8. Testeintrag aus /etc/hosts entfernen

Nur nötig, wenn der Eintrag aus Schritt 19 noch besteht und keine andere Anleitung ihn braucht.

sudo nano /etc/hosts

Suche mit Strg+W nach start.de und drücke Enter. Lösche die Zeile 127.0.0.1 start.de www.start.de mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

9. Zertifikat löschen

Nur nötig, wenn im optionalen Teil ein Zertifikat geholt wurde.

sudo certbot delete --cert-name start.de

10. Optional: MariaDB und PHP-Module entfernen

Nur ausführen, wenn kein anderes Programm MariaDB oder diese PHP-Module braucht. Achtung: purge bei mariadb-server fragt, ob alle Datenbanken gelöscht werden sollen.

sudo apt purge mariadb-server php-mysql php-imagick
sudo apt autoremove

Prüfen: Unter http://start.de antwortet kein WordPress mehr, und die Datenbank ist entfernt, falls MariaDB noch installiert ist:

sudo mariadb -e "SHOW DATABASES;" | grep -c wordpress

Die Ausgabe 0 bedeutet: Die Datenbank ist entfernt.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Wildcard-Zertifikat mit Certbot für nginx

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Ein Wildcard-Zertifikat gilt für alle Subdomains einer Domain auf einmal, z. B. für www.start.de, blog.start.de und wiki.start.de. Neue Subdomains bekommen damit sofort HTTPS, ohne dass für jede ein eigenes Zertifikat nötig ist. Diese Anleitung holt ein kostenloses Wildcard-Zertifikat von Let's Encrypt mit Certbot und bindet es in nginx ein, am Beispiel start.de.

Vorbemerkungen

  • Voraussetzung: Ein Server, der aus dem Internet erreichbar ist, mit nginx und der Website aus der Anleitung Statische Website mit nginx. Die Domain start.de gehört dir und zeigt per A-Eintrag auf den Server (dort Abschnitt „Im Internet veröffentlichen“, Schritte 1 bis 3).
  • Was *.start.de abdeckt: Der Stern steht für genau eine Ebene. blog.start.de ist abgedeckt, test.blog.start.de nicht. Die Domain start.de selbst ist ebenfalls nicht enthalten. Deshalb beantragt diese Anleitung ein Zertifikat für beide Namen, start.de und *.start.de.
  • Nachweis über DNS: Bei normalen Zertifikaten legt Certbot eine Datei auf den Webserver, die Let's Encrypt abruft. Für Wildcard-Zertifikate verlangt Let's Encrypt einen anderen Nachweis: einen TXT-Eintrag im DNS der Domain. Damit zeigst du, dass du die ganze Domain verwaltest und nicht nur einen Webserver.
  • Manueller Weg: Diese Anleitung setzt den TXT-Eintrag von Hand in der Weboberfläche deines Domain-Anbieters. Das funktioniert bei jedem Anbieter. Der Nachteil: Das Zertifikat gilt derzeit 90 Tage, und auch die Verlängerung ist Handarbeit (Abschnitt „Verlängern“). Let's Encrypt verschickt keine Erinnerungs-E-Mails mehr. Trage dir den Termin deshalb selbst in den Kalender ein.
  • Automatisch geht es nur mit Plugin: Für einige Anbieter gibt es Certbot-Plugins in apt, die den TXT-Eintrag selbst setzen und die Verlängerung automatisch erledigen, z. B. python3-certbot-dns-netcup, python3-certbot-dns-cloudflare oder python3-certbot-dns-ovh. Die ganze Liste zeigt apt search certbot-dns.

Zertifikat beantragen

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Certbot und den DNS-Werkzeugen kennt.

sudo apt update

2. Certbot und DNS-Werkzeuge installieren

certbot beantragt das Zertifikat. bind9-dnsutils enthält den Befehl dig, mit dem du prüfst, ob der TXT-Eintrag schon im Internet sichtbar ist.

sudo apt install certbot bind9-dnsutils

Prüfen: Die Ausgabe nennt die Version, z. B. certbot 4.0.0.

certbot --version

3. Zertifikat anfordern

  • certonly holt nur das Zertifikat und ändert nichts an nginx. Die Konfiguration schreibst du danach selbst.
  • --manual mit --preferred-challenges dns wählt den Nachweis über einen TXT-Eintrag, den du von Hand setzt.
  • --cert-name start.de legt den Namen fest, unter dem Certbot das Zertifikat ablegt: /etc/letsencrypt/live/start.de/.
  • Die beiden -d nennen die Namen im Zertifikat. '*.start.de' steht in einfachen Anführungszeichen, damit die Shell den Stern nicht als Platzhalter für Dateinamen auswertet.
sudo certbot certonly --manual --preferred-challenges dns --cert-name start.de -d start.de -d '*.start.de'

Beim allerersten Aufruf fragt Certbot nach einer E-Mail-Adresse für wichtige Hinweise und nach den Nutzungsbedingungen von Let's Encrypt (mit Y zustimmen). Die Frage nach Werbe-E-Mails kannst du mit N beantworten.

4. Ersten TXT-Eintrag anlegen

Certbot zeigt jetzt einen Namen und einen Wert, etwa so:

Please deploy a DNS TXT record under the name:

_acme-challenge.start.de.

with the following value:

<zufälliger Wert aus etwa 43 Zeichen>

Noch nicht Enter drücken. Öffne in der Weboberfläche deines Domain-Anbieters die DNS-Einstellungen von start.de und lege einen neuen Eintrag an:

FeldEingabe
TypTXT
Name / Host_acme-challenge (manche Anbieter wollen den vollen Namen _acme-challenge.start.de)
Wert / Inhaltder Wert aus dem Terminal, genau abgeschrieben, am besten kopiert
TTLder kleinste angebotene Wert, z. B. 300 Sekunden

Speichere den Eintrag und drücke dann im Terminal Enter.

5. Zweiten TXT-Eintrag anlegen

Weil das Zertifikat zwei Namen enthält, zeigt Certbot einen zweiten Wert unter demselben Namen _acme-challenge.start.de. Lege dafür einen weiteren TXT-Eintrag an, mit gleichem Namen und dem neuen Wert. Den ersten Eintrag nicht ändern oder löschen, beide müssen gleichzeitig bestehen.

Drücke noch nicht Enter, sondern prüfe zuerst im nächsten Schritt, ob beide Einträge sichtbar sind.

6. TXT-Einträge prüfen

Öffne ein zweites Terminal. dig fragt hier gezielt einen öffentlichen DNS-Server (1.1.1.1) nach den TXT-Einträgen. So siehst du, was auch Let's Encrypt sehen wird.

dig +short TXT _acme-challenge.start.de @1.1.1.1

Prüfen: Die Ausgabe enthält beide Werte in Anführungszeichen. Erscheint nichts oder nur ein Wert, warte eine bis fünf Minuten und frage erneut. Manche Anbieter brauchen länger, bis Änderungen im Internet sichtbar sind.

7. Nachweis abschließen

Wechsle zurück ins erste Terminal und drücke Enter. Let's Encrypt prüft jetzt beide Einträge und stellt das Zertifikat aus.

Prüfen: Die Ausgabe enthält Successfully received certificate. und die Pfade /etc/letsencrypt/live/start.de/fullchain.pem und privkey.pem. Meldet Certbot Incorrect TXT record oder No TXT record found, war ein Eintrag noch nicht sichtbar oder falsch abgeschrieben. Dann Schritt 3 wiederholen. Certbot zeigt dabei neue Werte, die alten TXT-Einträge ersetzt du durch die neuen.

8. Zertifikat anzeigen

sudo certbot certificates

Prüfen: Beim Eintrag Certificate Name: start.de stehen Domains: start.de *.start.de und bei Expiry Date ein Datum in knapp 90 Tagen. Trage dir einen Termin etwa 30 Tage vorher für die Verlängerung ein.

9. TXT-Einträge entfernen

Die beiden TXT-Einträge werden nicht mehr gebraucht. Lösche sie in der Weboberfläche des Anbieters. Bei der Verlängerung verlangt Certbot ohnehin neue Werte.

nginx einrichten

10. Bisherige Konfiguration sichern

Die folgenden Schritte ersetzen die Konfiguration von start.de. Die Kopie liegt außerhalb von sites-enabled, damit nginx sie nicht als zweite Website lädt.

sudo cp -p /etc/nginx/sites-available/start.de /root/start.de.vor-wildcard

11. Zertifikat als Baustein anlegen

Die beiden Zeilen, die auf das Zertifikat zeigen, kommen in eine eigene Datei. Jede Website unter start.de bindet sie mit einer include-Zeile ein. Das ist der eigentliche Vorteil des Wildcard-Zertifikats: Für eine neue Subdomain genügt diese eine Zeile.

  • fullchain.pem – das Zertifikat samt Zwischenzertifikat von Let's Encrypt, das Browser zur Prüfung brauchen
  • privkey.pem – der geheime Schlüssel. Er ist nur für root lesbar, nginx liest ihn beim Start mit Administratorrechten.
sudo nano /etc/nginx/snippets/ssl-start.de.conf

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Wildcard-Zertifikat für start.de und *.start.de
ssl_certificate     /etc/letsencrypt/live/start.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/start.de/privkey.pem;

12. Website auf HTTPS umstellen

Die Datei bekommt zwei server-Blöcke:

  • Der erste nimmt alle Anfragen auf Port 80 an, für start.de und jede Subdomain (*.start.de), und leitet sie dauerhaft auf HTTPS um. $host behält den aufgerufenen Namen bei, $request_uri den Pfad.
  • Der zweite ist die Website auf Port 443. ssl schaltet die Verschlüsselung ein, http2 on das schnellere Protokoll HTTP/2. nginx 1.28 erlaubt ab Werk nur die sicheren Verfahren TLS 1.2 und 1.3. Eigene Einstellungen dafür sind nicht nötig.
sudo nano /etc/nginx/sites-available/start.de

Die Datei hat schon Inhalt, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

# HTTP: alles auf HTTPS umleiten
server {
    listen 80;
    listen [::]:80;
    server_name start.de *.start.de;

    return 301 https://$host$request_uri;
}

# HTTPS: die Website start.de
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name start.de www.start.de;

    include snippets/ssl-start.de.conf;

    root /var/www/start.de/html;
    index index.html;

    access_log /var/log/nginx/start.de.access.log;
    error_log  /var/log/nginx/start.de.error.log;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;

    location ~* \.(css|js|png|jpe?g|gif|svg|webp|ico|woff2?)$ {
        expires 7d;
    }
}

Beispiel: eine weitere Subdomain

Als Beispiel bekommt test.start.de eine eigene kleine Website, die dasselbe Zertifikat nutzt.

13. DNS-Eintrag für die Subdomain anlegen

Lege beim Domain-Anbieter einen A-Eintrag mit dem Namen test und der IPv4-Adresse des Servers an (bei IPv6 zusätzlich AAAA). Alternativ ein A-Eintrag mit dem Namen *: Dann zeigt jede beliebige Subdomain auf den Server.

Prüfen: Nach einigen Minuten erscheint die Adresse des Servers.

dig +short test.start.de @1.1.1.1

14. Ordner für die Subdomain anlegen

Wie in der Anleitung Statische Website mit nginx gehört der Ordner deinem Benutzer, damit du ohne sudo Dateien ablegen kannst.

sudo mkdir -p /var/www/test.start.de/html
sudo chown -R "$USER":"$USER" /var/www/test.start.de

15. Startseite anlegen

nano /var/www/test.start.de/html/index.html

Füge diese Zeile ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

<h1>test.start.de mit Wildcard-Zertifikat</h1>

16. Konfiguration für die Subdomain anlegen

Nur ein HTTPS-Block ist nötig. Die Umleitung von HTTP erledigt schon der erste Block aus Schritt 12, weil er für *.start.de gilt. Das Zertifikat kommt über dieselbe include-Zeile.

sudo nano /etc/nginx/sites-available/test.start.de

Füge diesen Inhalt ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name test.start.de;

    include snippets/ssl-start.de.conf;

    root /var/www/test.start.de/html;
    index index.html;
}

17. Subdomain einschalten

sudo ln -s /etc/nginx/sites-available/test.start.de /etc/nginx/sites-enabled/test.start.de

18. Konfiguration testen und nginx neu laden

&& sorgt dafür, dass nginx nur neu geladen wird, wenn der Test erfolgreich war.

sudo nginx -t && sudo systemctl reload nginx

Prüfen: Die Ausgabe enthält test is successful. Meldet nginx cannot load certificate, stimmt der Pfad in Schritt 11 nicht mit dem aus Schritt 7 überein.

19. Firewall für HTTPS öffnen

Nur nötig, wenn ufw eingeschaltet ist. Das Profil Nginx Full öffnet Port 80 und 443.

sudo ufw allow 'Nginx Full'

Testen

20. Umleitung auf HTTPS prüfen

curl -sI http://start.de/ | grep -E '^HTTP|^Location'

Prüfen: Die Ausgabe lautet HTTP/1.1 301 Moved Permanently und Location: https://start.de/.

21. Beide Websites über HTTPS abrufen

curl prüft dabei das Zertifikat. Wäre es ungültig oder passte nicht zum Namen, bräche der Befehl mit einer Fehlermeldung ab.

curl -sI https://start.de/ | head -n 1
curl -s https://test.start.de/

Prüfen: Die erste Ausgabe lautet HTTP/2 200, die zweite <h1>test.start.de mit Wildcard-Zertifikat</h1>.

22. Namen im Zertifikat anzeigen

openssl s_client baut eine Verbindung auf wie ein Browser, openssl x509 zeigt die Namen, für die das gelieferte Zertifikat gilt.

openssl s_client -connect test.start.de:443 -servername test.start.de < /dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName

Prüfen: Die Ausgabe enthält DNS:*.start.de und DNS:start.de.

Verlängern

Das Zertifikat gilt derzeit 90 Tage. Certbot schlägt die Verlängerung ab 30 Tage vor Ablauf vor, früher ist sie auch möglich. sudo certbot renew funktioniert bei manuell beantragten Zertifikaten nicht, weil Certbot den TXT-Eintrag nicht selbst setzen kann. Der automatische Verlängerungsdienst von Certbot meldet deshalb im Log für dieses Zertifikat einen Fehler. Das ist bei diesem Weg normal.

1. Ablaufdatum prüfen

sudo certbot certificates

Prüfen: Bei Expiry Date steht, wie viele Tage das Zertifikat noch gilt (VALID: … days).

2. Zertifikat neu anfordern

Derselbe Befehl wie in Schritt 3. Certbot erkennt das vorhandene Zertifikat und fragt, ob es erneuert werden soll: Wähle Renew & replace the certificate. Danach folgen wieder zwei TXT-Einträge mit neuen Werten. Gehe dabei wie in den Schritten 4 bis 7 vor und lösche danach die Einträge (Schritt 9).

sudo certbot certonly --manual --preferred-challenges dns --cert-name start.de -d start.de -d '*.start.de'

3. nginx neu laden

nginx liest das neue Zertifikat erst beim Neuladen. Die Pfade bleiben gleich, die Konfiguration muss nicht geändert werden.

sudo systemctl reload nginx

Prüfen: Das neue Ablaufdatum liegt wieder knapp 90 Tage in der Zukunft.

echo | openssl s_client -connect start.de:443 -servername start.de 2>/dev/null | openssl x509 -noout -enddate

Prüfen der Installation

certbot --version
sudo nginx -T 2>/dev/null | grep 'include snippets/ssl-start.de.conf'

Prüfen: Der erste Befehl zeigt die Version von Certbot, der zweite zwei include-Zeilen, je eine pro Website.

Deinstallieren

1. Subdomain ausschalten und löschen

sudo rm /etc/nginx/sites-enabled/test.start.de /etc/nginx/sites-available/test.start.de

Achtung: Löscht auch die Dateien der Test-Website.

sudo rm -r /var/www/test.start.de

2. Alte Konfiguration von start.de zurückholen

Stellt die HTTP-Konfiguration aus Schritt 10 wieder her.

sudo cp -p /root/start.de.vor-wildcard /etc/nginx/sites-available/start.de

3. Zertifikats-Baustein löschen

sudo rm /etc/nginx/snippets/ssl-start.de.conf

4. nginx testen und neu laden

sudo nginx -t && sudo systemctl reload nginx

5. Zertifikat löschen

Entfernt Zertifikat, Schlüssel und Verlängerungseinstellungen unter /etc/letsencrypt. Certbot fragt zur Sicherheit nach.

sudo certbot delete --cert-name start.de

6. Sicherung löschen

sudo rm /root/start.de.vor-wildcard

7. DNS-Einträge aufräumen

Lösche beim Domain-Anbieter den A-Eintrag für test (oder *) aus Schritt 13 und eventuell noch vorhandene TXT-Einträge _acme-challenge.

8. Optional: Certbot entfernen

Nur ausführen, wenn keine andere Website ein Zertifikat von Certbot nutzt. bind9-dnsutils bleibt installiert, weil dig auch sonst nützlich ist.

sudo apt purge certbot
sudo apt autoremove

Prüfen: Es wird kein Zertifikat mehr angezeigt, bzw. der Befehl wird nicht mehr gefunden.

sudo certbot certificates

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

PostgreSQL

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

PostgreSQL ist eine freie Datenbank, die Daten in Tabellen ablegt und per SQL abfragen lässt. Auf dem Entwicklungsrechner dient es als robuste Datenbank für Webanwendungen und lokale Softwareprojekte. Mit der Erweiterung pgvector kann PostgreSQL außerdem Vektoren speichern und nach Ähnlichkeit durchsuchen, etwa für KI-Anwendungen mit Embeddings.

Vorbemerkungen

  • Installation über apt: Ubuntu 26.04 liefert PostgreSQL 18 und die Erweiterung pgvector direkt in den eigenen Paketquellen. Für die meisten Fälle reicht das.
  • Offizielles PostgreSQL-Archiv (optional): Das PostgreSQL-Projekt betreibt ein eigenes apt-Archiv (PGDG). Es liefert Fehlerbehebungen oft früher als Ubuntu und bietet auch ältere Hauptversionen wie 16 oder 17 an. Wer das braucht, bindet es vor der Installation ein, siehe den nächsten Abschnitt (mit nano) oder Plan B (per Befehl, ohne Editor). Sonst direkt mit Installation weitermachen.
  • Versionsnummer im Paketnamen: Erweiterungen wie pgvector gibt es passend zu jeder PostgreSQL-Hauptversion, deshalb heißt das Paket postgresql-18-pgvector.

Optional: Offizielles PostgreSQL-Archiv einbinden

Diese Schritte sind nur nötig, wenn du die Pakete direkt vom PostgreSQL-Projekt beziehen willst. Danach geht es wie gewohnt mit dem Abschnitt Installation weiter; apt nimmt dann automatisch die Pakete aus dem neuen Archiv.

1. Paketlisten aktualisieren

Sorgt dafür, dass apt die aktuellen Versionen der Hilfsprogramme aus dem nächsten Schritt kennt.

sudo apt update

2. Hilfsprogramme installieren

curl lädt den Signaturschlüssel herunter, ca-certificates enthält die Zertifikate, mit denen die HTTPS-Verbindung zum Archiv geprüft wird.

sudo apt install -y curl ca-certificates

3. Ordner für den Schlüssel anlegen

Legt das Verzeichnis an, in dem der Signaturschlüssel des Archivs abgelegt wird. install -d erzeugt den Ordner samt fehlender Elternordner und stört sich nicht daran, wenn er schon existiert.

sudo install -d /usr/share/postgresql-common/pgdg

4. Signaturschlüssel herunterladen

Mit diesem Schlüssel prüft apt, dass die Pakete wirklich vom PostgreSQL-Projekt stammen und unterwegs nicht verändert wurden. --fail sorgt dafür, dass bei einem Fehler keine kaputte Datei gespeichert wird.

sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc

Prüfen: Die erste Zeile lautet -----BEGIN PGP PUBLIC KEY BLOCK-----.

head -1 /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc

5. Codenamen der Ubuntu-Version ermitteln

Das Archiv hat für jede Ubuntu-Version einen eigenen Bereich, der nach dem Codenamen benannt ist. Diesen Namen brauchst du im nächsten Schritt.

grep VERSION_CODENAME /etc/os-release

Prüfen: Bei Ubuntu 26.04 erscheint VERSION_CODENAME=resolute.

6. Paketquelle eintragen

Öffnet eine neue Datei, in der die Adresse des Archivs steht. Alle Dateien mit der Endung .sources in /etc/apt/sources.list.d/ liest apt automatisch als zusätzliche Paketquellen ein. Ubuntu 26.04 verwendet dieses Format auch für seine eigenen Paketquellen (ubuntu.sources).

sudo nano /etc/apt/sources.list.d/pgdg.sources

Füge diesen Inhalt ein (Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X. Der Teil vor -pgdg in der Zeile Suites muss zu dem Namen aus Schritt 5 passen, sonst findet apt im Archiv nichts.

Types: deb
URIs: https://apt.postgresql.org/pub/repos/apt
Suites: resolute-pgdg
Components: main
Architectures: amd64
Signed-By: /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc

Was die Felder bedeuten:

  • Types: deb – aus dieser Quelle werden fertige Programmpakete geladen, keine Quelltexte.
  • URIs – die Internetadresse des Archivs.
  • Suites – der Bereich des Archivs für deine Ubuntu-Version.
  • Components: main – der Teil des Archivs mit den PostgreSQL-Paketen.
  • Architectures: amd64 – nur Pakete für 64-Bit-PCs mit Intel- oder AMD-Prozessor werden geladen.
  • Signed-By – Pakete aus dieser Quelle werden nur mit dem Schlüssel aus Schritt 4 akzeptiert.

7. Paketlisten neu einlesen

Erst jetzt lädt apt das Paketverzeichnis des neuen Archivs herunter.

sudo apt update

Prüfen: Unter den Versionen taucht eine Zeile mit apt.postgresql.org auf, und die Version beim Installationskandidat enthält pgdg26.04, z. B. 18.6-1.pgdg26.04+2.

apt policy postgresql-18

Weiter geht es mit dem Abschnitt Installation. Möchtest du eine ältere Hauptversion, ersetze dort 18 durch die gewünschte Zahl, z. B. sudo apt install postgresql-17 und sudo apt install postgresql-17-pgvector.

Plan B: Offizielles Archiv per Befehl einbinden

Dieser Weg führt zum selben Ziel wie der vorige Abschnitt, kommt aber ohne Editor aus: Die Paketquelle wird mit einem einzigen Befehl in die Datei /etc/apt/sources.list.d/pgdg.list geschrieben, und der Codename der Ubuntu-Version wird automatisch eingesetzt. Das ist praktisch, wenn das Eintragen mit nano nicht klappt oder wenn du die Schritte in ein Skript übernehmen willst.

Wichtig: Nutze entweder den vorigen Abschnitt oder Plan B, nicht beide. Gibt es schon die Datei /etc/apt/sources.list.d/pgdg.sources, lösche sie vorher mit sudo rm /etc/apt/sources.list.d/pgdg.sources. Sonst meldet apt update, dass dieselbe Quelle mehrfach eingetragen ist.

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen der Hilfsprogramme aus dem nächsten Schritt kennt.

sudo apt update

2. Hilfsprogramme installieren

curl holt den Signaturschlüssel aus dem Internet, ca-certificates wird gebraucht, damit die HTTPS-Verbindung zum Archiv als vertrauenswürdig erkannt wird. -y beantwortet die Rückfrage von apt automatisch mit Ja.

sudo apt install -y curl ca-certificates

3. Ordner für den Schlüssel anlegen

Erzeugt das Verzeichnis, in dem der Schlüssel liegen soll. Ist es schon vorhanden, passiert nichts.

sudo install -d /usr/share/postgresql-common/pgdg

4. Signaturschlüssel herunterladen

Speichert den öffentlichen Schlüssel des PostgreSQL-Projekts. apt prüft damit später jedes Paket aus dem Archiv. Schlägt der Download fehl, bricht --fail ab, statt eine Fehlerseite als Schlüssel abzulegen.

sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc

Prüfen: Die Ausgabe lautet -----BEGIN PGP PUBLIC KEY BLOCK-----.

head -1 /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc

5. Angaben zur Ubuntu-Version laden

Die Datei /etc/os-release enthält Name, Versionsnummer und Codename des Systems als Variablen. Der Punkt am Anfang liest sie in das aktuelle Terminal ein, sodass der nächste Schritt den Codenamen über $VERSION_CODENAME verwenden kann. Führe Schritt 6 deshalb im selben Terminalfenster aus.

. /etc/os-release

Prüfen: Bei Ubuntu 26.04 erscheint resolute.

echo $VERSION_CODENAME

6. Paketquelle eintragen

Schreibt eine Zeile mit der Adresse des Archivs in die Datei pgdg.list. Dabei setzt die Shell den Codenamen aus Schritt 5 für $VERSION_CODENAME ein. Der Umweg über sudo sh -c "…" ist nötig, weil die Umleitung > sonst mit deinen normalen Rechten ausgeführt würde und die Datei unter /etc nicht angelegt werden dürfte.

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"

Prüfen: Die Datei enthält eine Zeile, die mit deb [signed-by= beginnt und resolute-pgdg main enthält. Steht dort nur -pgdg main ohne Codenamen, wurde Schritt 5 übersprungen oder in einem anderen Terminal ausgeführt. Dann Schritt 5 und 6 wiederholen.

cat /etc/apt/sources.list.d/pgdg.list

7. Paketlisten neu einlesen

Jetzt lädt apt das Paketverzeichnis des PostgreSQL-Archivs herunter.

sudo apt update

Prüfen: Beim Installationskandidat steht eine Version mit pgdg26.04, z. B. 18.6-1.pgdg26.04+2.

apt policy postgresql-18

Weiter geht es mit dem Abschnitt Installation.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von PostgreSQL aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. PostgreSQL installieren

Installiert den Datenbankserver, die Client-Programme wie psql und richtet einen ersten Datenbank-Cluster namens 18/main ein. Der Dienst wird dabei automatisch gestartet.

sudo apt install postgresql

Prüfen: Die Version des Befehlszeilen-Clients wird angezeigt, z. B. psql (PostgreSQL) 18.6.

psql --version

3. Prüfen, ob der Datenbankdienst läuft

PostgreSQL läuft als Hintergrunddienst (systemd). pg_lsclusters zeigt alle Datenbank-Cluster mit ihrem Zustand.

pg_lsclusters

Prüfen: In der Zeile 18 main 5432 steht in der Spalte Status der Wert online.

Erste Schritte

4. Verbindung zur Datenbank testen

Bei der Installation wird der Verwaltungsbenutzer postgres eingerichtet. Mit ihm testest du die Verbindung.

sudo -u postgres psql -c "SELECT version();"

Prüfen: Die Ausgabe beginnt mit PostgreSQL 18.

5. Eigenen Datenbank-Benutzer anlegen

Erstellt einen PostgreSQL-Benutzer mit dem Namen deines Ubuntu-Benutzers. Danach kannst du ohne sudo mit der Datenbank arbeiten. --superuser gibt ihm volle Rechte, das ist auf einem Entwicklungsrechner praktisch, aber auf einem Server nicht zu empfehlen.

sudo -u postgres createuser --superuser "$USER"

6. Entwicklungsdatenbank anlegen

Erstellt eine erste eigene Datenbank mit dem Namen devdb.

createdb devdb

Prüfen: Die Verbindung klappt, und die Ausgabe zeigt devdb.

psql -d devdb -c "SELECT current_database();"

Interaktiv öffnest du die Datenbank mit psql -d devdb. Mit \q verlässt du die Konsole wieder.

pgvector einrichten

7. pgvector installieren

Installiert die Erweiterung passend zu PostgreSQL 18. Ein Neustart des Datenbankdienstes ist nicht nötig.

sudo apt install postgresql-18-pgvector

8. Erweiterung in der Datenbank einschalten

Erweiterungen werden in PostgreSQL pro Datenbank eingeschaltet. Dieser Befehl macht den Datentyp vector in devdb verfügbar. Er braucht Superuser-Rechte, die dein Benutzer aus Schritt 5 hat.

psql -d devdb -c "CREATE EXTENSION vector;"

Prüfen: Die Tabelle zeigt die Erweiterung vector mit Version 0.8.1.

psql -d devdb -c "\dx vector"

9. Beispieltabelle mit Vektoren anlegen

Legt eine Tabelle an, in der jede Zeile einen Text und einen Vektor mit drei Werten enthält. In echten Anwendungen stammen die Vektoren von einem Embedding-Modell und haben meist mehrere hundert Werte, z. B. vector(768). Zum Ausprobieren reichen drei.

psql -d devdb <<'EOF'
CREATE TABLE notizen (
    id      bigserial PRIMARY KEY,
    text    text,
    vektor  vector(3)
);
INSERT INTO notizen (text, vektor) VALUES
    ('Apfel', '[1, 0, 0]'),
    ('Birne', '[0.9, 0.1, 0]'),
    ('Auto',  '[0, 0, 1]');
EOF

Prüfen: Die Ausgabe endet mit INSERT 0 3.

10. Ähnlichkeitssuche ausprobieren

Sucht die zwei Einträge, deren Vektor dem Suchvektor am ähnlichsten ist. Der Operator <=> berechnet den Kosinus-Abstand: Je kleiner der Wert, desto ähnlicher. Weitere Operatoren sind <-> (euklidischer Abstand) und <#> (negatives Skalarprodukt).

psql -d devdb -c "SELECT text, vektor <=> '[1, 0.05, 0]' AS abstand FROM notizen ORDER BY abstand LIMIT 2;"

Prüfen: Es erscheinen Apfel und Birne mit sehr kleinen Abständen. Auto liegt weit entfernt und fehlt deshalb.

11. Index für schnelle Suche anlegen

Ohne Index vergleicht PostgreSQL den Suchvektor mit jeder Zeile. Ein HNSW-Index beschleunigt die Suche bei vielen Einträgen deutlich. vector_cosine_ops passt zum Operator <=> aus dem vorigen Schritt.

psql -d devdb -c "CREATE INDEX ON notizen USING hnsw (vektor vector_cosine_ops);"

Prüfen: Unter Indexes steht ein Eintrag mit hnsw (vektor vector_cosine_ops).

psql -d devdb -c "\d notizen"

Optional: Autostart ausschalten

Auf einem Entwicklungsrechner muss der Datenbankdienst nicht bei jedem Rechnerstart laufen.

Autostart ausschalten:

sudo systemctl disable postgresql

Bei Bedarf von Hand starten und stoppen:

sudo systemctl start postgresql
sudo systemctl stop postgresql

Deinstallieren

1. PostgreSQL-Dienst stoppen

Beendet den laufenden Dienst vor der Deinstallation.

sudo systemctl stop postgresql

2. PostgreSQL und pgvector entfernen

purge entfernt die Pakete samt Konfigurationsdateien. Beim Paket postgresql-18 fragt apt, ob auch die Datenbank-Verzeichnisse gelöscht werden sollen. Wähle Ja, wenn die Daten weg können, sonst Nein.

sudo apt purge postgresql postgresql-18 postgresql-18-pgvector postgresql-client-18 postgresql-common postgresql-client-common

3. Nicht mehr benötigte Abhängigkeiten entfernen

Entfernt Bibliotheken, die nur für PostgreSQL installiert wurden.

sudo apt autoremove

4. Datenbankdateien löschen (optional)

Entfernt verbliebene Datenbank- und Konfigurationsverzeichnisse, falls du in Schritt 2 Nein gewählt hast. Achtung: Alle gespeicherten Daten gehen dabei unwiderruflich verloren.

sudo rm -rf /var/lib/postgresql /etc/postgresql

Prüfen: Der Befehl psql wird nicht mehr gefunden.

psql --version

5. Offizielles PostgreSQL-Archiv entfernen (falls eingebunden)

Nur nötig, wenn du den optionalen Abschnitt oder Plan B zum PostgreSQL-Archiv ausgeführt hast. Der Befehl löscht die Paketquelle (pgdg.sources bzw. bei Plan B pgdg.list) und den Signaturschlüssel. -f sorgt dafür, dass keine Fehlermeldung erscheint, wenn eine der beiden Quelldateien nicht existiert.

sudo rm -f /etc/apt/sources.list.d/pgdg.sources /etc/apt/sources.list.d/pgdg.list /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc

6. Paketlisten aktualisieren

Damit apt das entfernte Archiv vergisst.

sudo apt update

Prüfen: In der Ausgabe kommt apt.postgresql.org nicht mehr vor.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Git und cgit

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Git ist ein Versionsverwaltungssystem: Es speichert jeden Stand deiner Dateien und macht Änderungen nachvollziehbar. cgit ist eine schlanke Weboberfläche, mit der du Git-Repositories im Browser ansehen kannst, also Dateien, Änderungsverlauf und Unterschiede. Zusammen ergeben sie einen einfachen, lokalen Git-Server.

Vorbemerkungen

  • Installation über apt: Git und cgit sind beide in den Ubuntu-Paketquellen enthalten.
  • Voraussetzung für cgit: nginx ist nach der Anleitung installiert und läuft. cgit ist ein CGI-Programm. nginx kann solche Programme nicht selbst starten, deshalb übernimmt das der kleine Hilfsdienst fcgiwrap.
  • Aufbau: Die zentralen Repositories liegen als sogenannte Bare-Repositories (ohne Arbeitskopie, Name endet auf .git) im Ordner /srv/git. Dort liest cgit sie aus. Gearbeitet wird in Klonen, z. B. in deinem Home-Verzeichnis.
  • Nur lesen im Browser: cgit zeigt Repositories an und erlaubt das Klonen über HTTP. Änderungen hochladen (git push) geht in dieser Anleitung nur lokal über den Dateipfad.

Git installieren und einrichten

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Git und cgit aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Git installieren

Installiert Git. Unter Ubuntu ist es oft schon vorhanden, dann meldet apt das nur.

sudo apt install git

Prüfen: Die Versionsnummer wird angezeigt, z. B. git version 2.53.0.

git --version

3. Namen festlegen

Git schreibt zu jeder gespeicherten Änderung (Commit), wer sie gemacht hat. --global speichert die Einstellung für alle deine Repositories in der Datei ~/.gitconfig.

git config --global user.name "Dein Name"

4. E-Mail-Adresse festlegen

Gehört ebenfalls zu jedem Commit. Verwende die Adresse, die du auch bei Diensten wie GitHub oder GitLab angibst.

git config --global user.email "du@example.org"

5. Namen des Hauptzweigs festlegen

Neue Repositories bekommen damit den Hauptzweig main statt master. Das entspricht dem heute üblichen Standard.

git config --global init.defaultBranch main

Prüfen: Die Ausgabe enthält die drei Einstellungen.

git config --global --list

Zentrales Repository anlegen

6. Ordner für die Repositories anlegen

/srv ist unter Linux für Daten gedacht, die ein Dienst bereitstellt, hier cgit.

sudo mkdir -p /srv/git

7. Ordner deinem Benutzer übergeben

So kannst du ohne sudo Repositories anlegen und Änderungen hochladen. cgit läuft als Benutzer www-data und braucht nur Leserechte. Die hat es, weil neue Dateien unter Ubuntu für alle lesbar angelegt werden.

sudo chown "$USER":"$USER" /srv/git

8. Bare-Repository anlegen

Legt das leere, zentrale Repository test.git an. --bare bedeutet: Es enthält nur die Versionsgeschichte, keine Arbeitskopie zum Bearbeiten.

git init --bare /srv/git/test.git

9. Beschreibung eintragen

cgit zeigt den Inhalt der Datei description in der Übersicht aller Repositories an.

nano /srv/git/test.git/description

Git hat die Datei mit einem englischen Platzhaltertext angelegt. Lösche diese Zeile mit Strg+K und füge stattdessen ein (im Terminal mit Strg+Umschalt+V). Speichere mit Strg+O und Enter und beende nano mit Strg+X:

Test-Repository für cgit

10. Repository klonen

Erstellt eine Arbeitskopie in ~/test. Die Meldung, dass ein leeres Repository geklont wurde, ist hier richtig.

git clone /srv/git/test.git ~/test

11. Erste Datei anlegen

Eine README-Datei in Markdown. cgit zeigt sie später auf der Seite about des Repositorys an.

nano ~/test/README.md

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Test

Hallo **cgit**.

12. Datei für den Commit vormerken

git add nimmt die Datei in den nächsten Commit auf. -C ~/test führt den Befehl im Ordner ~/test aus, ohne dass du hineinwechseln musst.

git -C ~/test add README.md

13. Commit erstellen

Speichert den vorgemerkten Stand mit einer kurzen Beschreibung dauerhaft in der Versionsgeschichte.

git -C ~/test commit -m "Erster Commit"

14. Änderungen ins zentrale Repository hochladen

Überträgt den Commit nach /srv/git/test.git. -u merkt sich die Verbindung, danach genügt künftig git push.

git -C ~/test push -u origin main

Prüfen: Das zentrale Repository enthält den Commit „Erster Commit“.

git -C /srv/git/test.git log --oneline

cgit einrichten

15. cgit und Hilfsprogramme installieren

  • cgit – die Weboberfläche
  • fcgiwrap – startet cgit im Auftrag von nginx
  • python3-markdown – stellt README-Dateien in Markdown formatiert dar
  • python3-pygments – färbt Quellcode in der Dateiansicht ein

cgit empfiehlt den Webserver Apache. Weil nginx schon installiert ist, gilt diese Empfehlung als erfüllt, und Apache wird nicht mitinstalliert.

sudo apt install cgit fcgiwrap python3-markdown python3-pygments

Prüfen: Die Ausgabe lautet active. fcgiwrap wartet damit auf Anfragen von nginx.

systemctl is-active fcgiwrap.socket

16. cgit konfigurieren

Ersetzt die Einstellungsdatei /etc/cgitrc. Die Angaben bewirken Folgendes:

  • css, logo, favicon – Adressen von Stildatei und Bildern
  • root-title, root-desc – Überschrift und Untertitel der Startseite
  • virtual-root=/ – kurze Adressen wie /test/log/ statt /?url=test/log/
  • enable-http-clone, clone-url – Repositories lassen sich über HTTP klonen, die Adresse wird auf jeder Repository-Seite angezeigt
  • readme, about-filter – zeigt README.md formatiert auf der Seite about an
  • source-filter – Syntaxhervorhebung für Quellcode
  • remove-suffix=1 – zeigt test statt test.git an
  • scan-path – Ordner, in dem cgit nach Repositories sucht. Diese Zeile muss am Ende stehen, weil nur die Einstellungen darüber für die gefundenen Repositories gelten.
sudo nano /etc/cgitrc

Die Datei hat schon Inhalt, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

css=/cgit.css
logo=/cgit.png
favicon=/favicon.ico

root-title=Meine Git-Repositories
root-desc=Lokaler Git-Server auf dem Entwicklungsrechner

virtual-root=/
enable-http-clone=1
clone-url=http://localhost:8086/$CGIT_REPO_URL

readme=:README.md
about-filter=/usr/lib/cgit/filters/about-formatting.sh
source-filter=/usr/lib/cgit/filters/syntax-highlighting.py

remove-suffix=1
scan-path=/srv/git

17. nginx-Konfiguration für cgit anlegen

cgit läuft auf Port 8086 und ist nur vom eigenen Rechner aus erreichbar. Die festen Dateien, die cgit mitbringt (Stildatei, Skript, Logo und Symbol im Ordner /usr/share/cgit), liefert nginx direkt aus. Alle anderen Adressen reicht nginx über fcgiwrap an cgit weiter: SCRIPT_FILENAME nennt das Programm, das fcgiwrap starten soll, und PATH_INFO übergibt die aufgerufene Adresse. Daraus liest cgit ab, welches Repository und welche Ansicht gemeint sind, z. B. /test/log/.

sudo nano /etc/nginx/sites-available/cgit

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 127.0.0.1:8086;
    server_name localhost;

    # Stildatei, Skript, Logo und Symbol bringt cgit mit, nginx liefert sie direkt aus
    location ~ ^/(cgit\.(css|js|png)|favicon\.ico|robots\.txt)$ {
        root /usr/share/cgit;
    }

    # Alle übrigen Adressen beantwortet cgit, gestartet über fcgiwrap
    location / {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
        fastcgi_param PATH_INFO $uri;
        fastcgi_pass unix:/run/fcgiwrap.socket;
    }
}

18. Konfiguration aktivieren

Ein Link in sites-enabled sorgt dafür, dass nginx die neue Seite lädt.

sudo ln -s /etc/nginx/sites-available/cgit /etc/nginx/sites-enabled/cgit

19. nginx-Konfiguration testen

Findet Tippfehler, bevor nginx neu geladen wird.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

20. nginx neu laden

Übernimmt die Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

Testen

21. Startseite aufrufen

Prüft, ob cgit antwortet und das Repository findet.

curl -s http://localhost:8086/ | grep "Test-Repository"

Prüfen: Die Ausgabe enthält Test-Repository für cgit. Im Browser zeigt http://localhost:8086 die Liste der Repositories. Ein Klick auf test öffnet das Repository, unter about erscheint die formatierte README-Datei, unter log der Commit.

22. Über HTTP klonen

Prüft, ob das Klonen über die Weboberfläche funktioniert. Der Klon landet in ~/test-klon.

git clone http://localhost:8086/test ~/test-klon

Prüfen: Der Klon enthält den Commit „Erster Commit“.

git -C ~/test-klon log --oneline

23. Test-Klon wieder löschen

Der Klon aus dem vorigen Schritt wird nicht mehr gebraucht.

rm -rf ~/test-klon

Weitere Repositories hinzufügen

Jedes Bare-Repository, das du in /srv/git anlegst, erscheint automatisch in cgit, genau wie in den Schritten 8 und 9. Ein bestehendes Projekt lädst du so hoch: Leeres Bare-Repository anlegen, dann im Projektordner das Ziel eintragen und hochladen:

git remote add origin /srv/git/projekt.git
git push -u origin main

Deinstallieren

1. Seite in nginx deaktivieren

Löscht den Link aus sites-enabled.

sudo rm -f /etc/nginx/sites-enabled/cgit

2. nginx-Konfigurationsdatei löschen

Löscht die Konfigurationsdatei der Seite.

sudo rm -f /etc/nginx/sites-available/cgit

3. nginx neu laden

Übernimmt das Abschalten der Seite.

sudo systemctl reload nginx

4. cgit und Hilfsprogramme entfernen

purge entfernt auch die Einstellungsdatei /etc/cgitrc. python3-pygments bleibt installiert, weil es auch andere Programme nutzen.

sudo apt purge cgit fcgiwrap python3-markdown

5. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für cgit installiert wurden.

sudo apt autoremove

6. Repositories und Arbeitskopie löschen (optional)

Achtung: Löscht alle zentralen Repositories in /srv/git und die Arbeitskopie ~/test endgültig. Nur ausführen, wenn du sie nicht mehr brauchst oder vorher gesichert hast.

sudo rm -rf /srv/git ~/test

7. Git entfernen (optional)

Git brauchen viele andere Programme und Anleitungen (z. B. MediaWiki). Entferne es nur, wenn du sicher bist, dass du es nicht mehr brauchst. Deine persönlichen Einstellungen in ~/.gitconfig bleiben dabei erhalten.

sudo apt purge git

Prüfen: Unter http://localhost:8086 antwortet kein Webserver mehr, curl meldet einen Verbindungsfehler.

curl -sI http://localhost:8086/

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Tileserver (OpenStreetMap)

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Ein Tileserver erzeugt aus OpenStreetMap-Daten eigene Kartenkacheln (PNG-Bilder), die sich in Webkarten wie Leaflet oder OpenLayers einbinden lassen – ohne Abhängigkeit von fremden Kartendiensten.

Vorbemerkungen

Der Tileserver besteht aus mehreren Bausteinen, die zusammenarbeiten:

BausteinAufgabe
PostgreSQL + PostGISspeichert die importierten OSM-Daten mit Geometrien
osm2pgsqlliest eine .osm.pbf-Datei und schreibt sie in die Datenbank
OpenStreetMap CartoKartenstil (Farben, Linien, Beschriftungen) im CartoCSS-Format
cartoübersetzt den Kartenstil in eine Mapnik-XML-Datei
Mapnikzeichnet aus Datenbank und Stil die Kartenbilder
renderdHintergrunddienst, der Kacheln mit Mapnik rendert und zwischenspeichert
Apache + mod_tileliefert die Kacheln per HTTP aus und beauftragt bei Bedarf renderd

Hinweise zum Umfang:

  • Diese Anleitung importiert als Beispiel nur die Stadt Ahrensburg (Kreis Stormarn). Der kleine Ausschnitt ist in wenigen Sekunden importiert. Größere Gebiete brauchen deutlich mehr Arbeitsspeicher, Festplattenplatz und Zeit. Für ganz Deutschland sollten es mindestens 32 GB RAM und rund 200 GB SSD-Speicher sein.
  • Die Kartendaten und der Kartenstil liegen unter /srv/osm. So muss das Home-Verzeichnis nicht für andere Benutzer freigegeben werden.
  • Ubuntu 26.04 bringt PostgreSQL 18 und Mapnik 4.2 mit. Pfade und Paketnamen unten sind darauf abgestimmt.
  • Quelle: Die Texte dieser Anleitung sind eigenständig geschrieben. Als technische Grundlage für die Befehle zu Datenbank, Import und renderd diente die englische Anleitung „Manually building a tile server (Ubuntu 24.04 LTS)“ der switch2osm-Mitwirkenden, veröffentlicht unter der Lizenz CC BY-SA 2.0. Befehle, Pfade und Versionen sind hier auf Ubuntu 26.04, Mapnik 4.2 und den Ausschnitt Ahrensburg abgestimmt.

Installation der Pakete

1. Paketlisten aktualisieren

Sorgt dafür, dass apt die neuesten Paketversionen aus den Ubuntu-Quellen kennt.

sudo apt update

2. Datenbank-Pakete installieren

Installiert PostgreSQL, die Geodaten-Erweiterung PostGIS und das Importwerkzeug osm2pgsql.

sudo apt install -y postgresql postgresql-contrib postgis postgresql-18-postgis-3 postgresql-18-postgis-3-scripts osm2pgsql

Prüfen: Die Version von osm2pgsql wird ausgegeben.

osm2pgsql --version

3. Render-Pakete installieren

Installiert den Renderdienst renderd, das Apache-Modul mod_tile, den Webserver Apache sowie die Mapnik-Werkzeuge.

sudo apt install -y apache2 renderd libapache2-mod-tile mapnik-utils

Prüfen: Apache läuft (active). renderd meldet an dieser Stelle noch failed – das ist richtig so, denn es ist noch kein Kartenstil eingetragen (Schritt 22).

systemctl is-active apache2 renderd

Port 80 schon belegt? Läuft auf dem Rechner bereits ein anderer Webserver (z. B. nginx), kann Apache nicht starten und meldet failed mit Address already in use bzw. no listening sockets available. Dann Apache auf Port 8080 legen und in allen späteren URLs localhost:8080 statt localhost verwenden:

sudo nano /etc/apache2/ports.conf

Suche mit Strg+W nach Listen 80, ändere die Zeile in Listen 8080, speichere mit Strg+O und Enter und beende nano mit Strg+X.

sudo nano /etc/apache2/sites-available/000-default.conf

Ändere die erste Zeile <VirtualHost *:80> in <VirtualHost *:8080>, speichere und beende nano. Danach Apache neu starten:

sudo systemctl restart apache2

Damit die Karte später auch ohne :8080 erreichbar ist, kann nginx die Kachelanfragen an Apache weiterreichen – siehe nginx als Proxy vor Apache.

4. Werkzeuge für den Kartenstil installieren

node-carto übersetzt den Kartenstil, osmium-tool schneidet ein Stadtgebiet aus einer größeren OSM-Datei aus, gdal-bin und die Python-Module werden vom Hilfsskript für die Küstenlinien- und Grenzdaten gebraucht, git holt den Kartenstil.

sudo apt install -y git curl unzip osmium-tool node-carto gdal-bin python3-psycopg2 python3-yaml python3-requests

Prüfen: carto meldet mindestens Version 1.2.0.

carto -v

5. Schriftarten installieren

Der Kartenstil beschriftet Orte in vielen Schriftsystemen und erwartet dafür die Noto-Schriften. Über apt installiert, findet Mapnik sie automatisch unter /usr/share/fonts.

sudo apt install -y fonts-noto-core fonts-noto-ui-core fonts-noto-cjk fonts-noto-extra fonts-hanazono fonts-unifont

Datenbank einrichten

6. Datenbank gis anlegen

Der Dienst renderd läuft als Systembenutzer _renderd (wurde mit dem Paket angelegt). Deshalb bekommt dieser Benutzer eine gleichnamige Datenbankrolle und wird Besitzer der Datenbank gis. Der Name gis ist im Kartenstil fest eingetragen.

sudo -u postgres createuser _renderd
sudo -u postgres createdb -E UTF8 -O _renderd gis

7. Erweiterungen PostGIS und hstore aktivieren

PostGIS ergänzt die Datenbank um Geometrie-Datentypen, hstore speichert beliebige OSM-Schlüssel/Wert-Paare in einer Spalte.

sudo -u postgres psql -d gis -c "CREATE EXTENSION postgis;" -c "CREATE EXTENSION hstore;"

8. Besitz der PostGIS-Tabellen übertragen

Die beiden Verwaltungstabellen von PostGIS gehören nach dem Anlegen postgres. _renderd braucht Schreibrechte darauf, damit der Import funktioniert.

sudo -u postgres psql -d gis -c "ALTER TABLE geometry_columns OWNER TO _renderd;" -c "ALTER TABLE spatial_ref_sys OWNER TO _renderd;"

Prüfen: In der Liste der Erweiterungen stehen postgis und hstore.

sudo -u postgres psql -d gis -c "\dx"

Kartenstil vorbereiten

9. Arbeitsverzeichnis anlegen

Legt /srv/osm an und macht den eigenen Benutzer zum Besitzer, damit die folgenden Schritte ohne sudo auskommen.

sudo mkdir -p /srv/osm
sudo chown "$USER": /srv/osm

10. OpenStreetMap Carto herunterladen

Klont den Standard-Kartenstil von openstreetmap.org.

git clone https://github.com/gravitystorm/openstreetmap-carto.git /srv/osm/openstreetmap-carto

11. Feste Version auswählen

Wechselt auf die veröffentlichte Version 5.9.0, damit Stil, Importregeln und Datenbankfunktionen sicher zueinander passen.

git -C /srv/osm/openstreetmap-carto switch --detach v5.9.0

12. Kartenstil in Mapnik-XML übersetzen

carto wandelt die Projektdatei project.mml in die Datei mapnik.xml um, die renderd später lädt.

cd /srv/osm/openstreetmap-carto && carto project.mml > mapnik.xml

Prüfen: Die Datei existiert und ist mehrere Megabyte groß. Warnungen von carto sind unkritisch, solange die Datei entsteht.

ls -lh /srv/osm/openstreetmap-carto/mapnik.xml

OSM-Daten importieren

13. Datenverzeichnis anlegen

Hier landet der heruntergeladene Kartenausschnitt.

mkdir -p /srv/osm/data

14. Bundesland Schleswig-Holstein herunterladen

Geofabrik bietet tagesaktuelle Ausschnitte der OSM-Daten an, allerdings nur bis hinunter zu Bundesländern und Regierungsbezirken. Für Ahrensburg wird deshalb zuerst das ganze Bundesland geladen (rund 150 MB). Für ein anderes Gebiet die passende URL von https://download.geofabrik.de/ einsetzen.

curl -L -o /srv/osm/data/schleswig-holstein-latest.osm.pbf https://download.geofabrik.de/europe/germany/schleswig-holstein-latest.osm.pbf

15. Ahrensburg ausschneiden

osmium extract schneidet ein Rechteck aus der Datei heraus. Die Werte nach -b sind die Ecken des Rechtecks als westliche Länge, südliche Breite, östliche Länge, nördliche Breite und umschließen das Stadtgebiet von Ahrensburg. Die Grenzen einer anderen Stadt lassen sich z. B. auf https://www.openstreetmap.org über „Export“ ablesen.

osmium extract -b 10.16,53.63,10.32,53.71 /srv/osm/data/schleswig-holstein-latest.osm.pbf -o /srv/osm/data/ahrensburg.osm.pbf

Prüfen: Die neue Datei ist nur wenige Megabyte groß.

ls -lh /srv/osm/data

16. Daten in die Datenbank importieren

osm2pgsql liest die PBF-Datei und legt die Tabellen an, die OpenStreetMap Carto erwartet. Der Import läuft als _renderd, damit dieser Benutzer die Tabellen besitzt.

Bedeutung der Optionen:

  • --create --slim: neue Datenbank aufbauen, Zwischendaten in der Datenbank statt im RAM halten (Voraussetzung für spätere Updates)
  • -G: Multipolygone als eine zusammenhängende Geometrie speichern
  • --hstore: legt zusätzlich die Spalte tags an. Darin landen als Schlüssel/Wert-Paare alle Merkmale eines Objekts, die in der Spaltenliste (-S) nicht vorkommen
  • --tag-transform-script und -S: Regeln und Spaltenliste aus dem Kartenstil
  • -C 2500: bis zu 2500 MB Arbeitsspeicher als Zwischenspeicher nutzen – bei wenig RAM kleiner wählen
sudo -u _renderd osm2pgsql -d gis --create --slim -G --hstore \
  --tag-transform-script /srv/osm/openstreetmap-carto/openstreetmap-carto.lua \
  -S /srv/osm/openstreetmap-carto/openstreetmap-carto.style \
  -C 2500 --number-processes 1 \
  /srv/osm/data/ahrensburg.osm.pbf

Prüfen: Am Ende meldet osm2pgsql osm2pgsql took ... overall. Die Tabellen sind vorhanden:

sudo -u _renderd psql -d gis -c "\dt"

17. Indizes anlegen

Zusätzliche Indizes beschleunigen die Abfragen, die Mapnik beim Zeichnen der Kacheln stellt.

cd /srv/osm/openstreetmap-carto && sudo -u _renderd psql -d gis -f indexes.sql

18. Datenbankfunktionen einspielen

Der Kartenstil ruft einige eigene SQL-Funktionen auf (z. B. zur Auswahl von Beschriftungen), die hier angelegt werden.

cd /srv/osm/openstreetmap-carto && sudo -u _renderd psql -d gis -f functions.sql

19. Externe Daten laden

Küstenlinien, Meeresflächen und einige Grenzen stammen nicht aus der PBF-Datei, sondern werden separat heruntergeladen und in die Datenbank geladen. Das Verzeichnis data muss _renderd gehören, weil das Skript als dieser Benutzer läuft.

mkdir -p /srv/osm/openstreetmap-carto/data
sudo chown _renderd /srv/osm/openstreetmap-carto/data
cd /srv/osm/openstreetmap-carto && sudo -u _renderd scripts/get-external-data.py

Prüfen: Das Skript endet ohne Fehlermeldung; die Tabelle water_polygons ist gefüllt.

sudo -u _renderd psql -d gis -c "SELECT count(*) FROM water_polygons;"

renderd konfigurieren

20. Konfigurationsdatei öffnen

Die Einstellungen von renderd liegen in /etc/renderd.conf.

sudo nano /etc/renderd.conf

21. Mapnik-Pfade korrigieren

Die mitgelieferte Datei zeigt noch auf das Plugin-Verzeichnis von Mapnik 3.1. Unter Ubuntu 26.04 liegt Mapnik 4.2 an anderer Stelle. Außerdem soll renderd alle Schriften unter /usr/share/fonts finden (die CJK-Schriften liegen unter opentype, nicht unter truetype). Den Abschnitt [mapnik] so ändern:

[mapnik]
plugins_dir=/usr/lib/x86_64-linux-gnu/mapnik/4.2/input
font_dir=/usr/share/fonts
font_dir_recurse=true

Prüfen: Im angegebenen Verzeichnis liegt u. a. postgis+pgraster.input – das ist das Plugin, mit dem Mapnik die Datenbank liest.

ls /usr/lib/x86_64-linux-gnu/mapnik/4.2/input

22. Kartenstil als Kachelsatz eintragen

Am Ende der Datei einen eigenen Abschnitt ergänzen. URI ist der URL-Pfad, unter dem die Kacheln erreichbar sind, XML der in Schritt 12 erzeugte Stil.

[osm]
URI=/osm/
XML=/srv/osm/openstreetmap-carto/mapnik.xml
HOST=localhost
TILESIZE=256
MAXZOOM=20

Anschließend speichern (Strg+O, Enter) und schließen (Strg+X).

23. renderd neu starten

Lädt die geänderte Konfiguration und den Kartenstil.

sudo systemctl restart renderd

Prüfen: Der Dienst ist active (running). Fehler beim Laden des Stils stehen im Journal.

systemctl status renderd --no-pager
journalctl -u renderd -n 30 --no-pager

Apache konfigurieren

24. Modul mod_tile aktivieren

Schaltet das Apache-Modul ein, das Kachel-URLs erkennt und mit renderd spricht. Meist hat das Paket das schon erledigt; die Meldung Module tile already enabled ist dann in Ordnung.

sudo a2enmod tile

25. Konfiguration für mod_tile anlegen

Die Datei sagt mod_tile, wo die Kachelsätze beschrieben sind und über welchen Socket renderd erreichbar ist. Die Zeitlimits legen fest, wie lange Apache auf eine neu gerenderte Kachel wartet.

sudo nano /etc/apache2/conf-available/renderd.conf

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

LoadTileConfigFile /etc/renderd.conf
ModTileRenderdSocketName /run/renderd/renderd.sock
ModTileRequestTimeout 3
ModTileMissingRequestTimeout 60

26. Konfiguration aktivieren

Bindet die neue Datei in Apache ein.

sudo a2enconf renderd

27. Apache neu starten

Neu starten statt nur neu laden, weil ein Modul hinzugekommen ist.

sudo systemctl restart apache2

Prüfen: Die Konfiguration ist fehlerfrei.

sudo apache2ctl configtest

Tileserver testen

28. Erste Kachel abrufen

Fordert die Weltkarte in Zoomstufe 0 an. Beim ersten Aufruf rendert renderd die Kachel, das kann einige Sekunden dauern.

curl -o /tmp/kachel.png http://localhost/osm/0/0/0.png

Prüfen: Die Datei ist ein PNG-Bild mit 256 × 256 Pixeln.

file /tmp/kachel.png

29. Testseite mit Leaflet anlegen

Eine kleine HTML-Seite zeigt die eigenen Kacheln als verschiebbare Karte, zentriert auf die Ahrensburger Innenstadt.

sudo nano /var/www/html/karte.html

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <title>Eigener Tileserver</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css">
  <script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js"></script>
  <style>html, body, #karte { height: 100%; margin: 0; }</style>
</head>
<body>
  <div id="karte"></div>
  <script>
    const karte = L.map('karte').setView([53.675, 10.236], 14);
    L.tileLayer('/osm/{z}/{x}/{y}.png', {
      maxZoom: 20,
      attribution: '&copy; OpenStreetMap-Mitwirkende'
    }).addTo(karte);
  </script>
</body>
</html>

30. Karte im Browser öffnen

Beim Verschieben und Zoomen werden fehlende Kacheln nachgerendert; bereits erzeugte Kacheln kommen aus dem Zwischenspeicher unter /var/cache/renderd/tiles.

xdg-open http://localhost/karte.html

Prüfen: Die Zahl der zwischengespeicherten Metakacheln (je 8 × 8 Kacheln in einer .meta-Datei) wächst, während man in der Karte herumzoomt.

find /var/cache/renderd/tiles -name '*.meta' | wc -l

Installation prüfen

osm2pgsql --version
systemctl is-active postgresql renderd apache2
curl -sI http://localhost/osm/0/0/0.png | head -n 1

Die letzte Zeile sollte HTTP/1.1 200 OK lauten.

Deinstallieren

1. Dienste stoppen

Beendet renderd und Apache, damit keine Dateien mehr in Benutzung sind.

sudo systemctl stop renderd apache2

2. Datenbank und Rolle löschen

Achtung: Alle importierten Kartendaten gehen verloren.

sudo -u postgres dropdb gis
sudo -u postgres dropuser _renderd

3. Kartenstil, Daten und Kachel-Zwischenspeicher löschen

sudo rm -r /srv/osm /var/cache/renderd

4. Testseite und Apache-Konfiguration entfernen

sudo rm /var/www/html/karte.html /etc/apache2/conf-available/renderd.conf

5. Pakete entfernen

purge entfernt auch die Konfigurationsdateien wie /etc/renderd.conf. PostgreSQL und Apache nur mit entfernen, wenn sie nicht für andere Zwecke gebraucht werden.

sudo apt purge renderd libapache2-mod-tile mapnik-utils node-carto osmium-tool osm2pgsql postgresql-18-postgis-3 postgresql-18-postgis-3-scripts postgis

6. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für den Tileserver installiert wurden.

sudo apt autoremove

Prüfen: Die Befehle werden nicht mehr gefunden.

renderd -h
osm2pgsql --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Martin (Vektor-Tileserver)

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Martin liefert aus PostGIS-Tabellen Vektorkacheln, die ein Webbrowser erst beim Anzeigen zeichnet. Diese Anleitung importiert die Stadt Ahrensburg aus der Datei ahrensburg.osm.pbf in PostgreSQL und veröffentlicht sie über Martin.

Vorbemerkungen

So arbeiten die Bausteine zusammen:

BausteinAufgabe
PostgreSQL + PostGIShält die OSM-Daten samt Geometrien
osm2pgsqlliest ahrensburg.osm.pbf und legt dabei eigene, schlanke Tabellen an
Martinfindet die Tabellen selbst und erzeugt daraus auf Anfrage Vektorkacheln (Format MVT)
MapLibre GL JSzeichnet die Vektorkacheln im Browser und bestimmt Farben und Linien

Hinweise:

  • Martin rendert keine Bilder. Das Aussehen der Karte legt allein die Webseite fest (Schritt 22). Einen Kartenstil wie OpenStreetMap Carto braucht es deshalb nicht.
  • Martin ist nicht in den Ubuntu-Paketquellen enthalten. Das Projekt stellt aber ein fertiges .deb-Paket bereit. Getestet wurde diese Anleitung mit Martin 1.16.1, PostgreSQL 18 und osm2pgsql 2.2.
  • Die Daten liegen in einer eigenen Datenbank osm. Eine vorhandene Datenbank gis aus der Anleitung Tileserver (OpenStreetMap) wird nicht verändert.
  • Martin läuft unter einem eigenen Systembenutzer martin. Weil die Datenbankrolle genauso heißt, meldet sich Martin über den lokalen Socket ohne Passwort an (Anmeldeart peer).
  • Martin hört nur auf 127.0.0.1:3000, ist also von anderen Rechnern aus nicht erreichbar.

Installation der Pakete

1. Paketlisten aktualisieren

Damit apt die neuesten Paketversionen kennt.

sudo apt update

2. Datenbank und Importwerkzeuge installieren

Installiert PostgreSQL mit der Geodaten-Erweiterung PostGIS, das Importprogramm osm2pgsql, das Ausschneidewerkzeug osmium und curl für Downloads. Bereits installierte Pakete lässt apt einfach stehen.

sudo apt install -y postgresql postgis postgresql-18-postgis-3 osm2pgsql osmium-tool curl

Prüfen: osm2pgsql meldet Version 2.0 oder neuer. Ältere Versionen verstehen die Importregeln aus Schritt 13 nicht.

osm2pgsql --version

3. Martin-Paket herunterladen

Lädt das .deb-Paket von der Release-Seite des Projekts (https://github.com/maplibre/martin/releases). Für eine neuere Version die Versionsnummer in der Adresse austauschen.

curl -L -o /tmp/martin.deb https://github.com/maplibre/martin/releases/download/martin-v1.16.1/debian-x86_64.deb

Prüfen: Die Datei ist rund 28 MB groß.

ls -lh /tmp/martin.deb

4. Martin installieren

apt installiert auch lokale Dateien. Wichtig ist das ./ bzw. der volle Pfad, sonst sucht apt in den Paketquellen nach einem Paket dieses Namens. Das Paket bringt die Programme martin, martin-cp und mbtiles, eine Beispielkonfiguration in /etc/martin/config.yaml und einen systemd-Dienst mit.

sudo apt install -y /tmp/martin.deb

Prüfen:

martin --version

5. Heruntergeladene Datei löschen

Das Paket ist installiert, die Datei wird nicht mehr gebraucht.

rm /tmp/martin.deb

Benutzer und Datenbank einrichten

6. Systembenutzer martin anlegen

Unter diesem Benutzer laufen später der Import und der Dienst. Er hat kein Home-Verzeichnis und keine Login-Shell, weil er nur für Martin da ist.

sudo useradd --system --no-create-home --shell /usr/sbin/nologin martin

7. Datenbankrolle martin anlegen

Eine gleichnamige Rolle in PostgreSQL erlaubt dem Systembenutzer martin die passwortlose Anmeldung über den lokalen Socket.

sudo -u postgres createuser martin

8. Datenbank osm anlegen

Die Datenbank gehört martin. So darf der Import darin Tabellen anlegen und löschen.

sudo -u postgres createdb -E UTF8 -O martin osm

9. PostGIS aktivieren

Erst mit dieser Erweiterung kennt die Datenbank Geometrien. Nur postgres darf sie einschalten.

sudo -u postgres psql -d osm -c "CREATE EXTENSION postgis;"

Prüfen: Die Anmeldung als martin klappt, und die PostGIS-Version wird angezeigt.

sudo -u martin psql -d osm -c "SELECT postgis_version();"

Kartendaten vorbereiten

Liegt /srv/osm/data/ahrensburg.osm.pbf schon vor (z. B. aus der Anleitung Tileserver (OpenStreetMap)), geht es direkt mit Schritt 13 weiter.

10. Datenverzeichnis anlegen

Unter /srv/osm kann der Benutzer martin die Dateien lesen. Aus dem Home-Verzeichnis ginge das nicht ohne Weiteres.

sudo mkdir -p /srv/osm/data
sudo chown "$USER": /srv/osm/data

11. Schleswig-Holstein herunterladen

Geofabrik stellt OSM-Auszüge je Bundesland bereit (rund 150 MB), aber keine einzelnen Städte. Deshalb zuerst das Bundesland laden.

curl -L -o /srv/osm/data/schleswig-holstein-latest.osm.pbf https://download.geofabrik.de/europe/germany/schleswig-holstein-latest.osm.pbf

12. Ahrensburg ausschneiden

osmium extract schneidet ein Rechteck aus. Die vier Zahlen hinter -b sind westliche Länge, südliche Breite, östliche Länge und nördliche Breite rund um Ahrensburg.

osmium extract -b 10.16,53.63,10.32,53.71 /srv/osm/data/schleswig-holstein-latest.osm.pbf -o /srv/osm/data/ahrensburg.osm.pbf

Prüfen: ahrensburg.osm.pbf ist nur wenige Megabyte groß.

ls -lh /srv/osm/data

Importregeln festlegen

13. Ordner für die Importregeln anlegen

In diesem Ordner liegt die Lua-Datei, die osm2pgsql sagt, welche OSM-Objekte in welche Tabelle kommen.

sudo mkdir -p /srv/osm/martin

14. Lua-Datei anlegen

osm2pgsql arbeitet hier mit der Flex-Ausgabe: Ein Lua-Skript legt die Tabellen fest und entscheidet für jedes Objekt, wohin es gehört. Das Beispiel legt vier Tabellen an: strassen (Wege und Straßen als Linien), gebaeude (Umrisse), flaechen (Wald, Wasser, Wiesen, Parks usw.) und orte (Punkte wie Geschäfte, Ärzte, Schulen). Die Geometrien speichert osm2pgsql automatisch in Web-Mercator (EPSG:3857), der Projektion der Webkarten. Martin muss dann nichts umrechnen.

sudo nano /srv/osm/martin/ahrensburg.lua

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

-- Importregeln für Martin: vier einfache Tabellen in Web-Mercator (EPSG:3857)

local strassen = osm2pgsql.define_way_table('strassen', {
    { column = 'art', type = 'text' },
    { column = 'name', type = 'text' },
    { column = 'geom', type = 'linestring', not_null = true },
})

local gebaeude = osm2pgsql.define_area_table('gebaeude', {
    { column = 'art', type = 'text' },
    { column = 'hausnummer', type = 'text' },
    { column = 'geom', type = 'geometry', not_null = true },
})

local flaechen = osm2pgsql.define_area_table('flaechen', {
    { column = 'art', type = 'text' },
    { column = 'name', type = 'text' },
    { column = 'geom', type = 'geometry', not_null = true },
})

local orte = osm2pgsql.define_node_table('orte', {
    { column = 'art', type = 'text' },
    { column = 'name', type = 'text' },
    { column = 'geom', type = 'point', not_null = true },
})

-- Welche Schlüssel eine Fläche beschreiben (in dieser Reihenfolge geprüft)
local flaechen_schluessel = { 'natural', 'landuse', 'leisure', 'water' }

local function flaechen_art(tags)
    for _, schluessel in ipairs(flaechen_schluessel) do
        if tags[schluessel] then
            return schluessel .. '=' .. tags[schluessel]
        end
    end
    return nil
end

function osm2pgsql.process_node(object)
    local art = object.tags.amenity or object.tags.shop or object.tags.place
    if art then
        orte:insert({
            art = art,
            name = object.tags.name,
            geom = object:as_point(),
        })
    end
end

function osm2pgsql.process_way(object)
    local tags = object.tags
    if tags.building and object.is_closed then
        gebaeude:insert({
            art = tags.building,
            hausnummer = tags['addr:housenumber'],
            geom = object:as_polygon(),
        })
    elseif tags.highway then
        strassen:insert({
            art = tags.highway,
            name = tags.name,
            geom = object:as_linestring(),
        })
    elseif object.is_closed then
        local art = flaechen_art(tags)
        if art then
            flaechen:insert({
                art = art,
                name = tags.name,
                geom = object:as_polygon(),
            })
        end
    end
end

function osm2pgsql.process_relation(object)
    local tags = object.tags
    if tags.type ~= 'multipolygon' then
        return
    end
    if tags.building then
        gebaeude:insert({
            art = tags.building,
            hausnummer = tags['addr:housenumber'],
            geom = object:as_multipolygon(),
        })
        return
    end
    local art = flaechen_art(tags)
    if art then
        flaechen:insert({
            art = art,
            name = tags.name,
            geom = object:as_multipolygon(),
        })
    end
end

Bei Flächen steht in der Spalte art Schlüssel und Wert zusammen, z. B. natural=water oder landuse=forest. Danach richtet die Testseite in Schritt 22 die Farben aus.

Daten importieren

15. In ein Verzeichnis wechseln, das martin lesen darf

sudo -u martin behält das aktuelle Verzeichnis bei. Liegt das im eigenen Home-Verzeichnis, gibt es sonst eine Warnung über fehlende Rechte.

cd /srv/osm

16. ahrensburg.osm.pbf importieren

Der Import läuft als martin, damit dieser Benutzer die neuen Tabellen besitzt.

  • -d osm: Zieldatenbank
  • -O flex: Flex-Ausgabe mit eigenen Tabellen
  • -S …/ahrensburg.lua: die Importregeln aus Schritt 14
sudo -u martin osm2pgsql -d osm -O flex -S /srv/osm/martin/ahrensburg.lua /srv/osm/data/ahrensburg.osm.pbf

Prüfen: Am Ende steht osm2pgsql took … overall. Die vier Tabellen sind gefüllt (zum Zeitpunkt des Tests je nach Tabelle zwischen 2 000 und 21 000 Zeilen):

sudo -u martin psql -d osm -c "SELECT 'strassen' AS tabelle, count(*) FROM strassen UNION ALL SELECT 'gebaeude', count(*) FROM gebaeude UNION ALL SELECT 'flaechen', count(*) FROM flaechen UNION ALL SELECT 'orte', count(*) FROM orte;"

Ein erneuter Aufruf von Schritt 16 (z. B. mit neueren Daten) löscht die Tabellen und baut sie neu auf.

Martin einrichten

17. Konfigurationsdatei öffnen

Das Paket hat unter /etc/martin/config.yaml schon eine Beispieldatei angelegt. Sie wird komplett ersetzt.

sudo nano /etc/martin/config.yaml

Lösche den vorhandenen Inhalt: Alt+\ (Dateianfang), Alt+A (Markierung starten), Alt+/ (Dateiende), Strg+K (Markiertes ausschneiden).

18. Neue Konfiguration eintragen

Füge diesen Inhalt ein (Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Nur lokal erreichbar
listen_addresses: '127.0.0.1:3000'

# Übersichtsseite mit allen Kachelquellen unter http://localhost:3000/
web_ui: enable-for-all

cache:
  size_mb: 256

postgres:
  # Anmeldung über den lokalen Socket, ohne Passwort
  connection_string: 'postgresql:///osm?host=/var/run/postgresql&user=martin'
  # Ausdehnung der Daten beim Start genau berechnen
  auto_bounds: calc
  auto_publish:
    tables: true
    functions: false

Was die Einträge bewirken:

  • connection_string: Der leere Teil zwischen // und /osm heißt „kein Rechnername“. Mit host=/var/run/postgresql nutzt Martin den Unix-Socket statt TCP. Nur so greift die passwortlose Anmeldung.
  • auto_publish.tables: true: Martin veröffentlicht jede Tabelle mit Geometriespalte als eigene Kachelquelle, benannt nach der Tabelle.
  • auto_bounds: calc: Martin trägt in die Beschreibung jeder Quelle den Ausschnitt ein, der tatsächlich Daten enthält.

19. Ordner für die Dienst-Ergänzung anlegen

Der mitgelieferte Dienst würde Martin als root starten. Das ist unnötig, und die Anmeldung als martin bei der Datenbank würde scheitern. Eine Ergänzungsdatei (Drop-in) ändert das, ohne die Paketdatei anzufassen, die bei einem Update überschrieben würde.

sudo mkdir -p /etc/systemd/system/martin.service.d

20. Ergänzungsdatei anlegen

sudo nano /etc/systemd/system/martin.service.d/override.conf

Füge diesen Inhalt ein (Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

[Service]
User=martin
Group=martin
Restart=on-failure

Restart=on-failure startet Martin neu, falls er abstürzt, z. B. weil PostgreSQL beim Hochfahren noch nicht bereit war.

21. Dienst einschalten und starten

daemon-reload liest die neue Ergänzungsdatei ein. enable --now startet Martin sofort und bei jedem Systemstart.

sudo systemctl daemon-reload
sudo systemctl enable --now martin

Prüfen: Der Dienst ist active (running). Im Journal steht für jede Tabelle eine Zeile Published source und am Ende Martin server is now active at http://127.0.0.1:3000/.

systemctl status martin --no-pager
journalctl -u martin -n 30 --no-pager

Prüfen: Der Katalog listet die vier Quellen flaechen, gebaeude, orte und strassen.

curl -s http://localhost:3000/catalog

Prüfen: Eine Kachel über der Ahrensburger Innenstadt (Zoomstufe 14) wird mit Status 200 und einigen zehn Kilobyte geliefert. Mehrere Quellen, durch Kommas getrennt, fasst Martin zu einer Kachel zusammen.

curl -s -o /dev/null -w '%{http_code} %{size_download}\n' http://localhost:3000/strassen,gebaeude,flaechen,orte/14/8657/5285

Status 204 bedeutet: Die Kachel ist gültig, enthält an dieser Stelle aber keine Daten.

Karte ansehen

22. Testseite anlegen

Eine kleine HTML-Datei holt sich über die TileJSON-Adresse http://localhost:3000/flaechen,gebaeude,strassen,orte die Kacheln und legt fest, wie jede Tabelle gezeichnet wird. source-layer ist dabei immer der Tabellenname. Martin erlaubt Zugriffe von fremden Seiten (CORS), deshalb klappt das auch mit einer lokal geöffneten Datei.

nano ~/martin-karte.html

Füge diesen Inhalt ein (Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <title>Martin – Ahrensburg</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css">
  <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js"></script>
  <style>html, body, #karte { height: 100%; margin: 0; }</style>
</head>
<body>
  <div id="karte"></div>
  <script>
    const karte = new maplibregl.Map({
      container: 'karte',
      center: [10.236, 53.675],
      zoom: 14,
      style: {
        version: 8,
        sources: {
          ahrensburg: {
            type: 'vector',
            url: 'http://localhost:3000/flaechen,gebaeude,strassen,orte',
            attribution: '&copy; OpenStreetMap-Mitwirkende'
          }
        },
        layers: [
          { id: 'hintergrund', type: 'background',
            paint: { 'background-color': '#f4f1ea' } },
          { id: 'flaechen', type: 'fill', source: 'ahrensburg', 'source-layer': 'flaechen',
            paint: { 'fill-color': ['match', ['get', 'art'],
              ['natural=water', 'water=pond', 'water=lake'], '#9cc3e6',
              ['landuse=forest', 'natural=wood'], '#a7c796',
              ['landuse=grass', 'landuse=meadow', 'leisure=park'], '#cfe5b5',
              ['landuse=residential'], '#e8e2d8',
              '#dcd8c8'] } },
          { id: 'gebaeude', type: 'fill', source: 'ahrensburg', 'source-layer': 'gebaeude',
            minzoom: 13,
            paint: { 'fill-color': '#c9b8a8', 'fill-outline-color': '#a8968a' } },
          { id: 'strassen', type: 'line', source: 'ahrensburg', 'source-layer': 'strassen',
            paint: {
              'line-color': ['match', ['get', 'art'],
                ['motorway', 'trunk', 'primary'], '#e8925a',
                ['secondary', 'tertiary'], '#f2c96b',
                '#ffffff'],
              'line-width': ['match', ['get', 'art'],
                ['motorway', 'trunk', 'primary'], 4,
                ['secondary', 'tertiary'], 3,
                ['footway', 'path', 'cycleway', 'track'], 1,
                2] } },
          { id: 'orte', type: 'circle', source: 'ahrensburg', 'source-layer': 'orte',
            minzoom: 15,
            paint: { 'circle-radius': 3, 'circle-color': '#b0406a' } }
        ]
      }
    });
    karte.addControl(new maplibregl.NavigationControl());

    // Beim Klick auf einen Punkt dessen Art und Namen anzeigen
    karte.on('click', 'orte', (e) => {
      const p = e.features[0].properties;
      new maplibregl.Popup()
        .setLngLat(e.lngLat)
        .setText(`${p.art}${p.name ? ': ' + p.name : ''}`)
        .addTo(karte);
    });
  </script>
</body>
</html>

Die Seite lädt MapLibre GL JS aus dem Netz. Es braucht also eine Internetverbindung, die Kartendaten selbst kommen aber vom eigenen Rechner.

23. Karte im Browser öffnen

xdg-open ~/martin-karte.html

Prüfen: Ahrensburg erscheint mit Flächen, Gebäuden und Straßen. Ab Zoomstufe 15 zeigen violette Punkte Geschäfte und Einrichtungen, ein Klick darauf nennt Art und Namen.

24. Übersichtsseite von Martin öffnen

Die eingebaute Oberfläche (dank web_ui aus Schritt 18) listet alle Quellen samt Feldern und hat eine einfache Vorschau.

xdg-open http://localhost:3000/

Über nginx veröffentlichen? Soll die Karte von außen erreichbar sein, bleibt Martin auf 127.0.0.1:3000, und nginx reicht einen Pfad wie /martin/ weiter. Dafür in Schritt 18 die Zeile route_prefix: '/martin' ergänzen und in nginx proxy_pass http://127.0.0.1:3000; verwenden, ohne Schrägstrich am Ende, damit /martin in der Adresse erhalten bleibt. nginx muss außerdem den Kopf Host weitergeben (proxy_set_header Host $host;), denn aus ihm baut Martin die Kachel-Adressen in den TileJSON-Antworten. Wie ein solcher Proxy grundsätzlich eingerichtet wird, zeigt nginx als Proxy vor Apache.

Installation prüfen

martin --version
systemctl is-active postgresql martin
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/health

Die letzte Zeile sollte 200 lauten.

Deinstallieren

1. Dienst stoppen und abschalten

Beendet Martin und entfernt den Autostart.

sudo systemctl disable --now martin

2. Paket entfernen

purge löscht auch /etc/martin/config.yaml.

sudo apt purge martin

3. Dienst-Ergänzung entfernen

Die Datei aus Schritt 20 gehört nicht zum Paket und bleibt sonst liegen.

sudo rm -r /etc/systemd/system/martin.service.d
sudo systemctl daemon-reload

4. Datenbank löschen

Achtung: Alle importierten Daten in osm gehen verloren. Die Datenbank gis eines anderen Tileservers bleibt unberührt.

sudo -u postgres dropdb osm

5. Datenbankrolle löschen

Geht erst, wenn der Rolle keine Datenbank mehr gehört (Schritt 4).

sudo -u postgres dropuser martin

6. Systembenutzer löschen

sudo userdel martin

7. Importregeln und Testseite löschen

/srv/osm/data bleibt stehen, falls ein anderer Tileserver die Daten noch nutzt. Sonst /srv/osm/data ebenfalls löschen.

sudo rm -r /srv/osm/martin
rm ~/martin-karte.html

Prüfen: Das Programm und der Dienst sind verschwunden.

martin --version
systemctl status martin

Beide Befehle melden einen Fehler (Kommando nicht gefunden bzw. Unit martin.service could not be found).

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Emacs

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

GNU Emacs ist ein sehr vielseitiger Texteditor. Er lässt sich mit der Sprache Emacs Lisp fast beliebig erweitern und wird zum Programmieren, für Notizen (Org-Modus) und viele andere Aufgaben genutzt.

Installation

Ubuntu bietet Emacs in mehreren Varianten an. Diese Anleitung verwendet emacs-pgtk, weil sie direkt mit Wayland zusammenarbeitet, dem Grafiksystem von Ubuntu. Schriften werden dadurch scharf dargestellt, auch bei Bildschirmskalierung. Wer nur im Terminal arbeitet (z. B. auf einem Server), nimmt stattdessen emacs-nox.

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von Emacs aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Emacs installieren

Installiert Emacs mit grafischer Oberfläche aus den offiziellen Ubuntu-Paketquellen. Die gemeinsam genutzten Dateien (z. B. Hilfe und Erweiterungen) werden automatisch mitinstalliert.

sudo apt install emacs-pgtk

Prüfen: Die erste Zeile der Ausgabe nennt die Version, z. B. GNU Emacs 30.2.

emacs --version | head -n 1

3. Emacs starten

Öffnet Emacs in einem eigenen Fenster. Alternativ findest du Emacs im Anwendungsmenü.

emacs &

Prüfen: Es öffnet sich ein Fenster mit der Begrüßungsseite von Emacs.

Soll Emacs direkt im Terminal laufen statt in einem eigenen Fenster, startest du es mit -nw:

emacs -nw

Erste Schritte

4. Die eingebaute Übung durcharbeiten

Emacs bringt eine Übung zum Mitmachen auf Deutsch mit. Sie erklärt die Grundbefehle und dauert etwa 30 Minuten. Nach dem Start fragt Emacs unten nach der Sprache: German eingeben und Enter drücken.

emacs -nw --eval '(call-interactively (quote help-with-tutorial-spec-language))'

Innerhalb von Emacs erreichst du die Übung jederzeit mit Strg+H, dann T (in der Sprache deines Systems).

5. Datei öffnen

Öffnet eine Datei zum Bearbeiten. Gibt es die Datei noch nicht, legt Emacs sie beim Speichern an.

emacs test.txt &

6. Die wichtigsten Tastenkürzel kennenlernen

Emacs verwendet eigene Tastenkürzel. In der Emacs-Hilfe steht C- für Strg und M- für Alt. C-x C-s bedeutet: Strg+X drücken, loslassen, dann Strg+S.

TastenWirkung
C-x C-fDatei öffnen
C-x C-sDatei speichern
C-x C-cEmacs beenden (fragt bei Änderungen, ob gespeichert werden soll)
C-gAktuellen Befehl abbrechen
C-/Letzte Änderung rückgängig machen
C-sText suchen, erneut C-s für den nächsten Treffer
M-%Suchen und ersetzen
C-kRest der Zeile ausschneiden
C-yAusgeschnittenen Text einfügen
C-h tÜbung öffnen

Tipp: Im Menü Options → Use CUA Keys (Cut/Paste with C-x/C-c/C-v) schaltest du die gewohnten Kürzel zum Ausschneiden, Kopieren und Einfügen ein. Mit Options → Save Options bleibt die Einstellung erhalten.

7. Systemdateien bearbeiten

Dateien unter /etc gehören root. Mit sudoedit bearbeitest du eine Kopie mit deinen normalen Rechten, beim Beenden wird sie zurückgeschrieben. Die Datei /etc/hosts dient hier nur als Beispiel.

SUDO_EDITOR="emacs -nw" sudoedit /etc/hosts

Optional: Emacs einrichten

8. Ordner für die Einstellungen anlegen

Emacs liest seine Einstellungen aus ~/.config/emacs. Der Ordner existiert anfangs nicht.

mkdir -p ~/.config/emacs

9. Einstellungsdatei anlegen

Die Datei init.el wird in Emacs Lisp geschrieben. Die Einstellungen blenden die Begrüßungsseite aus, zeigen Zeilennummern an und fügen statt eines Tabulators vier Leerzeichen ein.

nano ~/.config/emacs/init.el

Hast du die Datei schon mit eigenen Einstellungen, lösche deren alten Inhalt zuerst oder ergänze nur die fehlenden Zeilen. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

(setq inhibit-startup-screen t)
(global-display-line-numbers-mode 1)
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)

Prüfen: Beim nächsten Start von Emacs erscheint keine Begrüßungsseite, und links stehen die Zeilennummern.

emacs ~/.config/emacs/init.el &

10. Emacs als Standard-Editor festlegen

Programme wie crontab -e oder git commit lesen den gewünschten Editor aus der Umgebungsvariablen EDITOR. Dazu kommt Emacs (im Terminal-Modus) in die Datei ~/.bashrc, die bei jedem neuen Terminal gelesen wird.

nano ~/.bashrc

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile an (im Terminal mit Strg+Umschalt+V). Speichere mit Strg+O und Enter und beende nano mit Strg+X:

export EDITOR="emacs -nw"

Prüfen: Ein neues Terminal öffnen. Die Ausgabe lautet emacs -nw.

echo "$EDITOR"

Deinstallieren

1. Eintrag als Standard-Editor entfernen

Löscht die Zeile aus Schritt 10 wieder aus ~/.bashrc, falls du sie angelegt hast.

nano ~/.bashrc

Suche mit Strg+W nach EDITOR und drücke Enter. Lösche die Zeile export EDITOR="emacs -nw" mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

2. Eigene Einstellungen entfernen

Löscht die Einstellungen und alle darin installierten Erweiterungen. Die älteren Orte ~/.emacs und ~/.emacs.d werden gleich mit entfernt, falls vorhanden. Achtung: Deine Einstellungen gehen dabei verloren.

rm -rf ~/.config/emacs ~/.emacs.d ~/.emacs

3. Emacs entfernen

purge entfernt auch die Konfigurationsdateien des Pakets.

sudo apt purge emacs-pgtk

4. Nicht mehr benötigte Pakete entfernen

Entfernt die gemeinsam genutzten Emacs-Pakete (z. B. emacs-common), die nur für Emacs installiert wurden. --purge löscht dabei auch deren Konfigurationsdateien unter /etc/emacs.

sudo apt autoremove --purge

Prüfen: Der Befehl wird nicht mehr gefunden.

emacs --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

GNU nano

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

GNU nano ist ein kleiner Texteditor für das Terminal. Er eignet sich gut, um schnell Konfigurationsdateien zu bearbeiten, auch auf Servern ohne grafische Oberfläche.

Installation

Unter Ubuntu ist nano meistens schon vorinstalliert. Die folgenden Schritte schaden aber nicht: Ist nano bereits vorhanden, meldet apt das nur.

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von nano aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. nano installieren

Installiert nano aus den offiziellen Ubuntu-Paketquellen. Die Dateien für die Syntaxhervorhebung (z. B. für Shell, Python, HTML) sind im Paket enthalten.

sudo apt install nano

Prüfen: Die Versionsnummer wird angezeigt.

nano --version

Erste Schritte

3. Datei öffnen

Öffnet eine Datei zum Bearbeiten. Gibt es die Datei noch nicht, legt nano sie beim Speichern an.

nano test.txt

Prüfen: Oben steht der Dateiname, unten eine Leiste mit den wichtigsten Tastenkürzeln.

4. Die wichtigsten Tastenkürzel kennenlernen

In der unteren Leiste steht ^ für die Taste Strg und M- für die Taste Alt.

TastenWirkung
Strg+O, dann EnterDatei speichern
Strg+Xnano beenden (fragt bei Änderungen, ob gespeichert werden soll)
Strg+WText suchen
Strg+\Suchen und ersetzen
Strg+KAktuelle Zeile ausschneiden
Strg+UAusgeschnittenen Text einfügen
Alt+ULetzte Änderung rückgängig machen
Strg+_Zu einer bestimmten Zeilennummer springen
Strg+GHilfe anzeigen

5. Systemdateien bearbeiten

Dateien unter /etc gehören root. Damit du sie speichern kannst, startest du nano mit sudo. Die Datei /etc/hosts dient hier nur als Beispiel.

sudo nano /etc/hosts

Prüfen: Unten erscheint beim Speichern keine Meldung wie „Keine Berechtigung“.

Optional: nano einrichten

6. Eigene Einstellungsdatei anlegen

Die Datei ~/.nanorc gilt nur für deinen Benutzer. Die Einstellungen zeigen Zeilennummern an, rücken neue Zeilen automatisch ein und fügen statt eines Tabulators vier Leerzeichen ein.

nano ~/.nanorc

Hast du die Datei schon mit eigenen Einstellungen, lösche deren alten Inhalt zuerst oder ergänze nur die fehlenden Zeilen. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

set linenumbers
set autoindent
set tabsize 4
set tabstospaces

Prüfen: Beim nächsten Start von nano stehen links die Zeilennummern.

nano ~/.nanorc

7. nano als Standard-Editor festlegen

Programme wie crontab -e oder git commit öffnen den eingestellten Standard-Editor. Mit diesem Befehl wählst du aus einer Liste den Editor aus, der systemweit verwendet wird. Gib die Nummer ein, die vor /bin/nano steht.

sudo update-alternatives --config editor

Prüfen: Die Ausgabe zeigt als Link /bin/nano.

update-alternatives --query editor | grep Value

Deinstallieren

1. Eigene Einstellungen entfernen

Löscht die persönliche Einstellungsdatei, falls du sie in Schritt 6 angelegt hast.

rm -f ~/.nanorc

2. nano entfernen

purge entfernt auch die systemweite Einstellungsdatei /etc/nanorc. Hinweis: Ist nano dein Standard-Editor, stellt Ubuntu automatisch auf einen anderen installierten Editor um.

sudo apt purge nano

3. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für nano installiert wurden.

sudo apt autoremove

Prüfen: Der Befehl wird nicht mehr gefunden.

nano --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Vim

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Vim ist ein sehr leistungsfähiger Texteditor für das Terminal. Er wird komplett über die Tastatur bedient und eignet sich besonders zum Programmieren und für längere Arbeit an Textdateien.

Installation

Ubuntu bringt meist nur vim-tiny mit, eine stark abgespeckte Variante ohne Syntaxhervorhebung. Das Paket vim enthält die vollständige Version.

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von Vim aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Vim installieren

Installiert die vollständige Terminal-Version von Vim aus den offiziellen Ubuntu-Paketquellen.

sudo apt install vim

Prüfen: Die erste Zeile der Ausgabe nennt die Version, z. B. VIM - Vi IMproved 9.1.

vim --version | head -n 1

3. Optional: Version mit Zwischenablage installieren

Die normale Terminal-Version kann nicht auf die Zwischenablage des Desktops zugreifen. Wenn du Text zwischen Vim und anderen Programmen kopieren willst, installierst du stattdessen vim-gtk3. Das Paket bringt zusätzlich die grafische Oberfläche gvim mit.

sudo apt install vim-gtk3

Prüfen: In der Ausgabe steht +clipboard (mit Pluszeichen).

vim --version | grep -o '[+-]clipboard'

Erste Schritte

4. Die eingebaute Übung durcharbeiten

vimtutor öffnet eine Übungsdatei, in der du die Grundlagen direkt ausprobierst. Das dauert etwa 30 Minuten und ist der beste Einstieg, weil Vim anders funktioniert als die meisten Editoren.

vimtutor de

5. Datei öffnen

Öffnet eine Datei zum Bearbeiten. Gibt es die Datei noch nicht, legt Vim sie beim Speichern an.

vim test.txt

Prüfen: Unten links steht der Dateiname.

6. Die Modi verstehen

Vim startet im Normalmodus. Dort lösen Tasten Befehle aus, statt Text zu schreiben. Zum Tippen wechselst du in den Einfügemodus.

TastenWirkung
iIn den Einfügemodus wechseln (unten steht -- EINFÜGEN --)
EscZurück in den Normalmodus
:w + EnterDatei speichern
:q + EnterVim beenden
:wq + EnterSpeichern und beenden
:q! + EnterBeenden, ohne zu speichern
uLetzte Änderung rückgängig machen
ddAktuelle Zeile ausschneiden
pAusgeschnittenen Text einfügen
/wort + EnterNach „wort“ suchen, mit n zum nächsten Treffer
:help + EnterHilfe anzeigen

Die Befehle mit Doppelpunkt funktionieren nur im Normalmodus. Drücke im Zweifel vorher Esc.

7. Systemdateien bearbeiten

Dateien unter /etc gehören root. Mit sudoedit bearbeitest du eine Kopie mit deinen normalen Rechten, beim Beenden wird sie zurückgeschrieben. Das ist sicherer, als Vim komplett mit sudo zu starten. Die Datei /etc/hosts dient hier nur als Beispiel.

SUDO_EDITOR=vim sudoedit /etc/hosts

Optional: Vim einrichten

8. Eigene Einstellungsdatei anlegen

Die Datei ~/.vimrc gilt nur für deinen Benutzer. Die Einstellungen schalten Syntaxhervorhebung und Zeilennummern ein, rücken automatisch ein und fügen statt eines Tabulators vier Leerzeichen ein.

nano ~/.vimrc

Hast du die Datei schon mit eigenen Einstellungen, lösche deren alten Inhalt zuerst oder ergänze nur die fehlenden Zeilen. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

syntax on
filetype plugin indent on
set number
set autoindent
set tabstop=4
set shiftwidth=4
set expandtab

Prüfen: Beim nächsten Start von Vim stehen links die Zeilennummern.

vim ~/.vimrc

9. Vim als Standard-Editor festlegen

Programme wie crontab -e oder git commit öffnen den eingestellten Standard-Editor. Mit diesem Befehl wählst du aus einer Liste den Editor aus, der systemweit verwendet wird. Gib die Nummer ein, die vor /usr/bin/vim.basic steht (bzw. /usr/bin/vim.gtk3, wenn du Schritt 3 ausgeführt hast).

sudo update-alternatives --config editor

Prüfen: Die Ausgabe zeigt als Link den gewählten Vim.

update-alternatives --query editor | grep Value

Deinstallieren

1. Eigene Einstellungen entfernen

Löscht die persönliche Einstellungsdatei und den Ordner für Erweiterungen, falls vorhanden. Achtung: Selbst installierte Plugins in ~/.vim gehen verloren.

rm -rf ~/.vimrc ~/.vim

2. Vim entfernen

Entfernt die vollständige Version und, falls installiert, die Version mit Zwischenablage. vim-tiny bleibt erhalten, weil Ubuntu es als einfachen Editor mitbringt. Ist Vim dein Standard-Editor, stellt Ubuntu automatisch auf einen anderen installierten Editor um.

sudo apt purge vim vim-gtk3

3. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für Vim installiert wurden, z. B. vim-runtime.

sudo apt autoremove

Prüfen: Es wird nur noch die kleine Version gefunden, vim.basic fehlt.

ls /usr/bin/vim*

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Neovim

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Neovim ist eine Weiterentwicklung von Vim. Es wird genauso über die Tastatur bedient, lässt sich aber mit der Programmiersprache Lua einrichten und bringt moderne Funktionen für das Programmieren mit, etwa Unterstützung für Language Server (Autovervollständigung, Fehleranzeige).

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von Neovim aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Neovim installieren

Installiert Neovim aus den offiziellen Ubuntu-Paketquellen. Der Befehl zum Starten heißt nvim.

sudo apt install neovim

Prüfen: Die erste Zeile der Ausgabe nennt die Version, z. B. NVIM v0.11.6.

nvim --version | head -n 1

3. Werkzeug für die Zwischenablage installieren

Neovim greift nicht selbst auf die Zwischenablage des Desktops zu, sondern nutzt dafür ein Hilfsprogramm. Ubuntu verwendet Wayland, deshalb wird wl-clipboard gebraucht. Ohne das Paket kannst du keinen Text zwischen Neovim und anderen Programmen austauschen.

sudo apt install wl-clipboard

4. Einrichtung überprüfen

Neovim hat eine eingebaute Selbstprüfung. Sie zeigt, ob alles Nötige vorhanden ist.

nvim +checkhealth

Prüfen: Im Abschnitt vim.provider steht unter „Clipboard“ ein OK mit wl-copy. Warnungen zu Python, Ruby, Node.js oder Perl kannst du ignorieren, diese Erweiterungen werden nur von manchen Plugins gebraucht. Mit :qa + Enter verlässt du die Anzeige.

Erste Schritte

5. Die eingebaute Übung durcharbeiten

Neovim bringt eine Übung zum Mitmachen mit. Sie ist nur auf Englisch verfügbar. Wer die deutsche Fassung möchte, kann stattdessen vimtutor de aus der Vim-Anleitung nutzen, die Grundbefehle sind gleich.

nvim +Tutor

6. Datei öffnen

Öffnet eine Datei zum Bearbeiten. Gibt es die Datei noch nicht, legt Neovim sie beim Speichern an.

nvim test.txt

7. Die wichtigsten Befehle kennenlernen

Wie Vim startet Neovim im Normalmodus, in dem Tasten Befehle auslösen. Zum Tippen wechselst du in den Einfügemodus.

TastenWirkung
iIn den Einfügemodus wechseln (unten steht -- EINFÜGEN --)
EscZurück in den Normalmodus
:w + EnterDatei speichern
:q + EnterNeovim beenden
:wq + EnterSpeichern und beenden
:q! + EnterBeenden, ohne zu speichern
uLetzte Änderung rückgängig machen
ddAktuelle Zeile ausschneiden
pAusgeschnittenen Text einfügen
"+yMarkierten Text in die Zwischenablage des Desktops kopieren
"+pText aus der Zwischenablage des Desktops einfügen
/wort + EnterNach „wort“ suchen, mit n zum nächsten Treffer
:help + EnterHilfe anzeigen

8. Systemdateien bearbeiten

Dateien unter /etc gehören root. Mit sudoedit bearbeitest du eine Kopie mit deinen normalen Rechten, beim Beenden wird sie zurückgeschrieben. So bleiben auch deine eigenen Neovim-Einstellungen aktiv. Die Datei /etc/hosts dient hier nur als Beispiel.

SUDO_EDITOR=nvim sudoedit /etc/hosts

Optional: Neovim einrichten

Neovim hat bereits sinnvolle Grundeinstellungen, etwa Syntaxhervorhebung und automatisches Einrücken. Eine eigene Einstellungsdatei brauchst du nur für persönliche Anpassungen.

9. Ordner für die Einstellungen anlegen

Neovim liest seine Einstellungen aus ~/.config/nvim. Der Ordner existiert anfangs nicht.

mkdir -p ~/.config/nvim

10. Einstellungsdatei anlegen

Die Datei init.lua wird in Lua geschrieben. Die Einstellungen zeigen Zeilennummern an, fügen statt eines Tabulators vier Leerzeichen ein und verbinden die normalen Kopierbefehle direkt mit der Zwischenablage des Desktops (dann ist "+ nicht mehr nötig).

nano ~/.config/nvim/init.lua

Hast du die Datei schon mit eigenen Einstellungen, lösche deren alten Inhalt zuerst oder ergänze nur die fehlenden Zeilen. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

vim.opt.number = true
vim.opt.tabstop = 4
vim.opt.shiftwidth = 4
vim.opt.expandtab = true
vim.opt.clipboard = "unnamedplus"

Prüfen: Beim nächsten Start von Neovim stehen links die Zeilennummern.

nvim ~/.config/nvim/init.lua

11. Neovim als Standard-Editor festlegen

Programme wie crontab -e oder git commit öffnen den eingestellten Standard-Editor. Mit diesem Befehl wählst du aus einer Liste den Editor aus, der systemweit verwendet wird. Gib die Nummer ein, die vor /usr/bin/nvim steht.

sudo update-alternatives --config editor

Prüfen: Die Ausgabe zeigt als Link /usr/bin/nvim.

update-alternatives --query editor | grep Value

Deinstallieren

1. Eigene Einstellungen und Daten entfernen

Neovim legt Dateien an vier Stellen ab: Einstellungen, Plugins, Verlauf bzw. Sicherungsdateien und Zwischenspeicher. Achtung: Deine Einstellungen und selbst installierten Plugins gehen dabei verloren.

rm -rf ~/.config/nvim ~/.local/share/nvim ~/.local/state/nvim ~/.cache/nvim

2. Neovim entfernen

Entfernt Neovim und das Hilfsprogramm für die Zwischenablage. Lass wl-clipboard weg, wenn andere Programme es noch brauchen. Ist Neovim dein Standard-Editor, stellt Ubuntu automatisch auf einen anderen installierten Editor um.

sudo apt purge neovim wl-clipboard

3. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für Neovim installiert wurden, z. B. neovim-runtime.

sudo apt autoremove

Prüfen: Der Befehl wird nicht mehr gefunden.

nvim --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Visual Studio Code

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Visual Studio Code (kurz VS Code) ist ein kostenloser Code-Editor von Microsoft mit grafischer Oberfläche. Er unterstützt viele Programmiersprachen und lässt sich über Erweiterungen an fast jede Aufgabe anpassen, etwa Git, Debugging oder Markdown-Vorschau.

Installation

VS Code ist nicht in den Ubuntu-Paketquellen enthalten. Diese Anleitung bindet deshalb das offizielle Paketarchiv von Microsoft ein. Der Vorteil: VS Code wird danach wie jedes andere Paket mit apt verwaltet und bei sudo apt upgrade automatisch aktualisiert. Eine Alternative über Snap steht weiter unten.

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen der Hilfsprogramme für die nächsten Schritte kennt.

sudo apt update

2. Hilfsprogramm installieren

wget lädt Dateien aus dem Internet herunter. Es ist meist schon vorhanden, dann meldet apt das nur.

sudo apt install wget

3. Schlüssel von Microsoft einrichten

Mit diesem Schlüssel prüft apt, dass die Pakete wirklich von Microsoft stammen und nicht verändert wurden. wget speichert ihn mit -O direkt im Ordner für Paketschlüssel. apt liest die Textform mit der Endung .asc ohne Umwandlung.

sudo wget -O /usr/share/keyrings/microsoft.asc https://packages.microsoft.com/keys/microsoft.asc

Prüfen: Die erste Zeile lautet -----BEGIN PGP PUBLIC KEY BLOCK-----.

head -n 1 /usr/share/keyrings/microsoft.asc

4. Paketarchiv von Microsoft eintragen

Legt eine Datei an, die apt mitteilt, wo die VS-Code-Pakete liegen und mit welchem Schlüssel sie geprüft werden.

sudo nano /etc/apt/sources.list.d/vscode.sources

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

Types: deb
URIs: https://packages.microsoft.com/repos/code
Suites: stable
Components: main
Architectures: amd64
Signed-By: /usr/share/keyrings/microsoft.asc

5. Paketlisten erneut aktualisieren

Jetzt liest apt auch das neue Paketarchiv ein.

sudo apt update

Prüfen: In der Ausgabe erscheint eine Zeile mit packages.microsoft.com/repos/code, ohne Fehlermeldung.

6. VS Code installieren

Installiert VS Code. Der Befehl zum Starten im Terminal heißt code.

sudo apt install code

Prüfen: Die erste Zeile der Ausgabe ist die Versionsnummer, z. B. 1.139.0.

code --version

Erste Schritte

7. VS Code starten

Öffnet VS Code. Alternativ findest du das Programm im Anwendungsmenü unter „Visual Studio Code“.

code

8. Deutsche Oberfläche einrichten

VS Code ist zunächst auf Englisch. Dieser Befehl installiert das offizielle deutsche Sprachpaket als Erweiterung.

code --install-extension MS-CEINTL.vscode-language-pack-de

Danach in VS Code Strg+Umschalt+P drücken, Configure Display Language eingeben, Deutsch auswählen und VS Code neu starten.

Prüfen: Die Menüs heißen jetzt „Datei“, „Bearbeiten“ usw.

9. Projektordner öffnen

VS Code arbeitet am besten mit ganzen Ordnern. Wechsle im Terminal in deinen Projektordner und öffne ihn mit code . (der Punkt steht für den aktuellen Ordner). Hier als Beispiel dieser Ordner mit den Anleitungen:

cd ~/Installieren
code .

Beim ersten Öffnen eines Ordners fragt VS Code, ob du den Autoren vertraust. Nur bei eigenen oder bekannten Projekten mit „Ja“ antworten, sonst können Erweiterungen dort Code ausführen.

10. Die wichtigsten Tastenkürzel kennenlernen

TastenWirkung
Strg+Umschalt+PBefehlspalette: jeden Befehl über seinen Namen suchen
Strg+PDatei im Projekt schnell öffnen
Strg+SDatei speichern
Strg+FIn der Datei suchen
Strg+HIn der Datei ersetzen
Strg+Umschalt+FIm ganzen Projekt suchen
Strg+ÖTerminal ein- und ausblenden
Strg+BSeitenleiste ein- und ausblenden
Strg+Umschalt+XErweiterungen anzeigen und installieren

Optional: VS Code für Git verwenden

11. VS Code als Editor für Git festlegen

Git öffnet für Commit-Nachrichten einen Editor. Mit dieser Einstellung ist das VS Code. --wait sorgt dafür, dass Git wartet, bis du den Tab mit der Nachricht schließt.

git config --global core.editor "code --wait"

Prüfen: Die Ausgabe lautet code --wait.

git config --global core.editor

Aktualisieren

VS Code wird zusammen mit den anderen Paketen aktualisiert:

sudo apt update
sudo apt upgrade

Alternative: Installation über Snap

Statt über das Paketarchiv von Microsoft lässt sich VS Code auch als Snap installieren. Snaps aktualisieren sich selbstständig im Hintergrund. --classic ist nötig, weil ein Code-Editor auf alle Dateien und Programme zugreifen muss. Nutze nur einen der beiden Wege, nicht beide gleichzeitig.

sudo snap install code --classic

Prüfen:

code --version

Deinstallieren der Snap-Version:

sudo snap remove code

Deinstallieren

1. Git-Einstellung zurücksetzen

Entfernt VS Code als Git-Editor, falls du Schritt 11 ausgeführt hast. Git nutzt danach wieder den Standard-Editor des Systems.

git config --global --unset core.editor

2. VS Code entfernen

Entfernt das Programm.

sudo apt purge code

3. Paketarchiv und Schlüssel entfernen

Ohne diese Dateien sucht apt nicht mehr bei Microsoft nach Updates. microsoft.gpg stammt aus einer älteren Fassung dieser Anleitung. -f sorgt dafür, dass rm fehlende Dateien einfach überspringt.

sudo rm -f /etc/apt/sources.list.d/vscode.sources /usr/share/keyrings/microsoft.asc /usr/share/keyrings/microsoft.gpg

4. Paketlisten aktualisieren

Damit apt das entfernte Paketarchiv auch aus seinen Listen streicht.

sudo apt update

5. Eigene Einstellungen und Erweiterungen entfernen

VS Code speichert Einstellungen in ~/.config/Code und Erweiterungen in ~/.vscode. Achtung: Deine Einstellungen und alle installierten Erweiterungen gehen dabei verloren.

rm -rf ~/.config/Code ~/.vscode

Prüfen: Der Befehl wird nicht mehr gefunden.

code --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

IntelliJ IDEA

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

IntelliJ IDEA ist eine Entwicklungsumgebung (IDE) von JetBrains, vor allem für Java und Kotlin. Sie bietet intelligente Codevervollständigung, Refactoring, einen Debugger und eingebaute Unterstützung für Maven, Gradle und Git.

Vorbemerkungen

  • Eine Version für alle: IntelliJ IDEA gibt es seit Version 2025.3 nur noch als ein gemeinsames Produkt. Die frühere „Community Edition“ ist darin aufgegangen: Ihr Funktionsumfang bleibt kostenlos, auch für kommerzielle Projekte. Weitere Funktionen (früher „Ultimate“) erfordern ein Abo, das 30 Tage kostenlos getestet werden kann.
  • Kein apt-Paket: In den Ubuntu-Paketquellen gibt es Pakete wie libintellij-platform-api-java. Das sind nur Programmbibliotheken aus der IntelliJ-Plattform, auf der alle JetBrains-IDEs aufbauen, nicht die IDE selbst. Diese Anleitung installiert IntelliJ IDEA deshalb als Snap. Das Snap wird von JetBrains selbst veröffentlicht.
  • Speicherplatz: Das Snap ist knapp 2 GB groß.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version des Java-Entwicklungspakets im nächsten Schritt kennt.

sudo apt update

2. Java-Entwicklungspaket (JDK) installieren

IntelliJ IDEA bringt für sich selbst eine eigene Java-Laufzeit mit. Um eigene Java-Programme zu übersetzen und auszuführen, brauchst du aber ein JDK. default-jdk installiert die aktuelle Java-Version mit Langzeitunterstützung aus den Ubuntu-Paketquellen (derzeit Java 25).

sudo apt install default-jdk

Prüfen: Die Ausgabe nennt die Java-Version, z. B. javac 25.

javac -version

3. IntelliJ IDEA installieren

Installiert IntelliJ IDEA als Snap. --classic ist nötig, weil eine IDE uneingeschränkt auf deine Dateien, das JDK und andere Programme zugreifen muss.

sudo snap install intellij-idea --classic

Prüfen: Die Ausgabe zeigt Name, Version (z. B. 2026.2.3) und als Herausgeber jetbrains.

snap list intellij-idea

Erste Schritte

4. IntelliJ IDEA starten

Öffne das Anwendungsmenü und starte IntelliJ IDEA. Beim ersten Start fragt das Programm nach den Nutzungsbedingungen und ob anonyme Nutzungsdaten gesendet werden dürfen. Das Senden kannst du ablehnen.

Prüfen: Es erscheint der Willkommensbildschirm mit den Schaltflächen New Project und Open.

5. Kostenlose Nutzung wählen

Wenn IntelliJ IDEA nach einer Lizenz fragt, wähle die kostenlose Nutzung (nicht die Testversion des Abos). Damit stehen alle Grundfunktionen dauerhaft zur Verfügung. Das Abo kannst du später jederzeit über Help → Register freischalten.

6. Deutsche Oberfläche einrichten

Die Oberfläche ist zunächst auf Englisch. Öffne im Willkommensbildschirm Customize → Language (oder in einem Projekt File → Settings → Appearance & Behavior → System Settings → Language and Region), wähle Deutsch und starte IntelliJ IDEA neu. Fehlt Deutsch in der Liste, installiere zuerst unter Plugins das Sprachpaket „German Language Pack“.

7. Erstes Projekt anlegen

Klicke auf New Project. Wähle als Sprache Java und als Build-System Maven oder Gradle. Unter JDK sollte das in Schritt 2 installierte JDK erscheinen (Pfad /usr/lib/jvm/...). Mit Create wird das Projekt angelegt.

Prüfen: Öffne die Datei Main.java und klicke auf den grünen Pfeil neben main. Unten im Ausführungsfenster erscheint die Ausgabe des Programms.

8. Die wichtigsten Tastenkürzel kennenlernen

TastenWirkung
2 × UmschaltÜberall suchen: Dateien, Klassen, Aktionen, Einstellungen
Strg+Umschalt+AAktion über ihren Namen suchen
Alt+EnterLösungsvorschläge für die markierte Stelle anzeigen
Strg+LeertasteCodevervollständigung
Umschalt+F10Programm ausführen
Umschalt+F9Programm im Debugger ausführen
Strg+Alt+LCode formatieren
Umschalt+F6Umbenennen (überall im Projekt)
Alt+F12Terminal ein- und ausblenden

Hinweis: Strg+Alt+L sperrt unter Ubuntu eventuell den Bildschirm, bevor IntelliJ IDEA die Tasten erhält. In diesem Fall formatierst du den Code über Code → Reformat Code.

Optional: Mehr Dateien überwachen

9. Grenze für Dateiüberwachung erhöhen

IntelliJ IDEA lässt sich vom System melden, wenn sich Dateien im Projekt ändern. Bei großen Projekten reicht die Voreinstellung von Ubuntu dafür nicht aus, dann erscheint ein Hinweis „External file changes sync might be slow“. Nur in diesem Fall ist der Schritt nötig. Die Datei unter /etc/sysctl.d hebt die Grenze dauerhaft an.

sudo nano /etc/sysctl.d/60-jetbrains.conf

Die Datei ist neu und leer. Füge diese Zeile ein, speichere mit Strg+O und Enter und beende nano mit Strg+X:

fs.inotify.max_user_watches = 524288

10. Neue Grenze sofort übernehmen

Lädt die Einstellungen neu, damit du nicht neu starten musst. Danach IntelliJ IDEA neu starten.

sudo sysctl --system

Prüfen: Die Ausgabe lautet 524288.

cat /proc/sys/fs/inotify/max_user_watches

Aktualisieren

Snaps aktualisieren sich automatisch im Hintergrund. Sofort aktualisieren kannst du mit:

sudo snap refresh intellij-idea

Deinstallieren

1. IntelliJ IDEA entfernen

Entfernt das Snap. --purge verhindert, dass Snap vorher eine Sicherungskopie der Snap-Daten anlegt.

sudo snap remove --purge intellij-idea

2. Einstellungen, Plugins und Zwischenspeicher entfernen

IntelliJ IDEA speichert seine Daten in Ordnern, deren Name mit IntelliJIdea beginnt, gefolgt von der Version. Ordner anderer JetBrains-Programme (z. B. der Toolbox) bleiben erhalten. Achtung: Deine IDE-Einstellungen und installierten Plugins gehen verloren. Deine Projekte selbst werden nicht gelöscht.

rm -rf ~/.config/JetBrains/IntelliJIdea* ~/.cache/JetBrains/IntelliJIdea* ~/.local/share/JetBrains/IntelliJIdea*

3. Einstellung zur Dateiüberwachung entfernen

Nur nötig, wenn du Schritt 9 ausgeführt hast. Die höhere Grenze gilt dann ab dem nächsten Neustart nicht mehr.

sudo rm /etc/sysctl.d/60-jetbrains.conf

4. Optional: JDK entfernen

Nur ausführen, wenn kein anderes Programm Java braucht.

sudo apt purge default-jdk
sudo apt autoremove

Prüfen: Die Ausgabe meldet, dass kein Snap namens intellij-idea installiert ist.

snap list intellij-idea

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Eclipse IDE

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Eclipse ist eine kostenlose, quelloffene Entwicklungsumgebung (IDE), die vor allem für Java genutzt wird. Über Erweiterungen (Plugins) lässt sie sich auch für viele andere Sprachen und Aufgaben einsetzen, etwa C/C++, PHP oder Webentwicklung.

Vorbemerkungen

  • Kein apt-Paket: Eclipse ist in den aktuellen Ubuntu-Paketquellen nicht enthalten. Diese Anleitung installiert Eclipse deshalb als Snap. Das Snap wird von der Eclipse Foundation selbst veröffentlicht und enthält die Variante „Eclipse IDE for Java Developers“.
  • Versionsnamen: Eclipse erscheint viermal im Jahr. Die Versionen heißen nach Jahr und Monat, z. B. 2026-09.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version des Java-Entwicklungspakets im nächsten Schritt kennt.

sudo apt update

2. Java-Entwicklungspaket (JDK) installieren

Eclipse braucht ein JDK, um deine Java-Programme zu übersetzen und auszuführen. default-jdk installiert die aktuelle Java-Version mit Langzeitunterstützung aus den Ubuntu-Paketquellen (derzeit Java 25). Ist es schon vorhanden (z. B. aus der IntelliJ-IDEA-Anleitung), meldet apt das nur.

sudo apt install default-jdk

Prüfen: Die Ausgabe nennt die Java-Version, z. B. javac 25.

javac -version

3. Eclipse installieren

Installiert Eclipse als Snap. --classic ist nötig, weil eine IDE uneingeschränkt auf deine Dateien, das JDK und andere Programme zugreifen muss.

sudo snap install eclipse --classic

Prüfen: Die Ausgabe zeigt Name, Version (z. B. 2026-09) und als Herausgeber eclipsefoundation.

snap list eclipse

Erste Schritte

4. Eclipse starten

Startet Eclipse. Alternativ findest du das Programm im Anwendungsmenü unter „Eclipse“.

eclipse &

5. Arbeitsbereich (Workspace) festlegen

Beim Start fragt Eclipse nach einem Ordner für den Workspace. Darin liegen deine Projekte und die Einstellungen, die nur für diesen Arbeitsbereich gelten. Der Vorschlag ~/eclipse-workspace ist in Ordnung. Setze einen Haken bei Use this as the default and do not ask again, wenn die Frage nicht bei jedem Start erscheinen soll, und klicke auf Launch.

Prüfen: Es erscheint die Willkommensseite von Eclipse. Sie lässt sich über das × auf ihrem Reiter schließen.

6. JDK in Eclipse auswählen

Damit Eclipse das in Schritt 2 installierte JDK verwendet. Öffne Window → Preferences → Java → Installed JREs. Klicke auf Search…, wähle den Ordner /usr/lib/jvm und bestätige. Setze anschließend den Haken beim gefundenen Eintrag (z. B. java-25-openjdk-amd64) und klicke auf Apply and Close.

7. Erstes Projekt anlegen

Wähle File → New → Java Project, gib einen Projektnamen ein (z. B. Hallo) und klicke auf Finish. Lege danach mit einem Rechtsklick auf den Ordner src → New → Class eine Klasse Main an und setze dabei den Haken bei public static void main(String[] args). Schreibe in die main-Methode:

System.out.println("Hallo Eclipse");

Prüfen: Mit Strg+F11 startest du das Programm. Unten im Fenster Console erscheint Hallo Eclipse.

8. Die wichtigsten Tastenkürzel kennenlernen

TastenWirkung
Strg+3Schnellzugriff: Befehle, Ansichten und Einstellungen über ihren Namen suchen
Strg+LeertasteCodevervollständigung
Strg+1Lösungsvorschläge für die markierte Stelle anzeigen
Strg+Umschalt+RDatei im Workspace schnell öffnen
Strg+Umschalt+TJava-Klasse schnell öffnen
Strg+Umschalt+FCode formatieren
Strg+Umschalt+OImports aufräumen
Alt+Umschalt+RUmbenennen (überall im Projekt)
Strg+F11Programm ausführen
F11Programm im Debugger ausführen

Optional: Deutsche Oberfläche

Eclipse selbst ist nur auf Englisch. Deutsche Übersetzungen liefert das Projekt Eclipse Babel als Erweiterung. Die Übersetzung ist allerdings nicht vollständig, einige Menüs und Meldungen bleiben englisch.

9. Sprachpaket installieren

Öffne Help → Install New Software…. Trage bei Work with die folgende Adresse ein und drücke Enter:

https://download.eclipse.org/technology/babel/update-site/latest/

Klappe in der Liste den Eintrag Babel Language Packs in German auf, setze den Haken bei Babel Language Pack for eclipse in German und klicke auf Next, dann Finish. Eclipse fragt nach dem Vertrauen in die Quelle und die Lizenz: beides bestätigen. Zum Schluss Eclipse neu starten.

Prüfen: Das Menü File heißt jetzt Datei.

Aktualisieren

Snaps aktualisieren sich automatisch im Hintergrund. Sofort aktualisieren kannst du mit:

sudo snap refresh eclipse

Deinstallieren

1. Eclipse entfernen

Entfernt das Snap. --purge verhindert, dass Snap vorher eine Sicherungskopie der Snap-Daten anlegt.

sudo snap remove --purge eclipse

2. Einstellungen und installierte Erweiterungen entfernen

Eclipse speichert programmweite Einstellungen und nachinstallierte Erweiterungen (z. B. das Sprachpaket) in ~/.eclipse und ~/snap/eclipse.

rm -rf ~/.eclipse ~/snap/eclipse

3. Optional: Workspace entfernen

Achtung: Der Workspace enthält deine Projekte. Nur löschen, wenn du sie nicht mehr brauchst oder vorher gesichert hast.

rm -rf ~/eclipse-workspace

4. Optional: JDK entfernen

Nur ausführen, wenn kein anderes Programm (z. B. IntelliJ IDEA) Java braucht.

sudo apt purge default-jdk
sudo apt autoremove

Prüfen: Die Ausgabe meldet, dass kein Snap namens eclipse installiert ist.

snap list eclipse

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Microsoft Visual Studio

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Microsoft Visual Studio ist eine umfangreiche Entwicklungsumgebung von Microsoft, vor allem für C#, .NET und C++. Diese Seite erklärt, warum sie unter Ubuntu nicht installiert werden kann, und richtet stattdessen eine gleichwertige Arbeitsumgebung für C# und .NET ein.

Vorbemerkungen

  • Nur für Windows: Visual Studio (2022 und neuer) gibt es ausschließlich für Windows. Die Mac-Version hat Microsoft im August 2024 eingestellt, eine Linux-Version gab es nie. Auch mit Wine lässt sich Visual Studio nicht sinnvoll betreiben.
  • Nicht verwechseln: Visual Studio Code ist ein anderes, deutlich schlankeres Programm. Es läuft unter Ubuntu und ist die von Microsoft empfohlene Lösung für .NET-Entwicklung unter Linux.
  • Der Ersatz: Diese Anleitung installiert das .NET SDK aus den Ubuntu-Paketquellen und die Erweiterung C# Dev Kit für VS Code. Damit stehen Projektverwaltung, Codevervollständigung, Debugger und Testausführung ähnlich wie in Visual Studio zur Verfügung.
  • Lizenz des C# Dev Kit: Für Privatpersonen, Ausbildung und Open-Source-Projekte kostenlos. Für die Arbeit in Unternehmen gelten dieselben Bedingungen wie bei Visual Studio Community, größere Firmen brauchen also ein Visual-Studio-Abo.
  • Voraussetzung: VS Code ist installiert, siehe Anleitung Visual Studio Code.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version des .NET SDK aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. .NET SDK installieren

Das SDK enthält den C#-Compiler, die Laufzeitumgebung und den Befehl dotnet, mit dem Projekte angelegt, gebaut und gestartet werden. Ubuntu stellt die aktuelle Version mit Langzeitunterstützung (.NET 10) selbst bereit, ein Paketarchiv von Microsoft ist nicht nötig.

sudo apt install dotnet-sdk-10.0

Prüfen: Die Ausgabe ist eine Versionsnummer, die mit 10.0 beginnt.

dotnet --version

3. C# Dev Kit in VS Code installieren

Installiert die Erweiterung, die VS Code um die Visual-Studio-ähnlichen Funktionen für C# ergänzt. Die benötigte Grunderweiterung C# wird automatisch mitinstalliert.

code --install-extension ms-dotnettools.csdevkit

Prüfen: In der Liste erscheinen ms-dotnettools.csdevkit und ms-dotnettools.csharp.

code --list-extensions | grep ms-dotnettools

Erste Schritte

4. Testprojekt anlegen

Legt im Home-Verzeichnis ein kleines Konsolenprogramm im Ordner HalloDotnet an. Beim ersten Aufruf von dotnet erscheint einmalig ein Begrüßungstext.

dotnet new console -o ~/HalloDotnet

5. Testprojekt ausführen

Übersetzt das Programm und startet es. So siehst du, dass das SDK funktioniert.

dotnet run --project ~/HalloDotnet

Prüfen: Die Ausgabe lautet Hello, World!.

6. Projekt in VS Code öffnen

Öffnet den Projektordner in VS Code. Das C# Dev Kit erkennt das Projekt automatisch.

code ~/HalloDotnet

Beim ersten Öffnen fragt VS Code, ob du den Autoren des Ordners vertraust: mit „Ja“ bestätigen. Das C# Dev Kit bittet eventuell um eine Anmeldung mit einem Microsoft-Konto. Für die private Nutzung ist das nicht nötig, die Meldung kann geschlossen werden.

Prüfen: Links in der Seitenleiste erscheint der Bereich Projektmappen-Explorer (bzw. Solution Explorer) mit dem Projekt HalloDotnet.

7. Programm im Debugger starten

Öffne die Datei Program.cs, klicke links neben die Zeilennummer der Zeile mit Console.WriteLine, um einen Haltepunkt (roter Punkt) zu setzen, und drücke F5. Wählt VS Code nach einem Debugger, nimm C#.

Prüfen: Das Programm hält am Haltepunkt an, die Zeile ist gelb hinterlegt. Mit F5 läuft es weiter.

8. Die wichtigsten Tastenkürzel für C# kennenlernen

TastenWirkung
F5Programm im Debugger starten bzw. fortsetzen
Strg+F5Programm ohne Debugger starten
F9Haltepunkt setzen oder entfernen
F10 / F11Im Debugger: nächste Zeile / in Methode hineinspringen
F12Zur Definition springen
Strg+.Lösungsvorschläge für die markierte Stelle anzeigen
F2Umbenennen (überall im Projekt)
Strg+Umschalt+BProjekt bauen

Weitere Alternativen

  • JetBrains Rider: Eine vollwertige .NET-IDE, die Visual Studio in Aufbau und Umfang am nächsten kommt. Für nicht-kommerzielle Nutzung kostenlos, als Snap rider verfügbar.
  • Windows in einer virtuellen Maschine: Wer zwingend Visual Studio selbst braucht (z. B. für Windows-Forms-Designer oder C++ mit MSVC), kann Windows in einer virtuellen Maschine (z. B. mit GNOME Boxes oder VirtualBox) installieren. Dafür ist eine Windows-Lizenz nötig.

Aktualisieren

Das .NET SDK wird mit den anderen Paketen aktualisiert:

sudo apt update
sudo apt upgrade

Erweiterungen in VS Code aktualisieren sich automatisch.

Deinstallieren

1. C#-Erweiterungen entfernen

Entfernt das C# Dev Kit aus VS Code.

code --uninstall-extension ms-dotnettools.csdevkit

Entfernt die Grunderweiterung C#, die mitinstalliert wurde.

code --uninstall-extension ms-dotnettools.csharp

2. Hilfserweiterung entfernen

Das C# Dev Kit hat zusätzlich eine Hilfserweiterung installiert, die .NET-Laufzeiten für VS Code verwaltet.

code --uninstall-extension ms-dotnettools.vscode-dotnet-runtime

Prüfen: Die Ausgabe ist leer.

code --list-extensions | grep ms-dotnettools

3. .NET SDK entfernen

purge entfernt auch die Konfigurationsdateien des Pakets.

sudo apt purge dotnet-sdk-10.0

4. Nicht mehr benötigte Pakete entfernen

Entfernt Laufzeitumgebung und weitere Pakete, die nur für das SDK installiert wurden.

sudo apt autoremove

5. Zwischenspeicher und Testprojekt entfernen

~/.dotnet enthält Einstellungen des dotnet-Befehls, ~/.nuget heruntergeladene Programmbibliotheken. Achtung: Der letzte Ordner ist das Testprojekt aus Schritt 4, prüfe vorher, dass du nichts Eigenes darin gespeichert hast.

rm -rf ~/.dotnet ~/.nuget ~/HalloDotnet

Prüfen: Der Befehl wird nicht mehr gefunden.

dotnet --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

mdBook

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Mit mdBook wird aus einer Sammlung von Markdown-Dateien eine Website im Buchformat, mit Kapitelverzeichnis am Rand und Volltextsuche. Auf dem Entwicklungsrechner dient es dazu, Anleitungen und technische Dokumentationen als strukturierte, durchsuchbare HTML-Webseite lokal zu bauen und im Browser zu testen.

Installation (bevorzugt über apt)

Unter Ubuntu 26.04 ist mdBook direkt in den offiziellen Paketquellen enthalten.

1. Paketlisten aktualisieren

Damit apt die aktuellen Paketdaten aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. mdBook installieren

Installiert das mdbook-Paket auf deinem System.

sudo apt install mdbook

Prüfen: Die Versionsnummer von mdBook wird angezeigt.

mdbook --version

Alternative: Installation über Rust (Cargo)

Falls du die neueste Entwicklerversion benötigst oder mdBook im Benutzerverzeichnis (~/.cargo/bin) verwalten möchtest, kannst du die Installation über den Rust-Paketmanager Cargo durchführen.

3. Cargo installieren (falls nicht vorhanden)

Installiert den Rust-Paketmanager Cargo aus den Ubuntu-Paketquellen.

sudo apt install cargo

4. mdBook über Cargo installieren

Lädt den Quellcode von crates.io herunter, kompiliert mdBook und legt die ausführbare Datei unter ~/.cargo/bin/mdbook ab.

cargo install mdbook

Prüfen: Die Version der Cargo-Installation wird angezeigt.

~/.cargo/bin/mdbook --version

Verwendung und Test

5. Neues Buchprojekt initialisieren

Erstellt einen neuen Ordner mein-buch mit der grundlegenden Konfiguration (book.toml) und der Inhaltsstruktur (src/SUMMARY.md).

mdbook init mein-buch --title "Mein Handbuch" --ignore=none

Prüfen: Der Ordner mein-buch mit book.toml und src/ wurde angelegt.

ls -la mein-buch

6. Buch bauen

Erzeugt aus den Markdown-Dateien eine statische HTML-Webseite im Verzeichnis mein-buch/book/.

mdbook build mein-buch

Prüfen: Die generierte Einstiegsseite mein-buch/book/index.html existiert.

ls -lh mein-buch/book/index.html

7. Lokalen Entwicklungsserver starten

Startet einen Webserver auf http://localhost:3000, der Änderungen an Markdown-Dateien automatisch erkennt und die Seite im Browser live neu lädt.

mdbook serve mein-buch --open

Prüfen: Im Terminal läuft der Webserver und im Browser öffnet sich das Buch. Zum Beenden drückst du im Terminal Strg + C.

Deinstallieren

Wenn über apt installiert:

1. mdBook-Paket entfernen

purge entfernt das Programm vollständig aus dem System.

sudo apt purge mdbook

2. Nicht mehr benötigte Abhängigkeiten entfernen

Entfernt eventuell verbliebene Paketabhängigkeiten.

sudo apt autoremove

Wenn über Cargo installiert:

Entfernt die Binärdatei aus ~/.cargo/bin/:

cargo uninstall mdbook

Prüfen: Der Befehl wird nicht mehr im System gefunden.

mdbook --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Antora

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Antora ist ein statischer Webseitengenerator für umfangreiche Software- und Systemdokumentationen auf Basis von AsciiDoc. Auf dem Entwicklungsrechner dient es dazu, strukturierte Dokumentationen aus einem oder mehreren Git-Repositories lokal zu einer durchsuchbaren Webseite zusammenzuführen und zu testen.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Paketdaten aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Node.js, npm und Git installieren

Antora basiert auf Node.js und setzt Git voraus, um Dokumentationsinhalte aus Repositories einzulesen.

sudo apt install -y nodejs npm git

Prüfen: Die installierte Version von Node.js wird angezeigt.

node -v

3. Antora CLI und Site Generator installieren

Installiert das Antora-Befehlszeilenwerkzeug (@antora/cli) und den Webseitengenerator (@antora/site-generator) global über den Node-Paketmanager npm.

sudo npm install -g @antora/cli @antora/site-generator

(Hinweis: Falls du Node.js über nvm im Benutzerverzeichnis verwendest, führe den Befehl ohne sudo aus).

Prüfen: Die installierten Versionsnummern von Antora werden angezeigt.

antora -v

Beispiel-Dokumentation erstellen und testen

4. Projektverzeichnis anlegen

Erstellt die von Antora erwartete Standard-Ordnerstruktur für ein Modul.

mkdir -p ~/antora-demo/docs/modules/ROOT/pages

5. Komponenten-Konfiguration anlegen

Definiert den Namen, die Versionsbezeichnung und den Titel der Dokumentationskomponente in docs/antora.yml.

nano ~/antora-demo/docs/antora.yml

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

name: handbuch
title: Entwickler-Handbuch
version: '1.0'
start_page: index.adoc
nav:
  - modules/ROOT/nav.adoc

6. Navigationsdatei anlegen

Erstellt die Navigation für die linke Seitenleiste in docs/modules/ROOT/nav.adoc.

nano ~/antora-demo/docs/modules/ROOT/nav.adoc

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

* xref:index.adoc[Startseite]

7. Startseite in AsciiDoc verfassen

Erstellt den eigentlichen Inhalt der Einstiegsseite in docs/modules/ROOT/pages/index.adoc.

nano ~/antora-demo/docs/modules/ROOT/pages/index.adoc

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

= Willkommen im Entwickler-Handbuch

Dies ist eine lokale Dokumentationsseite, die mit Antora und AsciiDoc erstellt wurde.

== Erste Schritte

* Dokumentation im AsciiDoc-Format schreiben
* Änderungen mit Git versionieren
* Mit Antora zur fertigen Webseite bauen

8. Playbook-Konfiguration anlegen

Das Playbook antora-playbook.yml steuert den Bauprozess, bindet Inhaltsquellen ein und legt das Standard-Design fest.

nano ~/antora-demo/antora-playbook.yml

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

site:
  title: Mein Dokumentationsportal
  start_page: handbuch::index.adoc
content:
  sources:
    - url: .
      branches: HEAD
      start_path: docs
ui:
  bundle:
    url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable
    snapshot: true

9. Git-Repository initialisieren

Antora liest Dokumentationsstände standardmäßig aus Git-Zweigen (Branches).

git -C ~/antora-demo init

10. Dokumentationsdateien zum Git-Index hinzufügen

Nimmt alle erstellten Konfigurations- und Inhaltsdateien in die Versionsverwaltung auf.

git -C ~/antora-demo add .

11. Git-Commit erstellen

Erstellt den ersten Revisionsstand im Repository.

git -C ~/antora-demo commit -m "Initiale Dokumentation"

12. Dokumentationsseite bauen

Startet die Generierung der statischen HTML-Webseite über Antora. Die Ausgabe landet standardmäßig in build/site/.

antora ~/antora-demo/antora-playbook.yml

Prüfen: Die Startdatei build/site/index.html wurde erfolgreich erzeugt.

ls -lh ~/antora-demo/build/site/index.html

13. Dokumentation im Browser ansehen

Öffnet die generierte Dokumentationsseite direkt in deinem Standard-Webbrowser.

xdg-open ~/antora-demo/build/site/index.html

Deinstallieren

1. Antora-Pakete entfernen

Deinstalliert Antora CLI und den Site Generator aus npm.

sudo npm uninstall -g @antora/cli @antora/site-generator

2. Node.js und npm entfernen (optional)

Falls Node.js und npm über apt installiert wurden und nicht mehr benötigt werden.

sudo apt purge nodejs npm

3. Nicht mehr benötigte Abhängigkeiten entfernen

Entfernt verbliebene Hilfspakete aus dem System.

sudo apt autoremove

4. Testprojekt löschen (optional)

Entfernt das erstellte Testverzeichnis.

rm -rf ~/antora-demo

Prüfen: Der Befehl antora ist nicht mehr vorhanden.

antora -v

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Sphinx

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Sphinx ist ein Werkzeug, mit dem man aus einfachen Textdateien eine Dokumentation als Webseite, PDF oder E-Book erzeugt. Es wird vor allem für Software-Dokumentation eingesetzt, etwa die von Python selbst, und kann Dokumentation direkt aus Python-Quellcode übernehmen.

Vorbemerkungen

  • Textformate: Sphinx verwendet standardmäßig reStructuredText (Dateiendung .rst). Mit der Erweiterung MyST lassen sich Seiten auch in Markdown (.md) schreiben. Diese Anleitung richtet beides ein.
  • Installation über apt: Sphinx und die hier genutzten Erweiterungen sind in den Ubuntu-Paketquellen enthalten. Eine Installation mit pip ist nicht nötig.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von Sphinx aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Sphinx installieren

Installiert Sphinx mit den Befehlen sphinx-quickstart (neues Projekt anlegen) und sphinx-build (Dokumentation bauen).

sudo apt install python3-sphinx

Prüfen: Die Ausgabe nennt die Version, z. B. sphinx-build 8.2.3.

sphinx-build --version

3. Zusatzpakete installieren

Diese drei Pakete sind optional, werden aber im weiteren Verlauf verwendet:

  • python3-sphinx-rtd-theme – ein verbreitetes, übersichtliches Aussehen mit Navigationsleiste („Read the Docs“-Design)
  • python3-myst-parser – erlaubt Seiten in Markdown
  • python3-sphinx-autobuild – baut die Dokumentation bei jeder Änderung neu und zeigt sie sofort im Browser an
sudo apt install python3-sphinx-rtd-theme python3-myst-parser python3-sphinx-autobuild

Prüfen: Der Befehl zeigt seine Version an.

sphinx-autobuild --version

Erstes Projekt

4. Projektordner anlegen

Ein eigener Ordner für die Dokumentation. Hier als Beispiel ~/sphinx-test.

mkdir ~/sphinx-test

5. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/sphinx-test

6. Projekt anlegen

sphinx-quickstart erzeugt das Grundgerüst. Ohne Zusatzangaben stellt es Fragen im Terminal. Mit den folgenden Angaben läuft es ohne Rückfragen durch:

  • --sep trennt Quelltexte (Ordner source) und fertige Ausgabe (Ordner build)
  • -p Name des Projekts, -a Name des Autors
  • -l de stellt die Sprache auf Deutsch, damit Texte wie „Suche“ oder „Inhalt“ deutsch erscheinen
sphinx-quickstart --quiet --sep -p "Meine Dokumentation" -a "Dein Name" -l de

Prüfen: Im Ordner source liegen die Dateien conf.py (Einstellungen) und index.rst (Startseite).

ls source

7. Dokumentation zum ersten Mal bauen

Erzeugt aus den Quelltexten in source eine Webseite im Ordner build/html.

sphinx-build -M html source build

Prüfen: Die Ausgabe endet mit The HTML pages are in build/html.. Die Startseite öffnest du mit:

xdg-open build/html/index.html

sphinx-quickstart legt außerdem ein Makefile an. Ist das Paket make installiert, bewirkt make html dasselbe wie der Befehl oben.

Optional: Design und Markdown einrichten

8. Read-the-Docs-Design einschalten

Ersetzt in conf.py das Standard-Design alabaster durch das in Schritt 3 installierte Design.

nano source/conf.py

Suche mit Strg+W nach html_theme und drücke Enter. Die Zeile lautet html_theme = 'alabaster'. Ändere die gefundene Zeile so, dass sie lautet:

html_theme = 'sphinx_rtd_theme'

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Ausgabe lautet html_theme = 'sphinx_rtd_theme'.

grep '^html_theme' source/conf.py

9. Markdown-Unterstützung einschalten

Trägt die Erweiterung MyST in die (anfangs leere) Liste extensions in conf.py ein. Danach erkennt Sphinx neben .rst- auch .md-Dateien.

nano source/conf.py

Suche mit Strg+W nach extensions und drücke Enter. Die Zeile lautet extensions = []. Ändere die gefundene Zeile so, dass sie lautet:

extensions = ['myst_parser']

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Ausgabe lautet extensions = ['myst_parser'].

grep '^extensions' source/conf.py

10. Eine Seite in Markdown anlegen

Legt eine neue Seite erste-seite.md an. Die Überschrift mit # wird zum Seitentitel.

nano source/erste-seite.md

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Erste Seite

Diese Seite ist in **Markdown** geschrieben.

## Ein Codebeispiel

```python
print("Hallo Sphinx")
```

11. Seite ins Inhaltsverzeichnis aufnehmen

Sphinx zeigt nur Seiten an, die in einem Inhaltsverzeichnis (toctree) stehen. Öffne die Startseite in einem Editor:

nano source/index.rst

Suche den Block, der mit .. toctree:: beginnt. Füge nach den Zeilen, die mit : beginnen (die Beschriftung Contents: darfst du auch in Inhalt: ändern), eine Leerzeile und dann den Seitennamen ohne Dateiendung ein. Er muss genauso weit eingerückt sein wie die Zeilen darüber (drei Leerzeichen):

.. toctree::
   :maxdepth: 2
   :caption: Contents:

   erste-seite

Speichern mit Strg+O, Enter, beenden mit Strg+X.

12. Mit automatischer Vorschau arbeiten

sphinx-autobuild baut die Dokumentation und startet einen kleinen Webserver. Bei jeder gespeicherten Änderung wird neu gebaut und der Browser lädt die Seite von selbst neu.

sphinx-autobuild source build/html

Prüfen: Öffne http://127.0.0.1:8000 im Browser. Die Seite hat die Navigationsleiste des Read-the-Docs-Designs, und links steht der Eintrag „Erste Seite“. Mit Strg+C im Terminal beendest du die Vorschau.

Deinstallieren

1. Testprojekt entfernen

Löscht den Beispielordner aus Schritt 4. Achtung: Alles in ~/sphinx-test geht verloren.

rm -rf ~/sphinx-test

2. Sphinx und Zusatzpakete entfernen

purge entfernt auch die Konfigurationsdateien der Pakete.

sudo apt purge python3-sphinx python3-sphinx-rtd-theme python3-myst-parser python3-sphinx-autobuild

3. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für Sphinx installiert wurden, z. B. python3-docutils und das Design alabaster.

sudo apt autoremove

Prüfen: Der Befehl wird nicht mehr gefunden.

sphinx-build --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

MkDocs

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

MkDocs erzeugt aus Markdown-Dateien eine statische Dokumentations-Webseite mit Navigation und Suche. Zusammen mit dem Design Material for MkDocs entsteht daraus eine moderne Seite mit hellem und dunklem Modus, Hinweiskästen und Kopier-Schaltflächen für Codebeispiele.

Vorbemerkungen

  • Installation über apt: MkDocs und Material for MkDocs sind beide in den Ubuntu-Paketquellen enthalten. Eine Installation mit pip ist nicht nötig.
  • Einstellungen im YAML-Format: Alle Einstellungen stehen in einer Datei mkdocs.yml. In YAML zählt die Einrückung: Sie wird immer mit Leerzeichen gemacht, nie mit Tabulatoren.
  • Weiterentwicklung: Das Team hinter Material for MkDocs arbeitet inzwischen an einem Nachfolger namens Zensical. Material for MkDocs wird weiterhin gepflegt, bekommt aber vor allem Fehlerkorrekturen und keine großen neuen Funktionen mehr.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von MkDocs und Material for MkDocs aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. MkDocs installieren

Installiert den Befehl mkdocs, mit dem Projekte angelegt, in einer Vorschau angezeigt und gebaut werden.

sudo apt install mkdocs

Prüfen: Die Ausgabe beginnt mit mkdocs, version 1.6.1.

mkdocs --version

3. Material for MkDocs installieren

Installiert das Design. Die nötigen Markdown-Erweiterungen (Paket python3-pymdownx) werden automatisch mitinstalliert.

sudo apt install mkdocs-material

Prüfen: Die Ausgabe zeigt Status: install ok installed.

dpkg -s mkdocs-material | grep Status

Erstes Projekt

4. Projekt anlegen

mkdocs new legt einen Ordner mit einer Einstellungsdatei mkdocs.yml und einem Unterordner docs an. In docs liegen die Markdown-Seiten, zu Beginn nur die Startseite index.md.

mkdocs new ~/mkdocs-test

5. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/mkdocs-test

Prüfen: Es werden docs und mkdocs.yml angezeigt.

ls

6. Vorschau starten

mkdocs serve baut die Seite und startet einen kleinen Webserver. Bei jeder gespeicherten Änderung wird neu gebaut und der Browser lädt die Seite von selbst neu. Das Terminal bleibt dabei belegt, öffne für die nächsten Schritte ein zweites Terminal (ebenfalls im Ordner ~/mkdocs-test).

mkdocs serve

Prüfen: Im Terminal steht Serving on http://127.0.0.1:8000/. Öffne http://127.0.0.1:8000 im Browser: Es erscheint die Startseite im einfachen Standard-Design von MkDocs.

Material for MkDocs einrichten

7. Einstellungsdatei für Material schreiben

Ersetzt den Inhalt von mkdocs.yml. Die Einstellungen bewirken Folgendes:

  • theme: name: material – schaltet das Material-Design ein
  • language: de – deutsche Beschriftungen, z. B. „Suche“
  • palette – zwei Farbschemata (hell und dunkel) mit Umschalter oben rechts
  • features – schnelleres Laden der Seiten, Suchvorschläge und eine Kopier-Schaltfläche an Codeblöcken
  • markdown_extensions – Hinweiskästen, aufklappbare Abschnitte und Syntaxhervorhebung
  • nav – legt Reihenfolge und Titel der Seiten in der Navigation fest
nano mkdocs.yml

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

site_name: Meine Dokumentation

theme:
  name: material
  language: de
  palette:
    - scheme: default
      toggle:
        icon: material/brightness-7
        name: Dunkles Design einschalten
    - scheme: slate
      toggle:
        icon: material/brightness-4
        name: Helles Design einschalten
  features:
    - navigation.instant
    - search.suggest
    - content.code.copy

markdown_extensions:
  - admonition
  - pymdownx.details
  - pymdownx.highlight
  - pymdownx.superfences

nav:
  - Start: index.md
  - Erste Seite: erste-seite.md

Prüfen: Das Terminal mit mkdocs serve zeigt eine Warnung, dass erste-seite.md fehlt. Das ist richtig, die Seite folgt im nächsten Schritt.

8. Eine neue Seite anlegen

Legt die Seite erste-seite.md im Ordner docs an. Sie zeigt zwei typische Material-Funktionen: einen Hinweiskasten (!!! note) und einen Codeblock mit Kopier-Schaltfläche.

nano docs/erste-seite.md

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Erste Seite

Diese Seite nutzt Funktionen von Material for MkDocs.

!!! note "Hinweis"
    Das ist ein hervorgehobener Hinweiskasten.

```python
print("Hallo MkDocs")
```

Prüfen: Im Browser unter http://127.0.0.1:8000 hat die Seite jetzt das Material-Design. In der Navigation steht „Erste Seite“ mit einem blauen Hinweiskasten, und oben rechts gibt es den Umschalter für hell und dunkel.

9. Vorschau beenden

Beendet den Webserver aus Schritt 6. Wechsle dazu in dessen Terminal und drücke Strg+C.

10. Fertige Webseite bauen

Erzeugt die fertige Webseite im Ordner site. Diesen Ordner kannst du auf einen beliebigen Webserver hochladen, z. B. nach /var/www/... auf einem Server mit nginx. --strict bricht bei Fehlern wie fehlenden Seiten ab, statt nur zu warnen.

mkdocs build --strict

Prüfen: Die Ausgabe endet mit Documentation built in …, und im Ordner site liegt eine index.html.

ls site/index.html

Deinstallieren

1. Testprojekt entfernen

Löscht den Beispielordner aus Schritt 4. Achtung: Alles in ~/mkdocs-test geht verloren.

rm -rf ~/mkdocs-test

2. MkDocs und Material entfernen

purge entfernt auch die Konfigurationsdateien der Pakete.

sudo apt purge mkdocs mkdocs-material

3. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für MkDocs installiert wurden, z. B. python3-pymdownx und mkdocs-material-extensions.

sudo apt autoremove

Prüfen: Der Befehl wird nicht mehr gefunden.

mkdocs --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Docusaurus

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Docusaurus ist ein Werkzeug von Meta, mit dem man Dokumentations-Webseiten aus Markdown-Dateien erstellt. Es bringt Seitennavigation, Suche, Versionierung, mehrsprachige Seiten und auf Wunsch einen Blog mit. Die Seiten basieren auf React und lassen sich deshalb mit eigenen Komponenten erweitern.

Vorbemerkungen

  • Kein apt-Paket: Docusaurus ist nicht in den Ubuntu-Paketquellen enthalten. Es wird nicht systemweit installiert, sondern pro Projekt über npm, den Paketmanager von Node.js. Aus den Ubuntu-Paketquellen kommen nur Node.js und npm.
  • Node.js-Version: Docusaurus 3 braucht Node.js 20 oder neuer. Ubuntu 26.04 liefert Node.js 22, das passt.
  • Speicherplatz: Jedes Docusaurus-Projekt lädt seine Abhängigkeiten in einen eigenen Ordner node_modules. Er ist etwa 350 MB groß.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Node.js und npm aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Node.js und npm installieren

Node.js führt Docusaurus aus, npm lädt Docusaurus und seine Abhängigkeiten herunter. Das Paket npm bringt auch den Befehl npx mit, der im nächsten Schritt gebraucht wird. Ist beides schon vorhanden (z. B. aus der Antora-Anleitung), meldet apt das nur.

sudo apt install nodejs npm

Prüfen: Die Ausgabe ist eine Versionsnummer ab v20, z. B. v22.22.1.

node --version

Hast du Node.js zusätzlich über den Versionsmanager nvm installiert, wird dessen Version angezeigt. Das ist in Ordnung, solange sie mindestens v20 ist.

Erstes Projekt

3. Projekt anlegen

npx create-docusaurus lädt das Einrichtungsprogramm von Docusaurus herunter und erzeugt damit ein neues Projekt im Ordner ~/meine-doku. Die Angaben bedeuten:

  • classic – die Standardvorlage mit Dokumentation, Blog und Startseite
  • --javascript – das Projekt verwendet JavaScript statt TypeScript (sonst wird nachgefragt)
  • --package-manager npm – die Abhängigkeiten werden mit npm installiert

Der Vorgang dauert je nach Internetverbindung ein bis zwei Minuten. Fragt npx, ob create-docusaurus installiert werden soll, mit y bestätigen.

npx create-docusaurus@latest ~/meine-doku classic --javascript --package-manager npm

Prüfen: Die Ausgabe enthält [SUCCESS] Created.

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/meine-doku

Prüfen: Unter anderem werden die Ordner docs (Dokumentationsseiten), blog und src sowie die Einstellungsdatei docusaurus.config.js angezeigt.

ls

5. Vorschau starten

Startet einen Entwicklungsserver. Bei jeder gespeicherten Änderung aktualisiert sich die Seite im Browser von selbst. Das Terminal bleibt dabei belegt, öffne für die nächsten Schritte ein zweites Terminal (ebenfalls im Ordner ~/meine-doku).

npm start

Prüfen: Im Terminal steht Docusaurus website is running at: http://localhost:3000/. Der Browser öffnet sich meist von selbst, sonst http://localhost:3000 aufrufen. Es erscheint die Beispielseite „My Site“.

Projekt anpassen

6. Titel ändern

Ersetzt den Beispieltitel „My Site“ in der Einstellungsdatei durch einen eigenen. Er erscheint im Browser-Tab und oben links in der Navigationsleiste.

nano docusaurus.config.js

title: 'My Site', steht zweimal in der Datei: oben als Titel der Webseite und weiter unten beim Abschnitt navbar als Titel in der Navigationsleiste. Suche mit Strg+W nach title: 'My Site' und drücke Enter. Ersetze My Site durch Meine Dokumentation. Springe dann mit Alt+W zur zweiten Fundstelle und ändere sie genauso. Beide Zeilen lauten danach (mit unterschiedlicher Einrückung):

title: 'Meine Dokumentation',

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: In der Vorschau steht oben links „Meine Dokumentation“.

7. Sprache auf Deutsch stellen

Stellt die Sprache der Webseite von Englisch auf Deutsch um. Dadurch erscheinen fest eingebaute Beschriftungen wie „Weiter“ oder „Zurück“ auf Deutsch. Die Beispieltexte der Vorlage bleiben englisch, sie werden durch deine eigenen Seiten ersetzt.

nano docusaurus.config.js

Suche mit Strg+W nach defaultLocale und drücke Enter. Ändere in dieser und der Zeile darunter jeweils 'en' in 'de', sodass beide Zeilen so lauten:

    defaultLocale: 'de',
    locales: ['de'],

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Ausgabe zeigt defaultLocale: 'de' und locales: ['de'].

grep -E "defaultLocale|locales:" docusaurus.config.js

Die Spracheinstellung wird erst nach einem Neustart der Vorschau wirksam: Im Terminal mit npm start Strg+C drücken und npm start erneut ausführen.

8. Eine eigene Seite anlegen

Legt die Seite erste-seite.md im Ordner docs an. Der Block zwischen den ----Zeilen enthält Angaben für Docusaurus: sidebar_position: 2 setzt die Seite an die zweite Stelle der Seitenleiste. Der Kasten mit :::tip ist ein Hinweiskasten, eine Besonderheit von Docusaurus.

nano docs/erste-seite.md

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

---
sidebar_position: 2
---

# Erste Seite

Diese Seite ist in **Markdown** geschrieben.

:::tip Tipp
Änderungen erscheinen sofort im Browser, solange `npm start` läuft.
:::

Prüfen: In der Vorschau unter Tutorial erscheint in der linken Seitenleiste „Erste Seite“ mit einem grünen Hinweiskasten.

9. Vorschau beenden

Beendet den Entwicklungsserver aus Schritt 5. Wechsle dazu in dessen Terminal und drücke Strg+C.

10. Fertige Webseite bauen

Erzeugt die fertige, optimierte Webseite im Ordner build. Diesen Ordner kannst du auf einen beliebigen Webserver hochladen, z. B. auf einen Server mit nginx. Findet Docusaurus dabei defekte Links, bricht der Vorgang mit einer Fehlermeldung ab.

npm run build

Prüfen: Die Ausgabe enthält [SUCCESS] Generated static files in "build".

11. Fertige Webseite ansehen

Startet einen einfachen Webserver für den Ordner build. So siehst du die Seite genauso, wie sie später veröffentlicht wird.

npm run serve

Prüfen: http://localhost:3000 zeigt die fertige Seite. Mit Strg+C beendest du den Webserver.

Aktualisieren

Docusaurus wird pro Projekt aktualisiert. Im Projektordner zeigt dieser Befehl, ob neuere Versionen der Docusaurus-Pakete verfügbar sind:

npm outdated

Die Pakete, die mit @docusaurus/ beginnen, sollten immer alle dieselbe Version haben. Hinweise zum Umstieg auf eine neue Hauptversion stehen in den Versionshinweisen von Docusaurus.

Deinstallieren

1. Projekt entfernen

Löscht das Beispielprojekt samt node_modules. Achtung: Alles in ~/meine-doku geht verloren.

rm -rf ~/meine-doku

2. Zwischengespeichertes Einrichtungsprogramm entfernen

npx hat create-docusaurus in einem Zwischenspeicher abgelegt. Dieser Befehl leert ihn. Andere Projekte sind davon nicht betroffen, npx lädt benötigte Programme beim nächsten Aufruf einfach neu.

rm -rf ~/.npm/_npx

3. Optional: Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (z. B. Antora).

sudo apt purge nodejs npm
sudo apt autoremove

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/meine-doku

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

VitePress

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

VitePress erzeugt aus Markdown-Dateien eine schnelle, statische Dokumentations-Webseite. Es basiert auf Vite und Vue, bringt ein fertiges Design mit Seitenleiste, Suche und dunklem Modus mit und aktualisiert die Vorschau beim Schreiben ohne Verzögerung.

Vorbemerkungen

  • Kein apt-Paket: VitePress ist nicht in den Ubuntu-Paketquellen enthalten. Es wird nicht systemweit installiert, sondern pro Projekt über npm, den Paketmanager von Node.js. Aus den Ubuntu-Paketquellen kommen nur Node.js und npm.
  • Version: Diese Anleitung verwendet die stabile Version VitePress 1 (derzeit 1.6). An Version 2 wird noch gearbeitet.
  • Node.js-Version: VitePress 1 braucht Node.js 18 oder neuer. Ubuntu 26.04 liefert Node.js 22, das passt.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Node.js und npm aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Node.js und npm installieren

Node.js führt VitePress aus, npm lädt VitePress herunter. Das Paket npm bringt auch den Befehl npx mit. Ist beides schon vorhanden (z. B. aus der Docusaurus-Anleitung), meldet apt das nur.

sudo apt install nodejs npm

Prüfen: Die Ausgabe ist eine Versionsnummer ab v18, z. B. v22.22.1.

node --version

Hast du Node.js zusätzlich über den Versionsmanager nvm installiert, wird dessen Version angezeigt. Das ist in Ordnung, solange sie mindestens v18 ist.

Erstes Projekt

3. Projektordner anlegen

Ein eigener Ordner für die Dokumentation. Hier als Beispiel ~/meine-vitepress.

mkdir ~/meine-vitepress

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/meine-vitepress

5. VitePress im Projekt installieren

Lädt VitePress in den Ordner node_modules und legt die Datei package.json an, in der npm festhält, welche Pakete das Projekt braucht. -D markiert VitePress als Entwicklungswerkzeug: Es wird zum Bauen gebraucht, ist aber nicht Teil der fertigen Webseite.

npm add -D vitepress

Prüfen: Die Ausgabe zeigt die installierte Version, z. B. vitepress@1.6.4.

npm ls vitepress

6. Grundgerüst mit dem Assistenten anlegen

Der Assistent legt Einstellungsdatei, Startseite und zwei Beispielseiten an. Er stellt sechs Fragen, die du mit den Pfeiltasten und Enter beantwortest. Du kannst überall den Vorschlag mit Enter übernehmen, Titel und Beschreibung werden in Schritt 8 ohnehin ersetzt:

FrageAntwortBedeutung
Where should VitePress initialize the config?./Die Seiten liegen direkt im Projektordner
Site titlebeliebigTitel der Webseite
Site descriptionbeliebigKurzbeschreibung für Suchmaschinen
ThemeDefault ThemeDas fertige VitePress-Design
Use TypeScript for config and theme files?YesDie Einstellungsdatei heißt dann config.mts
Add VitePress npm scripts to package.json?YesLegt Kurzbefehle wie npm run docs:dev an
npx vitepress init

Prüfen: Der Assistent endet mit Done! Now run npm run docs:dev and start writing. Im Ordner liegen jetzt index.md, zwei Beispielseiten und der versteckte Ordner .vitepress mit der Datei config.mts.

ls -a . .vitepress

7. Vorschau starten

Startet einen Entwicklungsserver. Jede gespeicherte Änderung erscheint sofort im Browser. Das Terminal bleibt dabei belegt, öffne für die nächsten Schritte ein zweites Terminal (ebenfalls im Ordner ~/meine-vitepress).

npm run docs:dev

Prüfen: Im Terminal steht Local: http://localhost:5173/. Öffne http://localhost:5173 im Browser: Es erscheint die Beispiel-Startseite „My Awesome Project“.

Projekt anpassen

8. Einstellungen auf Deutsch schreiben

Ersetzt die Einstellungsdatei. Die Angaben bewirken Folgendes:

  • lang, title, description – Sprache, Titel und Beschreibung der Webseite
  • nav – Links in der Kopfleiste
  • sidebar – Aufbau der Seitenleiste
  • search – eingebaute Suche, die ohne externen Dienst funktioniert
  • die restlichen Angaben – deutsche Beschriftungen für fest eingebaute Texte wie „Nächste Seite“
nano .vitepress/config.mts

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

import { defineConfig } from 'vitepress'

export default defineConfig({
  lang: 'de-DE',
  title: 'Meine Dokumentation',
  description: 'Eine Dokumentation mit VitePress',
  themeConfig: {
    nav: [
      { text: 'Start', link: '/' },
      { text: 'Erste Seite', link: '/erste-seite' }
    ],
    sidebar: [
      {
        text: 'Anleitung',
        items: [
          { text: 'Erste Seite', link: '/erste-seite' }
        ]
      }
    ],
    search: { provider: 'local' },
    outline: { label: 'Auf dieser Seite' },
    docFooter: { prev: 'Vorherige Seite', next: 'Nächste Seite' },
    darkModeSwitchLabel: 'Design',
    sidebarMenuLabel: 'Menü',
    returnToTopLabel: 'Nach oben'
  }
})

Die Vorschau lädt die geänderten Einstellungen von selbst neu.

9. Startseite ersetzen

Die Startseite besteht nur aus Angaben zwischen den ----Zeilen. layout: home erzeugt daraus eine Titelseite mit großer Überschrift und einer Schaltfläche.

nano index.md

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

---
layout: home

hero:
  name: Meine Dokumentation
  tagline: Erstellt mit VitePress
  actions:
    - theme: brand
      text: Los geht's
      link: /erste-seite
---

10. Eine eigene Seite anlegen

Legt die Seite erste-seite.md an. Der Kasten mit ::: tip ist ein Hinweiskasten, eine Besonderheit von VitePress.

nano erste-seite.md

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Erste Seite

Diese Seite ist in **Markdown** geschrieben.

::: tip Tipp
Änderungen erscheinen sofort im Browser, solange `npm run docs:dev` läuft.
:::

## Ein Codebeispiel

```js
console.log('Hallo VitePress')
```

Prüfen: In der Vorschau führt die Schaltfläche „Los geht's“ zur neuen Seite. Sie hat einen grünen Hinweiskasten, und rechts steht „Auf dieser Seite“.

11. Beispielseiten entfernen

Die zwei Beispielseiten des Assistenten werden nicht mehr gebraucht und sind in den neuen Einstellungen auch nicht mehr verlinkt.

rm api-examples.md markdown-examples.md

12. Vorschau beenden

Beendet den Entwicklungsserver aus Schritt 7. Wechsle dazu in dessen Terminal und drücke Strg+C.

13. Fertige Webseite bauen

Erzeugt die fertige Webseite im Ordner .vitepress/dist. Diesen Ordner kannst du auf einen beliebigen Webserver hochladen, z. B. auf einen Server mit nginx. Findet VitePress dabei Links auf Seiten, die es nicht gibt, bricht der Vorgang mit einer Fehlermeldung ab.

npm run docs:build

Prüfen: Die Ausgabe endet mit build complete in ….

14. Fertige Webseite ansehen

Startet einen einfachen Webserver für den fertigen Ordner. So siehst du die Seite genauso, wie sie später veröffentlicht wird.

npm run docs:preview

Prüfen: http://localhost:4173 zeigt die fertige Seite. Mit Strg+C beendest du den Webserver.

Aktualisieren

VitePress wird pro Projekt aktualisiert. Im Projektordner holt dieser Befehl die neueste Version innerhalb von VitePress 1:

npm update vitepress

Prüfen:

npm ls vitepress

Deinstallieren

1. Projekt entfernen

Löscht das Beispielprojekt samt node_modules. Achtung: Alles in ~/meine-vitepress geht verloren.

rm -rf ~/meine-vitepress

2. Optional: Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (z. B. Antora oder Docusaurus).

sudo apt purge nodejs npm
sudo apt autoremove

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/meine-vitepress

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Astro Starlight

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Starlight macht aus Astro, einem Werkzeug zum Bauen von Webseiten, ein fertiges System für Dokumentationen. Aus Markdown-Dateien entsteht damit eine schnelle, statische Webseite mit Seitenleiste, eingebauter Suche, hellem und dunklem Modus sowie Unterstützung für mehrere Sprachen.

Vorbemerkungen

  • Kein apt-Paket: Astro und Starlight sind nicht in den Ubuntu-Paketquellen enthalten. Sie werden nicht systemweit installiert, sondern pro Projekt über npm, den Paketmanager von Node.js. Aus den Ubuntu-Paketquellen kommen nur Node.js und npm.
  • Node.js-Version: Astro 7 braucht Node.js 22.12 oder neuer. Ubuntu 26.04 liefert Node.js 22.22, das passt.
  • Junge Software: Starlight hat noch eine Versionsnummer unter 1 (derzeit 0.42). Zwischen Versionen ändern sich gelegentlich Einstellungen. Die Beispiele hier passen zu Astro 7 und Starlight 0.42.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Node.js und npm aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Node.js und npm installieren

Node.js führt Astro aus, npm lädt Astro und Starlight herunter. Ist beides schon vorhanden (z. B. aus der Docusaurus-Anleitung), meldet apt das nur.

sudo apt install nodejs npm

Prüfen: Die Ausgabe ist eine Versionsnummer ab v22.12, z. B. v22.22.1.

node --version

Hast du Node.js zusätzlich über den Versionsmanager nvm installiert, wird dessen Version angezeigt. Das ist in Ordnung, solange sie mindestens v22.12 ist.

Erstes Projekt

3. Projekt anlegen

npm create astro lädt das Einrichtungsprogramm von Astro herunter und erzeugt damit ein neues Projekt im Ordner ~/meine-starlight. Die Angaben nach -- bedeuten:

  • --template starlight – verwendet die Starlight-Vorlage statt einer leeren Astro-Seite
  • --install – installiert die benötigten Pakete gleich mit
  • --no-git – legt kein Git-Repository an (das kannst du später jederzeit mit git init nachholen)
  • --yes – beantwortet alle weiteren Fragen mit dem Vorschlag

Der Vorgang dauert je nach Internetverbindung etwa eine Minute.

npm create --yes astro@latest -- ~/meine-starlight --template starlight --install --no-git --yes

Prüfen: Die Ausgabe enthält Project initialized!.

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/meine-starlight

Prüfen: Unter anderem werden die Einstellungsdatei astro.config.mjs und der Ordner src angezeigt. Die Seiten der Dokumentation liegen in src/content/docs.

ls

5. Vorschau starten

Startet einen Entwicklungsserver. Jede gespeicherte Änderung erscheint sofort im Browser. Das Terminal bleibt dabei belegt, öffne für die nächsten Schritte ein zweites Terminal (ebenfalls im Ordner ~/meine-starlight).

npm run dev

Prüfen: Im Terminal steht Local http://localhost:4321/. Öffne http://localhost:4321 im Browser: Es erscheint die englische Beispielseite „Welcome to Starlight“.

Projekt anpassen

6. Einstellungen auf Deutsch schreiben

Ersetzt die Einstellungsdatei. Die Angaben bewirken Folgendes:

  • title – Titel der Webseite, erscheint oben links
  • defaultLocale und locales – die Seite ist einsprachig auf Deutsch. Dadurch erscheinen fest eingebaute Beschriftungen wie „Suchen“ oder „Auf dieser Seite“ auf Deutsch.
  • sidebar – die Seitenleiste enthält eine Gruppe „Anleitungen“, die automatisch alle Seiten aus dem Ordner anleitungen auflistet
nano astro.config.mjs

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

// @ts-check
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';

export default defineConfig({
	integrations: [
		starlight({
			title: 'Meine Dokumentation',
			defaultLocale: 'root',
			locales: {
				root: { label: 'Deutsch', lang: 'de' },
			},
			sidebar: [
				{
					label: 'Anleitungen',
					items: [{ autogenerate: { directory: 'anleitungen' } }],
				},
			],
		}),
	],
});

In der Vorschau ist die Seitenleiste jetzt leer, weil es den Ordner anleitungen noch nicht gibt. Das ändert sich in den nächsten Schritten.

7. Beispielseiten entfernen

Die Vorlage enthält zwei Beispielordner, die in den neuen Einstellungen nicht mehr vorkommen.

rm -r src/content/docs/guides src/content/docs/reference

8. Ordner für die eigenen Seiten anlegen

In diesem Ordner sucht die Seitenleiste nach Seiten (siehe Schritt 6).

mkdir src/content/docs/anleitungen

9. Eine eigene Seite anlegen

Legt die Seite erste-seite.md an. Jede Seite beginnt mit Angaben zwischen ----Zeilen: title ist Pflicht und wird zur Überschrift der Seite, description erscheint in Suchmaschinen. Der Kasten mit :::tip ist ein Hinweiskasten, eine Besonderheit von Starlight.

nano src/content/docs/anleitungen/erste-seite.md

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

---
title: Erste Seite
description: Eine erste Seite mit Starlight
---

Diese Seite ist in **Markdown** geschrieben. Den Titel oben setzt Starlight aus der Angabe `title`.

:::tip[Tipp]
Änderungen erscheinen sofort im Browser, solange `npm run dev` läuft.
:::

## Ein Codebeispiel

```js
console.log('Hallo Starlight');
```

10. Startseite ersetzen

Die Startseite der Vorlage ist englisch und verlinkt auf die gelöschten Beispielseiten. template: splash erzeugt eine Titelseite ohne Seitenleiste mit großer Überschrift und einer Schaltfläche.

nano src/content/docs/index.mdx

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

---
title: Meine Dokumentation
description: Startseite der Dokumentation
template: splash
hero:
  tagline: Erstellt mit Astro Starlight
  actions:
    - text: Los geht's
      link: /anleitungen/erste-seite/
      icon: right-arrow
---

Prüfen: Lade http://localhost:4321 im Browser neu. Die Schaltfläche „Los geht's“ führt zur neuen Seite. Links steht die Gruppe „Anleitungen“, rechts „Auf dieser Seite“, und oben gibt es ein Suchfeld „Suchen“.

11. Vorschau beenden

Beendet den Entwicklungsserver aus Schritt 5. Wechsle dazu in dessen Terminal und drücke Strg+C.

12. Fertige Webseite bauen

Erzeugt die fertige Webseite im Ordner dist, einschließlich des Suchindex. Diesen Ordner kannst du auf einen beliebigen Webserver hochladen, z. B. auf einen Server mit nginx.

npm run build

Prüfen: Die Ausgabe endet mit [build] Complete!. Die Warnung, dass für die Sitemap die Einstellung site fehlt, kannst du hier ignorieren. Vor einer echten Veröffentlichung trägst du in astro.config.mjs vor integrations die spätere Adresse ein, z. B. site: 'https://docs.example.org',.

13. Fertige Webseite ansehen

Startet einen einfachen Webserver für den Ordner dist. So siehst du die Seite genauso, wie sie später veröffentlicht wird. Anders als in der Vorschau funktioniert hier auch die Suche.

npm run preview

Prüfen: http://localhost:4321 zeigt die fertige Seite. Die Suche oben findet die „Erste Seite“. Mit Strg+C beendest du den Webserver.

Aktualisieren

Astro und Starlight werden pro Projekt aktualisiert. Im Projektordner bringt dieser Befehl Astro, Starlight und passende Erweiterungen gemeinsam auf den neuesten Stand. Er zeigt vorher an, was sich ändert, und fragt nach.

npx @astrojs/upgrade

Weil Starlight noch unter Version 1 ist, lohnt vor größeren Sprüngen ein Blick in die Versionshinweise von Starlight.

Deinstallieren

1. Projekt entfernen

Löscht das Beispielprojekt samt node_modules. Achtung: Alles in ~/meine-starlight geht verloren.

rm -rf ~/meine-starlight

2. Zwischengespeichertes Einrichtungsprogramm entfernen

npm create und npx haben Programme in einem Zwischenspeicher abgelegt. Dieser Befehl leert ihn. Andere Projekte sind davon nicht betroffen, die Programme werden beim nächsten Aufruf einfach neu geladen.

rm -rf ~/.npm/_npx

3. Optional: Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (z. B. Antora, Docusaurus oder VitePress).

sudo apt purge nodejs npm
sudo apt autoremove

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/meine-starlight

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Hugo

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Hugo ist ein sehr schneller Generator für statische Webseiten. Nach dem Prinzip „Docs as Code“ liegt die Dokumentation als Markdown im Git-Repository, wird wie Quellcode versioniert und geprüft und von Hugo zu einer Webseite mit Navigation und Suche gebaut.

Vorbemerkungen

  • Docs as Code: Die Texte werden mit denselben Werkzeugen gepflegt wie Programmcode: Texteditor, Git, Commits und Prüfungen vor dem Einchecken. Hugo übernimmt dabei zwei Aufgaben: Es baut die Webseite und es bricht den Bau ab, wenn z. B. ein interner Link ins Leere zeigt.
  • Installation über apt: Ubuntu liefert Hugo in der Variante „extended“ aus (Version 0.154). Diese Variante kann auch SCSS verarbeiten, was viele Designs voraussetzen.
  • Design (Theme): Hugo bringt kein fertiges Design mit. Diese Anleitung verwendet Hugo Book, ein schlichtes Design für Dokumentationen mit Seitenleiste, Suche und „Bearbeiten“-Link. Die neuesten Versionen von Hugo Book verlangen Hugo 0.158 oder neuer. Deshalb wird hier die Version v13 fest eingestellt, die mit der Hugo-Version aus Ubuntu funktioniert.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Paketversionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Hugo und Git installieren

Installiert den Befehl hugo und Git. Git wird für die Versionsverwaltung der Texte und zum Einbinden des Designs gebraucht.

sudo apt install hugo git

Prüfen: Die Ausgabe beginnt mit hugo v0.154.5+extended. Wichtig ist das Wort extended.

hugo version

Dokumentationsprojekt anlegen

3. Neues Projekt erzeugen

Legt den Ordner ~/hugo-docs mit der Grundstruktur eines Hugo-Projekts an. --format yaml sorgt dafür, dass die Einstellungsdatei hugo.yaml heißt und im YAML-Format geschrieben ist.

hugo new site ~/hugo-docs --format yaml

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/hugo-docs

Prüfen: Es werden unter anderem content, themes und hugo.yaml angezeigt.

ls

5. Git-Repository anlegen

Macht den Ordner zu einem Git-Repository mit dem Hauptzweig main. Ab jetzt wird jede Änderung an der Dokumentation nachvollziehbar gespeichert.

git init -b main

6. Erzeugte Dateien von Git ausschließen

Die fertige Webseite (public/) und Zwischenergebnisse entstehen bei jedem Bau neu. Sie gehören deshalb nicht ins Repository, nur die Quelltexte.

nano .gitignore

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

public/
resources/_gen/
.hugo_build.lock

7. Design als Git-Submodul einbinden

Lädt Hugo Book in den Ordner themes/hugo-book. Als Submodul merkt sich das Repository nur, welche Version des Designs verwendet wird, statt alle Dateien selbst zu speichern.

git submodule add https://github.com/alex-shpak/hugo-book themes/hugo-book

8. Passende Design-Version einstellen

Stellt das Design auf die Version v13, die zu Hugo 0.154 passt (siehe Vorbemerkungen).

git -C themes/hugo-book checkout v13

Git meldet dabei einen „losgelösten HEAD“ (detached HEAD). Das ist hier gewollt: Das Design soll auf genau dieser Version stehen bleiben.

Prüfen: Die Ausgabe zeigt v13.

git -C themes/hugo-book describe --tags

9. Einstellungsdatei schreiben

Ersetzt den Inhalt von hugo.yaml. Die Einstellungen bewirken Folgendes:

  • languageCode und defaultContentLanguage – die Seite ist deutschsprachig
  • theme – verwendet das Design aus Schritt 7
  • enableGitInfo – übernimmt das Datum der letzten Änderung jeder Seite aus der Git-Historie
  • BookSection – der Ordner content/docs erscheint als Navigation in der Seitenleiste
  • BookRepo und BookEditLink – jede Seite bekommt einen Link, der direkt zur Datei im Online-Repository führt; die Adresse später durch die eigene ersetzen
nano hugo.yaml

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

baseURL: https://example.org/
languageCode: de
defaultContentLanguage: de
title: Meine Dokumentation
theme: hugo-book
enableGitInfo: true

params:
  BookSection: docs
  BookRepo: https://github.com/beispiel/hugo-docs
  BookEditLink: '{{ .Site.Params.BookRepo }}/edit/main/{{ .Path }}'

10. Grundgerüst einchecken

Speichert den bisherigen Stand als ersten Commit. Das ist schon jetzt nötig: Wegen enableGitInfo liest Hugo die Git-Historie und bricht ab, solange das Repository noch gar keinen Commit hat.

git add .
git commit -m "Hugo-Projekt mit Design Hugo Book angelegt"

Prüfen: git log --oneline zeigt den Commit an.

git log --oneline

Inhalte schreiben

11. Startseite anlegen

Die Datei content/_index.md wird zur Startseite. Der Link darin verwendet relref: Hugo sucht die Zielseite beim Bauen und meldet einen Fehler, falls es sie nicht gibt.

nano content/_index.md

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

---
title: Start
---

# Willkommen

Hier beginnt die Dokumentation. Weiter geht es mit der
[Installation]({{< relref "docs/installation" >}}).

12. Erste Dokumentationsseite erzeugen

hugo new content legt die Datei content/docs/installation.md mit einem vorbereiteten Kopfbereich an. Das Design liefert dafür eine eigene Vorlage mit allen Einstellungen, die eine Seite haben kann.

hugo new content docs/installation.md

Prüfen: Der Kopfbereich zwischen den beiden --- enthält title: "Installation".

cat content/docs/installation.md

13. Text der Seite ergänzen

Hängt einen Hinweiskasten und einen Codeblock an. Der Hinweiskasten nutzt die Markdown-Schreibweise > [!NOTE], die auch GitHub und GitLab darstellen.

nano content/docs/installation.md

Springe mit Strg+Ende ans Ende der Datei und füge diesen Text an (im Terminal mit Strg+Umschalt+V). Speichere mit Strg+O und Enter und beende nano mit Strg+X:


# Installation

> [!NOTE]
> Diese Seite liegt im Git-Repository und wird wie Code geprüft.

```bash
echo "Hallo Hugo"
```

14. Vorschau starten

hugo server baut die Seite im Arbeitsspeicher und startet einen kleinen Webserver. Jede gespeicherte Änderung erscheint sofort im Browser. Das Terminal bleibt belegt, öffne für die nächsten Schritte ein zweites Terminal (ebenfalls im Ordner ~/hugo-docs).

hugo server

Prüfen: Im Terminal steht Web Server is available at http://localhost:1313/. Unter http://localhost:1313 erscheint die Startseite, links die Navigation mit „Installation“ und darüber ein Suchfeld.

15. Vorschau beenden

Beendet den Webserver aus Schritt 14. Wechsle dazu in dessen Terminal und drücke Strg+C.

Prüfen wie Code

16. Automatische Prüfung vor jedem Commit einrichten

Ein Git-Hook ist ein Skript, das Git bei bestimmten Aktionen selbst startet. Dieser Hook baut die Seite vor jedem Commit testweise im Arbeitsspeicher. --panicOnWarning wertet schon Warnungen als Fehler. Scheitert der Bau, z. B. wegen eines Links auf eine nicht vorhandene Seite, bricht Git den Commit ab.

nano .git/hooks/pre-commit

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

#!/bin/sh
# Vor jedem Commit die Seite testweise bauen
hugo build --panicOnWarning --renderToMemory --logLevel error

17. Hook ausführbar machen

Git startet nur Hooks, die als ausführbar markiert sind.

chmod +x .git/hooks/pre-commit

18. Inhalte einchecken

Merkt die neuen Seiten für den Commit vor und speichert sie. Dabei läuft der Hook aus Schritt 16 zum ersten Mal.

git add .
git commit -m "Startseite und Installationsseite ergänzt"

Prüfen: Der Commit wird angelegt, und git log --oneline zeigt jetzt zwei Commits.

git log --oneline

Gegenprobe (optional): Ändere in content/_index.md das Linkziel docs/installation in docs/fehlt und versuche erneut einen Commit. Hugo meldet REF_NOT_FOUND, und der Commit wird nicht angelegt. Danach die Änderung wieder rückgängig machen.

19. Fertige Webseite bauen

Erzeugt die fertige Webseite im Ordner public. --minify verkleinert HTML, CSS und JavaScript. Den Ordner public kannst du auf einen beliebigen Webserver hochladen, z. B. nach /var/www/... auf einem Server mit nginx.

hugo build --minify --panicOnWarning

Prüfen: Die Ausgabe endet mit Total in … ms ohne ERROR, und die Seite liegt als HTML-Datei vor.

ls public/docs/installation/index.html

Projekt auf einem anderen Rechner weiterbearbeiten

Wird das Repository später geklont, muss das Design (Submodul) mitgeladen werden. Dafür gibt es die Option --recurse-submodules:

git clone --recurse-submodules <adresse-des-repositorys>

Deinstallieren

1. Testprojekt entfernen

Löscht den Beispielordner aus Schritt 3. Achtung: Alles in ~/hugo-docs geht verloren, auch die Git-Historie.

rm -rf ~/hugo-docs

2. Hugo entfernen

purge entfernt auch die Konfigurationsdateien des Pakets. Git bleibt installiert, weil es meist auch für andere Zwecke gebraucht wird.

sudo apt purge hugo

3. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für Hugo installiert wurden, z. B. libsass1.

sudo apt autoremove

Prüfen: Der Befehl wird nicht mehr gefunden.

hugo version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

gh-pages

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

gh-pages ist ein kleines npm-Werkzeug, das einen fertig gebauten Ordner (z. B. dist) mit einem einzigen Befehl in den Branch gh-pages eines Git-Repositorys schiebt. GitHub Pages veröffentlicht diesen Branch dann als Webseite.

Vorbemerkungen

  • Kein apt-Paket: gh-pages gibt es nicht in den Ubuntu-Paketquellen. Es wird pro Projekt mit npm installiert. Aus den Ubuntu-Paketquellen kommen nur Git, Node.js und npm.
  • Version: Diese Anleitung verwendet gh-pages 6 (derzeit 6.3). Es läuft mit jeder Node.js-Version ab 10, das Node.js 22 aus Ubuntu 26.04 passt also.
  • Voraussetzung: Du hast ein Repository auf GitHub, und git push funktioniert von deinem Rechner aus (per SSH-Schlüssel oder Zugangstoken). gh-pages nutzt genau diesen Zugang.
  • Was gh-pages nicht tut: Es baut die Webseite nicht. Den Ordner mit den fertigen Dateien erzeugt vorher dein Werkzeug, z. B. VitePress, Docusaurus oder mdBook.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Git, Node.js und npm kennt.

sudo apt update

2. Git, Node.js und npm installieren

Git überträgt die Dateien zu GitHub, Node.js führt gh-pages aus und npm lädt es herunter. Ist schon alles vorhanden, meldet apt das nur.

sudo apt install git nodejs npm

Prüfen: Beide Befehle geben eine Versionsnummer aus.

node --version
git --version

Beispielprojekt

Die folgenden Schritte zeigen gh-pages an einem kleinen Projekt. Hast du schon ein Projekt, beginne in dessen Ordner bei Schritt 6.

3. Repository von GitHub holen

Lädt ein bestehendes GitHub-Repository auf deinen Rechner. Ersetze BENUTZER und meine-seite durch deinen GitHub-Namen und den Namen des Repositorys. Das Repository sollte schon mindestens einen Commit haben (z. B. eine README.md, die GitHub beim Anlegen erzeugt).

git clone git@github.com:BENUTZER/meine-seite.git ~/meine-seite

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/meine-seite

Prüfen: Unter origin steht die Adresse deines GitHub-Repositorys. An diese Adresse schickt gh-pages später die Dateien.

git remote -v

5. package.json anlegen

npm braucht die Datei package.json, um festzuhalten, welche Pakete das Projekt verwendet. -y übernimmt alle Vorschläge, ohne nachzufragen.

npm init -y

6. gh-pages installieren

Lädt gh-pages in den Ordner node_modules und trägt es in package.json ein. -D kennzeichnet es als Entwicklungswerkzeug, das nicht zur Webseite selbst gehört.

npm add -D gh-pages

Prüfen: Die Ausgabe zeigt die installierte Version, z. B. gh-pages@6.3.0.

npm ls gh-pages

7. node_modules von Git ausschließen

Der Ordner node_modules lässt sich jederzeit mit npm install wiederherstellen und gehört nicht ins Repository. gh-pages legt dort außerdem seinen Zwischenspeicher ab.

nano .gitignore

Füge diese Zeile ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

node_modules

8. Ordner für die fertige Webseite anlegen

In einem echten Projekt erzeugt dein Werkzeug diesen Ordner beim Bauen. Für das Beispiel legst du ihn selbst an.

mkdir dist

9. Eine Testseite anlegen

Eine einfache HTML-Seite, an der du erkennst, ob die Veröffentlichung geklappt hat.

nano dist/index.html

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <title>Meine Seite</title>
</head>
<body>
  <h1>Hallo von GitHub Pages</h1>
</body>
</html>

10. Kurzbefehl in package.json eintragen

Ein Eintrag unter scripts erspart dir, die Optionen jedes Mal abzutippen. Danach genügt npm run deploy.

nano package.json

Suche mit Strg+W nach "test" und bestätige mit Enter. Lösche diese Zeile mit Strg+K und füge an ihrer Stelle diese Zeile ein. Speichere mit Strg+O und Enter und beende nano mit Strg+X:

    "deploy": "gh-pages -d dist --nojekyll"

Die Optionen bedeuten:

  • -d dist – dieser Ordner wird veröffentlicht
  • --nojekyll – legt eine leere Datei .nojekyll an. Sonst bereitet GitHub die Seite mit Jekyll auf und lässt dabei Ordner weg, die mit _ beginnen (das betrifft z. B. VitePress und Sphinx).

Der Abschnitt scripts sieht danach so aus:

  "scripts": {
    "deploy": "gh-pages -d dist --nojekyll"
  },

11. Projektdateien committen

Sichert package.json, package-lock.json und .gitignore im Branch main. Der Ordner dist wird hier mit übernommen, das ist für das Beispiel in Ordnung.

git add .
git commit -m "gh-pages einrichten"
git push

12. Webseite veröffentlichen

gh-pages kopiert den Inhalt von dist in den Branch gh-pages, erstellt dort einen Commit und schiebt ihn zu GitHub. Den Branch legt es beim ersten Mal selbst an.

npm run deploy

Prüfen: Die Ausgabe endet mit Published. Auf GitHub gibt es jetzt den Branch gh-pages mit den Dateien index.html und .nojekyll.

git ls-remote origin gh-pages

13. GitHub Pages einschalten

Einmalig im Browser: GitHub muss wissen, aus welchem Branch es die Webseite liefern soll.

  1. Öffne dein Repository auf GitHub.
  2. Klicke auf Settings und links auf Pages.
  3. Wähle unter Source den Eintrag Deploy from a branch.
  4. Wähle unter Branch den Eintrag gh-pages und den Ordner / (root) und klicke auf Save.

Prüfen: Nach ein bis zwei Minuten zeigt https://BENUTZER.github.io/meine-seite/ die Überschrift „Hallo von GitHub Pages“.

Mit anderen Werkzeugen verwenden

Bei einem echten Projekt ersetzt du in Schritt 10 nur dist durch den Ordner, in den dein Werkzeug baut, und baust vor npm run deploy die Seite neu:

WerkzeugOrdner für -d
mdBookbook
VitePress.vitepress/dist
Docusaurusbuild
Astro Starlightdist

Weil die Seite unter /meine-seite/ liegt und nicht direkt unter der Domain, muss dein Werkzeug das wissen. In VitePress trägst du dazu z. B. base: '/meine-seite/' in .vitepress/config.mts ein, in Docusaurus baseUrl. Ohne diese Angabe fehlen auf der veröffentlichten Seite Stile und Bilder.

Beispiel: mdBook unter eigener Domain veröffentlichen

So wird dieses Buch veröffentlicht: mdBook baut die Seiten in den Ordner book, gh-pages schiebt sie in den Branch gh-pages, und GitHub liefert sie unter der Subdomain installieren.wissen-ahrensburg.de aus. Die Schritte setzen voraus, dass gh-pages wie oben im Projekt installiert ist und origin auf das GitHub-Repository zeigt.

1. Kurzbefehl in package.json eintragen

Der Kurzbefehl heißt hier ver (für „veröffentlichen“) und bündelt alle Optionen.

nano package.json

Suche mit Strg+W nach "scripts" und bestätige mit Enter. Füge in der Zeile darunter diese Zeile ein (im Terminal mit Strg+Umschalt+V). Steht danach noch ein weiterer Eintrag wie "test", muss die Zeile mit einem Komma enden. Speichere mit Strg+O und Enter und beende nano mit Strg+X:

    "ver": "gh-pages -d book --nojekyll --cname installieren.wissen-ahrensburg.de --no-history"

Die Optionen bedeuten:

  • -d book – veröffentlicht den Ordner book, in den mdbook build schreibt
  • --nojekyll – verhindert, dass GitHub die Seite mit Jekyll aufbereitet (siehe Schritt 10 oben)
  • --cname installieren.wissen-ahrensburg.de – legt die Datei CNAME mit dieser Domain in den Branch. Daran erkennt GitHub, unter welcher Domain es die Seite ausliefern soll. Ersetze sie durch deine eigene (Sub-)Domain.
  • --no-history – ersetzt den Branch gh-pages bei jeder Veröffentlichung durch einen einzigen neuen Commit, statt einen weiteren anzuhängen. Das Repository wächst dadurch nicht mit jeder Veröffentlichung. Ältere Stände der Webseite sind danach nicht mehr im Branch gh-pages gespeichert; die Quelltexte in main bleiben unberührt.

Der Abschnitt scripts sieht danach z. B. so aus:

  "scripts": {
    "ver": "gh-pages -d book --nojekyll --cname installieren.wissen-ahrensburg.de --no-history"
  },

Prüfen: npm listet den Kurzbefehl ver auf.

npm run

2. Ordner book von Git ausschließen

book wird bei jedem Bauen neu erzeugt und gehört nicht in den Branch main. Öffne dazu .gitignore:

nano .gitignore

Füge diese Zeile ein, falls sie noch fehlt, speichere mit Strg+O und Enter und beende nano mit Strg+X:

book

3. DNS-Eintrag für die Subdomain setzen

Einmalig beim Anbieter deiner Domain: Die Subdomain muss auf GitHub Pages zeigen. Lege dazu einen CNAME-Eintrag an:

NameTypZiel
installierenCNAMEthorstenkloehn.github.io

Ersetze thorstenkloehn durch deinen GitHub-Namen. Der Eintrag verweist nur auf deine GitHub-Adresse, nicht auf das Repository. Welches Repository gemeint ist, erkennt GitHub an der Datei CNAME aus Schritt 1.

Prüfen: Nach einiger Zeit (je nach Anbieter Minuten bis Stunden) nennt dieser Befehl zuerst thorstenkloehn.github.io. und danach die Adressen von GitHub, die mit 185.199. beginnen.

dig +short installieren.wissen-ahrensburg.de

Fehlt dig, installierst du es mit sudo apt install bind9-dnsutils.

Hauptdomain statt Subdomain: Soll die Seite direkt unter wissen-ahrensburg.de erscheinen, ist ein CNAME-Eintrag bei vielen Anbietern nicht erlaubt. Dann legst du stattdessen vier A-Einträge mit den Adressen 185.199.108.153, 185.199.109.153, 185.199.110.153 und 185.199.111.153 an und gibst bei --cname die Hauptdomain an.

4. Buch bauen

Erzeugt den Ordner book mit der aktuellen Fassung aller Anleitungen. Ohne diesen Schritt würde gh-pages einen veralteten oder gar keinen Stand veröffentlichen.

mdbook build

Prüfen: Im Ordner book liegt eine index.html.

ls book/index.html

5. Buch veröffentlichen

Führt den Kurzbefehl aus Schritt 1 aus.

npm run ver

Prüfen: Die Ausgabe endet mit Published. Der Branch gh-pages enthält jetzt genau einen Commit:

git fetch origin gh-pages
git log --oneline origin/gh-pages

6. Eigene Domain in GitHub bestätigen

Einmalig im Browser: Öffne im Repository Settings → Pages. Stelle wie in Schritt 13 oben den Branch gh-pages ein. Unter Custom domain steht nun installieren.wissen-ahrensburg.de (aus der Datei CNAME). Setze, sobald GitHub es anbietet, den Haken bei Enforce HTTPS, damit die Seite verschlüsselt ausgeliefert wird.

Prüfen: https://installieren.wissen-ahrensburg.de/ zeigt das Buch.

Bei jeder späteren Änderung genügen die Schritte 4 und 5. Weil die Seite direkt unter der Subdomain liegt und nicht unter /meine-seite/, ist in mdBook keine zusätzliche Pfadangabe nötig.

Aktualisieren

gh-pages wird pro Projekt aktualisiert. Im Projektordner holt dieser Befehl die neueste Version innerhalb von gh-pages 6:

npm update gh-pages

Prüfen:

npm ls gh-pages

Fehlerbehebung

Meldet gh-pages Remote url mismatch, hat sich die Adresse von origin geändert, seit der Zwischenspeicher angelegt wurde. Dieser Befehl leert den Zwischenspeicher, danach funktioniert npm run deploy wieder:

npx gh-pages-clean

Deinstallieren

1. gh-pages aus dem Projekt entfernen

Löscht gh-pages aus node_modules und aus package.json.

npm uninstall gh-pages

Prüfen: Die Ausgabe zeigt (empty).

npm ls gh-pages

2. Kurzbefehl entfernen

Die Einträge deploy bzw. ver funktionieren ohne gh-pages nicht mehr.

nano package.json

Suche mit Strg+W nach "deploy" (bzw. "ver"), lösche die Zeile mit Strg+K, speichere mit Strg+O und Enter und beende nano mit Strg+X.

3. Optional: Veröffentlichte Webseite löschen

Entfernt den Branch gh-pages auf GitHub. Achtung: Die Webseite ist danach nicht mehr erreichbar.

git push origin --delete gh-pages

4. Optional: Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (z. B. VitePress oder Docusaurus).

sudo apt purge nodejs npm
sudo apt autoremove

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Obsidian

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Obsidian ist ein Programm für Notizen und persönliches Wissensmanagement. Notizen sind gewöhnliche Markdown-Dateien in einem Ordner auf deinem Rechner, die sich über Links zu einem Netz verknüpfen lassen. Mit Canvas kommen frei anordenbare Pinnwände hinzu, die ebenfalls in einem offenen Textformat gespeichert werden.

Vorbemerkungen

  • Kein apt-Paket: Obsidian ist nicht in den Ubuntu-Paketquellen enthalten. Diese Anleitung installiert es als Snap, das die Hersteller selbst veröffentlichen.
  • Lizenz: Obsidian ist kostenlos, auch für die Arbeit, aber nicht quelloffen. Kostenpflichtig sind nur Zusatzdienste wie die Synchronisation zwischen Geräten (Obsidian Sync).
  • Vault: Obsidian nennt einen Notizordner Vault (Tresor). Alles, was du schreibst, liegt als Datei in diesem Ordner. Das Programm ist nur die Oberfläche dafür.
  • Formate im Mittelpunkt: Diese Anleitung legt zuerst ein Beispiel-Vault im Terminal an. So siehst du, wie die Dateien aussehen, bevor Obsidian sie darstellt.

Installation

1. Paketlisten aktualisieren

Damit apt im nächsten Schritt die aktuelle Version von snapd kennt.

sudo apt update

2. Snap-Unterstützung sicherstellen

snapd ist der Dienst, der Snaps installiert und aktualisiert. Unter Ubuntu ist er normalerweise schon vorhanden, dann meldet apt das nur.

sudo apt install snapd

3. Obsidian installieren

Installiert Obsidian als Snap. --classic ist nötig, damit Obsidian Vaults an jedem Ort öffnen und Links zu anderen Programmen öffnen kann.

sudo snap install obsidian --classic

Prüfen: Die Ausgabe zeigt Name, Version (z. B. 1.13.7) und als Herausgeber obsidianmd.

snap list obsidian

Beispiel-Vault anlegen: die Format-Ebene

4. Ordner für das Vault anlegen

Das Vault ist ein ganz normaler Ordner. Hier als Beispiel ~/Dokumente/Obsidian.

mkdir -p ~/Dokumente/Obsidian

5. In den Ordner wechseln

Die nächsten Dateien werden hier angelegt.

cd ~/Dokumente/Obsidian

6. Eine Notiz in Markdown anlegen

Legt die Notiz Projekt Garten.md an. Sie zeigt die wichtigsten Bausteine des Obsidian-Markdowns:

  • Der Block zwischen den ----Zeilen am Anfang enthält Eigenschaften (Properties) im YAML-Format. Obsidian zeigt sie als Formular über der Notiz an.
  • [[Pflanzenliste]] ist ein Wikilink auf eine andere Notiz. Der Dateiname wird ohne .md angegeben.
  • #garten ist ein Tag.
  • > [!tip] leitet einen Hinweiskasten (Callout) ein.
  • - [ ] ist eine Aufgabe mit Kontrollkästchen.
nano "Projekt Garten.md"

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

---
status: geplant
beginn: 2026-10-01
tags:
  - garten
---

# Projekt Garten

Hochbeet im Herbst anlegen, Bepflanzung siehe [[Pflanzenliste]]. #garten

> [!tip] Tipp
> Erde erst nach dem ersten Regen auffüllen.

- [ ] Holz besorgen
- [x] Standort festlegen

7. Die verlinkte Notiz anlegen

Legt die Notiz an, auf die der Wikilink zeigt. Obsidian findet sie allein über den Dateinamen, egal in welchem Unterordner sie liegt.

nano Pflanzenliste.md

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

# Pflanzenliste

- Salat
- Radieschen
- Kräuter

8. Ein Canvas anlegen

Ein Canvas ist eine Pinnwand mit Karten und Verbindungslinien. Obsidian speichert sie in Dateien mit der Endung .canvas im offenen Format JSON Canvas. Der Aufbau:

  • nodes – die Karten. Jede hat eine eindeutige id, eine Position (x, y) und eine Größe (width, height) in Pixeln. Der type legt fest, was die Karte zeigt: text (eigener Markdown-Text), file (eine Notiz aus dem Vault), link (eine Webseite) oder group (ein Rahmen um andere Karten).
  • edges – die Verbindungslinien. fromNode und toNode verweisen auf die id der Karten, fromSide und toSide legen fest, an welcher Seite (top, right, bottom, left) die Linie ansetzt.
nano Gartenplanung.canvas

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

{
  "nodes": [
    {
      "id": "idee",
      "type": "text",
      "text": "## Idee\nHochbeet mit Gemüse",
      "x": 0, "y": 0, "width": 250, "height": 120
    },
    {
      "id": "projekt",
      "type": "file",
      "file": "Projekt Garten.md",
      "x": 400, "y": -60, "width": 400, "height": 300
    }
  ],
  "edges": [
    {
      "id": "idee-zu-projekt",
      "fromNode": "idee", "fromSide": "right",
      "toNode": "projekt", "toSide": "left",
      "label": "wird zu"
    }
  ]
}

Prüfen: Der Befehl meldet keinen Fehler, die Datei ist also gültiges JSON.

python3 -m json.tool Gartenplanung.canvas > /dev/null

Obsidian verwenden

9. Obsidian starten

Startet Obsidian. Alternativ findest du das Programm im Anwendungsmenü unter „Obsidian“.

obsidian &

10. Beispiel-Vault öffnen

Wähle im Startfenster Open folder as vault und dann den Ordner ~/Dokumente/Obsidian. Beim ersten Öffnen fragt Obsidian, ob du den Autoren des Vaults vertraust. Das betrifft Erweiterungen (Plugins). Weil das Vault von dir stammt, kannst du zustimmen.

Prüfen: Links in der Dateiliste stehen Gartenplanung, Pflanzenliste und Projekt Garten. Die Notiz „Projekt Garten“ zeigt oben die Eigenschaften status und beginn, darunter den Hinweiskasten und die Aufgaben. „Gartenplanung“ zeigt zwei Karten, die mit einem beschrifteten Pfeil verbunden sind.

11. Deutsche Oberfläche einstellen

Öffne die Einstellungen über das Zahnrad unten links (oder Strg+,). Wähle unter General bei Language den Eintrag Deutsch und klicke auf Relaunch, damit Obsidian neu startet.

12. Die wichtigsten Tastenkürzel kennenlernen

TastenWirkung
Strg+ONotiz schnell öffnen (Schnellwechsler)
Strg+PBefehlspalette: jeden Befehl über seinen Namen suchen
Strg+NNeue Notiz
Strg+EZwischen Bearbeiten und Leseansicht wechseln
Strg+Umschalt+FIm ganzen Vault suchen
Strg+GGraph-Ansicht: alle Notizen und ihre Links als Netz
[[Link auf eine Notiz einfügen (mit Vorschlagsliste)

Was Obsidian im Vault ablegt

13. Einstellungsordner ansehen

Beim ersten Öffnen legt Obsidian im Vault den versteckten Ordner .obsidian an. Darin stehen die Einstellungen dieses Vaults als JSON-Dateien, z. B. Darstellung, Tastenkürzel und installierte Plugins. Deine Notizen enthält der Ordner nicht.

ls ~/Dokumente/Obsidian/.obsidian

Prüfen: Es werden Dateien wie app.json und workspace.json angezeigt.

Weil Notizen und Canvas-Dateien reine Textdateien sind, kannst du sie auch mit jedem Editor bearbeiten, mit Git versionieren oder mit anderen Programmen weiterverarbeiten. Obsidian bemerkt Änderungen von außen und zeigt sie sofort an.

Aktualisieren

Snaps aktualisieren sich automatisch im Hintergrund. Sofort aktualisieren kannst du mit:

sudo snap refresh obsidian

Deinstallieren

1. Obsidian entfernen

Entfernt das Snap. --purge verhindert, dass Snap vorher eine Sicherungskopie anlegt. Deine Notizen bleiben erhalten.

sudo snap remove --purge obsidian

2. Programmeinstellungen entfernen

Obsidian merkt sich in ~/.config/obsidian die Liste der geöffneten Vaults und die Fenstereinstellungen. Deine Notizen sind dort nicht enthalten.

rm -rf ~/.config/obsidian

Prüfen: Die Ausgabe meldet, dass kein Snap namens obsidian installiert ist.

snap list obsidian

3. Optional: Vault löschen

Achtung: Dieser Befehl löscht alle Notizen und Canvas-Dateien des Vaults endgültig. Nur ausführen, wenn du sie nicht mehr brauchst oder vorher gesichert hast.

rm -rf ~/Dokumente/Obsidian

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Logseq

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Logseq ist ein Programm für Notizen und persönliches Wissensmanagement. Notizen werden als verschachtelte Stichpunkte (Blöcke) geschrieben und über Links und Tags miteinander verknüpft. Alle Inhalte liegen als gewöhnliche Markdown-Dateien in einem Ordner auf deinem Rechner, nicht in einer Cloud.

Vorbemerkungen

  • Kein apt-Paket: Logseq ist nicht in den Ubuntu-Paketquellen enthalten. Diese Anleitung installiert es deshalb als Snap. Das Snap wird unter dem Herausgeber „Logseq, Inc.“ veröffentlicht.
  • Zwei Versionen: Logseq teilt sich derzeit in zwei Linien auf:
    • Logseq 0.10 – die stabile Version, die Notizen als Markdown-Dateien speichert. Diese Version installiert die Anleitung.
    • Logseq 2.0 – eine neue Version, die Notizen in einer Datenbank speichert. Sie ist noch eine Beta-Version und nur als AppImage von der GitHub-Seite des Projekts erhältlich. Für wichtige Notizen ist sie noch nicht zu empfehlen.
  • Graph: Logseq nennt einen Ordner mit Notizen einen Graph. Du kannst mehrere Graphen anlegen, z. B. einen privaten und einen beruflichen.

Installation

1. Paketlisten aktualisieren

Damit apt im nächsten Schritt die aktuelle Version von snapd kennt.

sudo apt update

2. Snap-Unterstützung sicherstellen

snapd ist der Dienst, der Snaps installiert und aktualisiert. Unter Ubuntu ist er normalerweise schon vorhanden. Dann meldet apt das nur.

sudo apt install snapd

3. Logseq installieren

Installiert Logseq als Snap. Das Snap läuft in einem abgeschotteten Bereich und darf nur auf dein Home-Verzeichnis (ohne versteckte Ordner) und auf Wechseldatenträger zugreifen. Für Notizen reicht das.

sudo snap install logseq

Prüfen: Die Ausgabe zeigt Name und Version, z. B. 0.10.15.

snap list logseq

Erste Schritte

4. Ordner für die Notizen anlegen

Logseq braucht einen Ordner, in dem es die Notizen ablegt. Er muss in deinem Home-Verzeichnis liegen und darf nicht mit einem Punkt beginnen, sonst hat das Snap keinen Zugriff. Hier als Beispiel ~/Dokumente/Logseq.

mkdir -p ~/Dokumente/Logseq

5. Logseq starten

Startet Logseq. Alternativ findest du das Programm im Anwendungsmenü unter „Logseq“.

logseq &

Prüfen: Es öffnet sich ein Fenster mit einer Begrüßung und der Schaltfläche Choose a folder.

6. Ordner als Graph auswählen

Klicke auf Choose a folder und wähle den Ordner ~/Dokumente/Logseq aus Schritt 4. Logseq richtet darin seine Unterordner ein und öffnet die Tagesseite für heute.

Prüfen: Im Ordner liegen jetzt die Unterordner journals (Tagesseiten), pages (eigene Seiten) und logseq (Einstellungen des Graphen).

ls ~/Dokumente/Logseq

Die Unterordner journals und pages erscheinen erst, sobald du den ersten Text geschrieben hast.

7. Deutsche Oberfläche einstellen

Die Oberfläche ist zunächst auf Englisch. Klicke oben rechts auf die drei Punkte … → Settings. Wähle im Reiter General bei Language den Eintrag Deutsch. Die Umstellung wirkt sofort.

8. Die Grundlagen kennenlernen

Jeder Absatz in Logseq ist ein Block. Blöcke lassen sich einrücken, verlinken und als Aufgabe markieren.

Eingabe / TastenWirkung
EnterNeuen Block beginnen
Umschalt+EnterNeue Zeile im selben Block
Tab / Umschalt+TabBlock einrücken / ausrücken
[[Seitenname]]Link auf eine Seite; existiert sie nicht, wird sie angelegt
#TagSchlagwort, ebenfalls ein Link auf eine gleichnamige Seite
/Menü mit Befehlen öffnen, z. B. Datum, Aufgabe, Überschrift
TODO am BlockanfangBlock wird zur Aufgabe mit Kontrollkästchen
Strg+EnterAufgabenstatus umschalten (TODO → DOING → DONE)
Strg+KSuche über alle Seiten und Blöcke
G, dann JZu den Tagesseiten springen (außerhalb eines Blocks)

Prüfen: Schreibe auf der Tagesseite Test mit [[Erste Seite]] und klicke dann auf den Link. Logseq öffnet die neue Seite „Erste Seite“ und zeigt unten unter Verlinkte Referenzen, dass die Tagesseite auf sie verweist.

Das Dateiformat

9. Eine Seite als Datei ansehen

Logseq speichert jede Seite als Markdown-Datei, aber in einer besonderen Form: Jeder Block ist ein Listenpunkt (- ), eingerückte Blöcke sind mit Tabulatoren eingerückt. Tagesseiten liegen in journals und heißen nach dem Datum (z. B. 2026_09_23.md), alle anderen Seiten liegen in pages. Dieser Befehl zeigt die Seite „Erste Seite“ aus Schritt 8:

cat ~/Dokumente/Logseq/pages/Erste\ Seite.md

Prüfen: Die Datei beginnt mit - . Hast du auf der Seite etwas geschrieben, steht jeder Block in einer eigenen Zeile mit - .

Weitere Bausteine des Formats:

SchreibweiseBedeutung
- TextEin Block
[[Seite]], #TagLinks auf andere Seiten
TODO Text, DONE TextAufgabe mit ihrem Status
schluessel:: wertEigenschaft (Property). Steht sie in der ersten Zeile der Datei, gilt sie für die ganze Seite, sonst für den Block darüber.
id:: 6512…Kennung eines Blocks, die Logseq anlegt, sobald ein Block von anderswo verlinkt wird

Die Einstellungen des Graphen stehen in logseq/config.edn, einer Textdatei im EDN-Format (einer Schreibweise aus der Programmiersprache Clojure). Weil alles aus Textdateien besteht, kannst du die Notizen auch mit einem Editor lesen oder mit Git versionieren. Beim Wechsel zu Obsidian lassen sich die Dateien meist direkt weiterverwenden. Nur die Listenpunkt-Struktur und die Schreibweise schluessel:: wert sind dort ungewohnt.

Optional: Notizen sichern

Weil Logseq alle Notizen als Markdown-Dateien speichert, reicht es, den Ordner ~/Dokumente/Logseq in deine normale Datensicherung aufzunehmen. Die Dateien lassen sich auch ohne Logseq mit jedem Texteditor öffnen, z. B. mit GNU nano.

Aktualisieren

Snaps aktualisieren sich automatisch im Hintergrund. Sofort aktualisieren kannst du mit:

sudo snap refresh logseq

Deinstallieren

1. Logseq entfernen

Entfernt das Snap. --purge verhindert, dass Snap vorher eine Sicherungskopie anlegt, und löscht auch die Programmeinstellungen, die das Snap unter ~/snap/logseq gespeichert hat. Deine Notizen in ~/Dokumente/Logseq bleiben erhalten.

sudo snap remove --purge logseq

Prüfen: Die Ausgabe meldet, dass kein Snap namens logseq installiert ist.

snap list logseq

2. Optional: Notizen löschen

Achtung: Dieser Befehl löscht alle Notizen des Graphen endgültig. Nur ausführen, wenn du sie nicht mehr brauchst oder vorher gesichert hast.

rm -rf ~/Dokumente/Logseq

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

SiYuan

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

SiYuan ist ein Programm für Notizen und persönliches Wissensmanagement. Notizen bestehen aus Blöcken, die sich untereinander verlinken, einbetten und in Datenbank-Ansichten (Tabelle, Kanban, Kalender) auswerten lassen. Die Daten liegen lokal auf deinem Rechner.

Vorbemerkungen

  • Kein apt-Paket und kein Snap: SiYuan ist weder in den Ubuntu-Paketquellen noch als Snap erhältlich. Die Entwickler veröffentlichen aber auf GitHub ein fertiges .deb-Paket. Diese Anleitung installiert dieses Paket mit apt, damit die nötigen Abhängigkeiten automatisch mitinstalliert werden.
  • Version: Die Befehle verwenden die Version 3.8.5. Ist eine neuere Version erschienen, ersetzt du in den Befehlen die Versionsnummer. Die aktuelle Version steht auf der Seite https://github.com/siyuan-note/siyuan/releases/latest.
  • Speicherplatz: Das installierte Programm belegt etwa 700 MB.
  • Arbeitsbereich: SiYuan speichert alle Notizen in einem Ordner, dem Arbeitsbereich (standardmäßig ~/SiYuan). Die Notizen liegen dort in einem eigenen Format (.sy-Dateien), nicht als Markdown. Über das Menü lassen sie sich aber jederzeit als Markdown exportieren.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen der Abhängigkeiten kennt, die SiYuan braucht.

sudo apt update

2. In den Download-Ordner wechseln

Die Dateien der nächsten Schritte werden hier abgelegt.

cd ~/Downloads

3. Paket herunterladen

Lädt das .deb-Paket für 64-Bit-PCs (amd64) von der GitHub-Seite des Projekts herunter. Die Datei ist etwa 200 MB groß.

wget https://github.com/siyuan-note/siyuan/releases/download/v3.8.5/siyuan-3.8.5-linux.deb

4. Prüfsummen herunterladen

Die Datei enthält für jede Download-Datei eine Prüfsumme. Damit lässt sich feststellen, ob das Paket vollständig und unverändert angekommen ist.

wget https://github.com/siyuan-note/siyuan/releases/download/v3.8.5/SHA256SUMS.txt

5. Paket prüfen

Berechnet die Prüfsumme des heruntergeladenen Pakets und vergleicht sie mit der Liste. --ignore-missing überspringt die Einträge für Dateien, die du nicht heruntergeladen hast (z. B. für andere Systeme).

sha256sum --ignore-missing -c SHA256SUMS.txt

Prüfen: Die Ausgabe lautet siyuan-3.8.5-linux.deb: OK. Steht dort FEHLSCHLAG bzw. FAILED, lösche die Datei und lade sie erneut herunter.

6. SiYuan installieren

Installiert das Paket. Das ./ vor dem Dateinamen ist wichtig: Es sagt apt, dass es eine lokale Datei installieren soll und nicht nach einem Paket in den Paketquellen suchen. Fehlende Abhängigkeiten lädt apt automatisch aus den Ubuntu-Paketquellen nach. Das Paket richtet außerdem ein AppArmor-Profil ein, das SiYuan unter Ubuntu zum Starten braucht.

sudo apt install ./siyuan-3.8.5-linux.deb

Prüfen: Die Ausgabe zeigt Paketname und Version 3.8.5.

dpkg -l siyuan | tail -n 1

7. Heruntergeladene Dateien löschen

Nach der Installation werden die Dateien nicht mehr gebraucht.

rm siyuan-3.8.5-linux.deb SHA256SUMS.txt

Erste Schritte

8. SiYuan starten

Startet SiYuan. Alternativ findest du das Programm im Anwendungsmenü unter „SiYuan“.

siyuan &

9. Arbeitsbereich festlegen

Beim ersten Start fragt SiYuan, wo der Arbeitsbereich liegen soll. Der Vorschlag ~/SiYuan ist in Ordnung. Bestätige ihn.

Prüfen: SiYuan öffnet sich mit einem Notizbuch mit Einführungsdokumenten. Im Arbeitsbereich liegt jetzt unter anderem der Ordner data.

ls ~/SiYuan

10. Deutsche Oberfläche einstellen

Ist die Oberfläche nicht schon auf Deutsch, öffne die Einstellungen mit Alt+P oder über das Menü oben links. Wähle unter Appearance (Erscheinungsbild) bei Language (Sprache) den Eintrag Deutsch. SiYuan lädt die Oberfläche danach neu.

11. Die Grundlagen kennenlernen

Jeder Absatz, jede Überschrift und jeder Listenpunkt ist in SiYuan ein Block. Blöcke lassen sich über ihre Kennung verlinken und an anderer Stelle einbetten.

Eingabe / TastenWirkung
/Menü mit Befehlen öffnen, z. B. Überschrift, Tabelle, Datenbank, Aufgabe
((Auf einen anderen Block verweisen (Suche nach dem Block öffnet sich)
[[Auf ein anderes Dokument verweisen
#Tag#Schlagwort vergeben
{{Einen anderen Block einbetten (sein Inhalt wird hier angezeigt)
Strg+PSuche über alle Notizen
Alt+5Tagesnotiz für heute öffnen
Alt+PEinstellungen öffnen

Prüfen: Lege über das + neben einem Notizbuch ein neues Dokument an, tippe [[ und wähle ein Einführungsdokument aus. Ein Klick auf den Link öffnet das Dokument.

Optional: Notizen sichern

SiYuan legt im Arbeitsbereich regelmäßig eigene Datensicherungen an (Einstellungen → Datenverlauf und Datenrepository). Zusätzlich solltest du den Ordner ~/SiYuan in deine normale Datensicherung aufnehmen. Sicherer ist es, SiYuan vorher zu beenden, damit keine Datei gerade geschrieben wird.

Aktualisieren

SiYuan zeigt beim Start einen Hinweis, wenn eine neue Version erschienen ist. Weil das Paket nicht aus einem Paketarchiv stammt, aktualisiert sudo apt upgrade SiYuan nicht. Zum Aktualisieren wiederholst du die Schritte 2 bis 7 mit der neuen Versionsnummer. Das neue Paket ersetzt das alte, deine Notizen im Arbeitsbereich bleiben erhalten.

Deinstallieren

1. SiYuan beenden

Schließe alle SiYuan-Fenster. SiYuan läuft eventuell noch im Hintergrund weiter (Symbol in der oberen Leiste). Beende es dort über das Symbol mit Beenden.

Prüfen: Die Ausgabe ist leer, es läuft kein SiYuan-Prozess mehr.

pgrep -ai siyuan

2. SiYuan entfernen

Entfernt das Programm unter /opt/SiYuan, den Befehl siyuan und das AppArmor-Profil.

sudo apt purge siyuan

3. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten, die nur für SiYuan installiert wurden.

sudo apt autoremove

4. Programmeinstellungen entfernen

SiYuan speichert seine Programmeinstellungen, die Liste der Arbeitsbereiche und ein Protokoll in ~/.config/siyuan sowie Daten der Programmoberfläche in ~/.config/SiYuan-Electron. Deine Notizen sind dort nicht enthalten.

rm -rf ~/.config/siyuan ~/.config/SiYuan-Electron

Prüfen: Der Befehl wird nicht mehr gefunden.

siyuan --version

5. Optional: Notizen löschen

Achtung: Dieser Befehl löscht den Arbeitsbereich mit allen Notizen und Sicherungen endgültig. Nur ausführen, wenn du sie nicht mehr brauchst oder vorher exportiert bzw. gesichert hast.

rm -rf ~/SiYuan

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Excalidraw

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Excalidraw ist ein Zeichenprogramm für Skizzen, Diagramme und Schaubilder im Handzeichnungs-Stil. Es läuft im Browser. Zeichnungen lassen sich als offene JSON-Datei (.excalidraw) speichern oder als PNG bzw. SVG exportieren.

Vorbemerkungen

  • Kein apt-Paket, kein Snap: Excalidraw ist eine Web-App. Diese Anleitung baut sie aus dem offiziellen Quellcode und liefert sie mit nginx auf dem eigenen Rechner aus. So läuft sie ohne die Seite excalidraw.com.
  • Version: Verwendet wird die Version 0.18.1 (Git-Tag v0.18.1). Sie braucht Node.js 18 bis 22. Ubuntu 26.04 liefert Node.js 22, das passt.
  • Speicherplatz und Zeit: Die Build-Werkzeuge belegen etwa 1,1 GB, der Bau dauert je nach Rechner ein bis drei Minuten. Die fertige App ist etwa 45 MB groß.
  • Was lokal bleibt: Zeichnen, Speichern und Exportieren funktionieren komplett lokal. Die Funktionen Live-Zusammenarbeit, Link teilen und die Bibliothek mit fertigen Formen nutzen weiterhin die Server von excalidraw.com.

Vorbereitung

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Node.js, npm und Git kennt.

sudo apt update

2. Node.js, npm und Git installieren

Node.js und npm werden zum Bauen gebraucht, Git zum Herunterladen des Quellcodes. Ist alles schon vorhanden (z. B. aus der Docusaurus-Anleitung), meldet apt das nur.

sudo apt install nodejs npm git

Prüfen: Die Versionsnummer liegt zwischen v18 und v22, z. B. v22.22.1.

node --version

Zeigt der Befehl eine höhere Version (z. B. v25), stammt Node.js aus dem Versionsmanager nvm. Schalte dann für dieses Terminal auf das Node.js von Ubuntu um und prüfe erneut:

nvm use system

Excalidraw bauen

3. Quellcode herunterladen

Lädt den Quellcode der Version 0.18.1 nach ~/excalidraw. --depth 1 lädt nur diesen Stand ohne die gesamte Versionsgeschichte.

git clone --depth 1 -b v0.18.1 https://github.com/excalidraw/excalidraw.git ~/excalidraw

4. In den Quellcode-Ordner wechseln

Alle Befehle zum Bauen werden hier ausgeführt.

cd ~/excalidraw

5. Abhängigkeiten installieren

Excalidraw verwendet den Paketmanager Yarn in Version 1. Ubuntu liefert nur die neuere, nicht passende Yarn-Version 4. npx lädt deshalb genau die benötigte Version 1.22.22 herunter und führt sie aus. --frozen-lockfile installiert exakt die Versionen, die die Entwickler getestet haben.

npx --yes yarn@1.22.22 install --frozen-lockfile

Prüfen: Die Ausgabe endet mit Done in ….

6. App bauen

Erzeugt die fertige Web-App im Ordner excalidraw-app/build. Das Build-Skript heißt build:app:docker, hat aber nichts mit Docker zu tun: Es ist die Variante, die keine Fehlerberichte an den Dienst Sentry sendet und keine Nutzungsstatistik erhebt. Deshalb eignet sie sich für eine eigene Installation.

npx --yes yarn@1.22.22 build:app:docker

Prüfen: Die Ausgabe enthält ✓ built in …, und im Ordner liegt eine index.html.

ls excalidraw-app/build/index.html

Mit nginx ausliefern

7. Zielordner anlegen

Die fertige App wird nach /var/www/excalidraw kopiert, wo nginx sie lesen darf.

sudo mkdir -p /var/www/excalidraw

8. App kopieren

Kopiert den Inhalt des Build-Ordners. Der Punkt am Ende von build/. sorgt dafür, dass auch versteckte Dateien mitkommen.

sudo cp -r excalidraw-app/build/. /var/www/excalidraw/

9. nginx-Konfiguration anlegen

Excalidraw läuft auf Port 8087 und ist nur vom eigenen Rechner aus erreichbar. Die App besteht nur aus statischen Dateien, PHP oder ein anderer Dienst ist nicht nötig. Der zweite Block gibt der Datei manifest.webmanifest den richtigen Typ. Mit ihr kann der Browser Excalidraw als eigene App installieren.

sudo nano /etc/nginx/sites-available/excalidraw

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 127.0.0.1:8087;
    server_name localhost;

    root /var/www/excalidraw;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location = /manifest.webmanifest {
        default_type application/manifest+json;
    }
}

10. Konfiguration aktivieren

Ein Link in sites-enabled sorgt dafür, dass nginx die neue Seite lädt.

sudo ln -s /etc/nginx/sites-available/excalidraw /etc/nginx/sites-enabled/excalidraw

11. nginx-Konfiguration testen

Findet Tippfehler, bevor nginx neu geladen wird.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

12. nginx neu laden

Übernimmt die Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

Prüfen: Die Ausgabe enthält den Seitentitel Excalidraw.

curl -s http://localhost:8087/ | grep -o '<title>[^<]*'

Im Browser öffnet http://localhost:8087 die Zeichenfläche. Ist dein Browser auf Deutsch eingestellt, erscheint auch Excalidraw auf Deutsch. Sonst stellst du die Sprache im Menü (☰ oben links) ganz unten um.

13. Optional: Quellcode-Ordner löschen

Der Quellcode samt Build-Werkzeugen (etwa 1,1 GB) wird für den Betrieb nicht mehr gebraucht. Behalte ihn, wenn du später aktualisieren willst.

rm -rf ~/excalidraw

Das Dateiformat .excalidraw

Excalidraw merkt sich die aktuelle Zeichnung automatisch im Speicher des Browsers. Dieser Speicher gehört zur Adresse http://localhost:8087. Löschst du die Browserdaten, ist die Zeichnung weg. Wichtige Zeichnungen speicherst du deshalb mit Strg+S als Datei.

Eine .excalidraw-Datei ist lesbares JSON:

  • type ist immer "excalidraw", version die Formatversion (derzeit 2)
  • elements enthält alle Formen: Rechtecke, Pfeile, Texte usw., jeweils mit Position, Größe, Farben und einer eindeutigen id. Pfeile verweisen über diese id auf die Formen, die sie verbinden.
  • appState enthält Ansichtseinstellungen wie Hintergrundfarbe und Raster
  • files enthält eingefügte Bilder, als Text kodiert (Base64)

Beim Export als PNG oder SVG kannst du die Option Szene einbetten wählen. Dann steckt die komplette Zeichnung in der Bilddatei, und Excalidraw kann sie später wieder bearbeitbar öffnen.

Tipp: Wer Obsidian nutzt, kann Excalidraw-Zeichnungen mit der Community-Erweiterung „Excalidraw“ direkt im Vault ablegen und mit Notizen verlinken.

Aktualisieren

Für eine neue Version wiederholst du die Schritte 3 bis 8 mit der neuen Versionsnummer im Befehl git clone. Den alten Quellcode-Ordner löschst du vorher, den alten Inhalt von /var/www/excalidraw ebenfalls (sudo rm -rf /var/www/excalidraw/*). Neue Versionen stehen auf https://github.com/excalidraw/excalidraw/releases. Prüfe dort auch, welche Node.js-Version sie brauchen.

Deinstallieren

1. Seite in nginx deaktivieren

Löscht den Link aus sites-enabled.

sudo rm -f /etc/nginx/sites-enabled/excalidraw

2. nginx-Konfigurationsdatei löschen

Löscht die Konfigurationsdatei der Seite.

sudo rm -f /etc/nginx/sites-available/excalidraw

3. nginx neu laden

Übernimmt das Abschalten der Seite.

sudo systemctl reload nginx

4. App-Dateien löschen

Entfernt die ausgelieferte App.

sudo rm -rf /var/www/excalidraw

5. Quellcode und Zwischenspeicher löschen

Entfernt den Quellcode-Ordner (falls noch vorhanden) und das von npx zwischengespeicherte Yarn. Andere Projekte sind nicht betroffen, npx lädt benötigte Programme beim nächsten Aufruf neu.

rm -rf ~/excalidraw ~/.npm/_npx

6. Optional: Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (z. B. Antora, Docusaurus, VitePress oder Starlight).

sudo apt purge nodejs npm
sudo apt autoremove

Prüfen: Unter http://localhost:8087 antwortet kein Webserver mehr, curl meldet einen Verbindungsfehler.

curl -sI http://localhost:8087/

Zeichnungen, die du als .excalidraw-Datei gespeichert hast, bleiben erhalten. Die automatisch gemerkte Zeichnung im Browser verschwindet erst, wenn du die Browserdaten für localhost:8087 löschst.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Yjs und Automerge

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Yjs und Automerge sind Programmbibliotheken für JavaScript, mit denen mehrere Geräte oder Personen gleichzeitig dasselbe Dokument bearbeiten können, auch ohne ständige Verbindung. Änderungen werden später automatisch und ohne Konflikte zusammengeführt. Sie bilden den Kern vieler kollaborativer Editoren und Local-First-Anwendungen.

Vorbemerkungen

  • Was ist ein CRDT? Beide Bibliotheken beruhen auf CRDTs (Conflict-free Replicated Data Types, konfliktfreie replizierte Datentypen). Jedes Gerät hat eine vollständige Kopie des Dokuments und ändert sie lokal. Tauschen die Geräte ihre Änderungen aus, kommen alle garantiert zum selben Ergebnis, egal in welcher Reihenfolge die Änderungen eintreffen. Ein zentraler Server, der Konflikte entscheidet, ist nicht nötig.
  • Keine Programme, sondern Bibliotheken: Yjs und Automerge haben keine eigene Oberfläche. Man baut sie in eigene Anwendungen ein. Diese Anleitung richtet deshalb ein kleines Testprojekt ein und zeigt an zwei Beispielen, wie sie arbeiten.
  • Installation: Die Bibliotheken sind nicht in den Ubuntu-Paketquellen enthalten. Sie werden pro Projekt über npm installiert. Aus den Ubuntu-Paketquellen kommen nur Node.js und npm.
  • Versionen: Yjs 13.6 und Automerge 3.5.

Die beiden Bibliotheken im Vergleich

YjsAutomerge
SchwerpunktEchtzeit-Zusammenarbeit an Texten, sehr schnell und sparsamDokumente als JSON-ähnliche Daten mit vollständigem Verlauf
DatenmodellGemeinsame Typen: Y.Text, Y.Array, Y.Map, Y.XmlFragmentEin gewöhnliches JavaScript-Objekt, das über change() geändert wird
VerlaufNur der aktuelle Stand (Verlauf optional über Snapshots)Jede Änderung bleibt mit Beschreibung erhalten, ähnlich wie Commits in Git
SpeicherformatKompaktes Binärformat (Updates)Kompaktes Binärformat
UmsetzungReines JavaScriptKern in Rust, im Browser und in Node.js als WebAssembly
Typische EinsätzeEditoren wie Tiptap, ProseMirror, CodeMirror, MonacoLocal-First-Apps, Offline-Synchronisation

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Node.js und npm aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Node.js und npm installieren

Node.js führt die Beispielprogramme aus, npm lädt die Bibliotheken herunter. Ist beides schon vorhanden (z. B. aus der Docusaurus-Anleitung), meldet apt das nur.

sudo apt install nodejs npm

Prüfen: Die Versionsnummer wird angezeigt, z. B. v22.22.1.

node --version

Testprojekt einrichten

3. Projektordner anlegen

Ein eigener Ordner für die Beispiele.

mkdir ~/crdt-test

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/crdt-test

5. Projekt anlegen

Legt die Datei package.json an. Darin hält npm fest, welche Bibliotheken das Projekt braucht. -y übernimmt alle Vorgaben, ohne nachzufragen.

npm init -y

6. Moderne Modul-Schreibweise einschalten

Erlaubt in den Beispielen die Schreibweise import … from …, die heute in JavaScript üblich ist.

npm pkg set type=module

7. Yjs und Automerge installieren

Lädt beide Bibliotheken in den Ordner node_modules und trägt sie in package.json ein.

npm install yjs @automerge/automerge

Prüfen: Die Ausgabe zeigt @automerge/automerge@3.5.0 und yjs@13.6.33 (oder neuere Versionen).

npm ls --depth=0

Beispiel mit Yjs

8. Beispielprogramm anlegen

Das Programm spielt zwei Geräte durch, Laptop und Handy. Beide haben dieselbe Notiz „Einkauf: Brot“ und ergänzen sie gleichzeitig, ohne voneinander zu wissen: das eine um „Milch“, das andere um „Käse“. Danach tauschen sie ihre Änderungen aus. Die wichtigsten Funktionen:

  • new Y.Doc() – ein Dokument, also eine Kopie auf einem Gerät
  • getText('notiz') – ein gemeinsamer Text mit dem Namen notiz innerhalb des Dokuments
  • Y.encodeStateAsUpdate() – packt den Stand eines Dokuments in ein kompaktes Binärpaket (Update)
  • Y.applyUpdate() – spielt ein solches Paket in ein anderes Dokument ein

Am Ende wird der Stand als Datei notiz.yjs gespeichert und in ein neues Dokument geladen.

nano yjs-demo.mjs

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

import * as Y from 'yjs'
import { writeFileSync, readFileSync } from 'node:fs'

// Zwei Geräte mit je einer eigenen Kopie des Dokuments
const laptop = new Y.Doc()
const handy = new Y.Doc()

// Gemeinsamer Ausgangsstand: laptop schreibt, handy übernimmt den Stand
laptop.getText('notiz').insert(0, 'Einkauf: Brot')
Y.applyUpdate(handy, Y.encodeStateAsUpdate(laptop))

// Beide ändern gleichzeitig, ohne voneinander zu wissen
laptop.getText('notiz').insert(13, ', Milch')
handy.getText('notiz').insert(13, ', Käse')

// Änderungen in beide Richtungen austauschen
Y.applyUpdate(handy, Y.encodeStateAsUpdate(laptop))
Y.applyUpdate(laptop, Y.encodeStateAsUpdate(handy))

console.log('Laptop:', laptop.getText('notiz').toString())
console.log('Handy: ', handy.getText('notiz').toString())
console.log('Gleich:', laptop.getText('notiz').toString() === handy.getText('notiz').toString())

// Als kompakte Binärdatei speichern und in ein neues Dokument laden
writeFileSync('notiz.yjs', Y.encodeStateAsUpdate(laptop))
const geladen = new Y.Doc()
Y.applyUpdate(geladen, readFileSync('notiz.yjs'))
console.log('Geladen:', geladen.getText('notiz').toString())

9. Beispiel ausführen

Startet das Programm mit Node.js.

node yjs-demo.mjs

Prüfen: Beide Geräte zeigen denselben Text mit beiden Ergänzungen, z. B. Einkauf: Brot, Milch, Käse, und Gleich: true. Die Reihenfolge von Milch und Käse kann bei jedem Start anders sein, weil jedes Dokument eine zufällige Kennung bekommt. Entscheidend ist, dass beide Geräte immer dasselbe Ergebnis haben. Die Datei notiz.yjs ist nur etwa 60 Byte groß.

Beispiel mit Automerge

10. Beispielprogramm anlegen

Dasselbe Szenario mit einer Aufgabenliste. Bei Automerge ist das Dokument ein gewöhnliches JavaScript-Objekt. Die wichtigsten Funktionen:

  • Automerge.init() – ein leeres Dokument
  • Automerge.change(dokument, 'Beschreibung', d => { … }) – ändert das Dokument. Innerhalb der Klammern arbeitest du mit d wie mit einem normalen Objekt. Das Ergebnis ist ein neuer Stand, deshalb wird es wieder zugewiesen.
  • Automerge.clone() – eine unabhängige Kopie für ein zweites Gerät
  • Automerge.merge() – übernimmt die Änderungen eines anderen Stands
  • Automerge.getHistory() – alle Änderungen mit ihrer Beschreibung
  • Automerge.save() / Automerge.load() – Speichern als Binärdaten und Laden
nano automerge-demo.mjs

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

import * as Automerge from '@automerge/automerge'
import { writeFileSync, readFileSync } from 'node:fs'

// Gemeinsamer Ausgangsstand mit einer ersten, beschriebenen Änderung
let laptop = Automerge.change(Automerge.init(), 'Liste angelegt', d => {
  d.aufgaben = ['Brot kaufen']
})
let handy = Automerge.clone(laptop)

// Beide ändern gleichzeitig, ohne voneinander zu wissen
laptop = Automerge.change(laptop, 'Milch ergänzt', d => { d.aufgaben.push('Milch kaufen') })
handy = Automerge.change(handy, 'Käse ergänzt', d => { d.aufgaben.push('Käse kaufen') })

// Änderungen zusammenführen
laptop = Automerge.merge(laptop, handy)
handy = Automerge.merge(handy, laptop)

console.log('Laptop:', laptop.aufgaben)
console.log('Handy: ', handy.aufgaben)
console.log('Gleich:', JSON.stringify(laptop) === JSON.stringify(handy))

// Verlauf: jede Änderung bleibt mit ihrer Beschreibung erhalten
for (const eintrag of Automerge.getHistory(laptop)) {
  console.log('Änderung:', eintrag.change.message)
}

// Als kompakte Binärdatei speichern und wieder laden
writeFileSync('einkauf.automerge', Automerge.save(laptop))
const geladen = Automerge.load(readFileSync('einkauf.automerge'))
console.log('Geladen:', geladen.aufgaben)

11. Beispiel ausführen

Startet das Programm mit Node.js.

node automerge-demo.mjs

Prüfen: Beide Listen enthalten alle drei Aufgaben in derselben Reihenfolge, und es erscheint Gleich: true. Darunter stehen die drei Änderungen „Liste angelegt“, „Milch ergänzt“ und „Käse ergänzt“ aus dem Verlauf, zum Schluss die aus der Datei geladene Liste.

Wie geht es weiter?

Die Beispiele tauschen Änderungen direkt im selben Programm aus. In echten Anwendungen übernehmen das Zusatzbibliotheken, die ebenfalls über npm installiert werden:

  • Yjs: y-websocket synchronisiert über einen WebSocket-Server, y-webrtc direkt zwischen Browsern, y-indexeddb speichert Dokumente im Browser. Für Editoren gibt es fertige Anbindungen, z. B. y-prosemirror, y-codemirror.next und y-monaco.
  • Automerge: @automerge/automerge-repo verwaltet viele Dokumente, speichert sie und synchronisiert sie über Netzwerkadapter, z. B. über WebSocket oder zwischen Browser-Tabs.

Deinstallieren

1. Testprojekt entfernen

Löscht den Projektordner mit den Beispielen, den gespeicherten Dateien und den installierten Bibliotheken.

rm -rf ~/crdt-test

2. Optional: Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (z. B. Antora, Docusaurus, VitePress, Starlight oder Excalidraw).

sudo apt purge nodejs npm
sudo apt autoremove

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/crdt-test

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Drupal

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Drupal ist ein flexibles, modulares Open-Source-Content-Management-System (CMS) und Web-Framework. Auf dem Entwicklungsrechner dient es zum Aufbau komplexer Websites und Webanwendungen, die lokal mit Composer, nginx, PHP und PostgreSQL entwickelt und getestet werden.

Vorbereitung und PHP-Module

1. Paketlisten aktualisieren

Damit apt die aktuellen Paketdaten aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Benötigte PHP-Erweiterungen und Composer installieren

Drupal benötigt Composer sowie spezifische PHP-Erweiterungen für PostgreSQL (php-pgsql), mathematische Berechnungen (php-bcmath), Bildverarbeitung (php-gd), Unicode-Verarbeitung (php-intl), Caching (php-apcu), XML-Parsing und ZIP-Archive.

sudo apt install -y composer php-pgsql php-bcmath php-gd php-intl php-apcu php-curl php-mbstring php-xml php-zip

Prüfen: Listet die geladenen Module auf.

php -m | grep -E "pgsql|bcmath|gd|intl"

Datenbank in PostgreSQL einrichten

PostgreSQL sollte bereits installiert sein und laufen (siehe PostgreSQL-Anleitung).

3. PostgreSQL-Benutzer für Drupal anlegen

Erstellt einen dedizierten Datenbankbenutzer drupaluser mit einem sicheren Passwort.

sudo -u postgres psql -c "CREATE USER drupaluser WITH PASSWORD 'geheimes_passwort';"

4. Drupal-Datenbank anlegen

Erstellt die Datenbank drupaldb mit UTF-8-Zeichensatz und weist drupaluser als Eigentümer zu.

sudo -u postgres psql -c "CREATE DATABASE drupaldb OWNER drupaluser ENCODING 'UTF8';"

5. PostgreSQL-Erweiterung pg_trgm aktivieren

Drupal setzt für Volltext- und Ähnlichkeitsabfragen in PostgreSQL die Erweiterung pg_trgm voraus.

sudo -u postgres psql -d drupaldb -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"

Prüfen: Die Erweiterung ist in der Datenbank aktiv.

sudo -u postgres psql -d drupaldb -c "\dx pg_trgm"

Drupal mit Composer herunterladen und einrichten

6. Drupal-Projekt mit Composer erstellen

Erstellt über das offizielle Template drupal/recommended-project eine neue Drupal-Installation im Verzeichnis /var/www/drupal. Dabei werden automatisch alle PHP-Abhängigkeiten in vendor/ und das Web-Verzeichnis in web/ angelegt.

sudo composer create-project drupal/recommended-project /var/www/drupal

Prüfen: Das Verzeichnis /var/www/drupal/web existiert.

ls -ld /var/www/drupal/web

7. Drush als Befehlszeilenwerkzeug hinzufügen (optional)

Installiert Drush (The Drupal Shell) als Abhängigkeit im Projekt, um administrative Aufgaben und Installationen im Terminal durchzuführen.

sudo composer require --working-dir=/var/www/drupal drush/drush

8. Dateirechte für den Webserver anpassen

Überträgt die Eigentümerschaft des Drupal-Ordners an den Benutzer www-data, damit Drupal Dateien hochladen und Konfigurationen verwalten kann.

sudo chown -R www-data:www-data /var/www/drupal

nginx für Drupal konfigurieren

9. Konfiguration für Drupal anlegen

Erstellt einen Server-Block auf Port 8090, der nur vom eigenen Rechner aus erreichbar ist und auf das Web-Stammverzeichnis /var/www/drupal/web zeigt. nginx prüft die Blöcke mit regulären Ausdrücken (~) von oben nach unten und nimmt den ersten Treffer. Deshalb stehen die Sperren vor dem Block, der PHP ausführt:

  • Sperren: versteckte Dateien wie .git und .env, interne Drupal-Dateien (z. B. .yml-Einstellungen, .twig-Vorlagen) und PHP-Dateien im Upload-Ordner sites/…/files. So kann niemand eine hochgeladene Datei als Programm starten.
  • PHP: Alle .php-Dateien gehen an PHP-FPM. (/|$) erlaubt auch Adressen wie /update.php/selection, die Drupal bei Aktualisierungen verwendet.
  • Bilder, CSS, JavaScript: Der Browser darf sie 30 Tage zwischenspeichern. Fehlt eine Datei, reicht nginx die Anfrage an Drupal weiter. Drupal erzeugt verkleinerte Bilder und zusammengefasste CSS- und JavaScript-Dateien erst beim ersten Abruf.
  • Alles andere: Adressen wie /node/1 gibt es nicht als Datei. try_files reicht sie an index.php weiter, und Drupal entscheidet, welche Seite erscheint.
sudo nano /etc/nginx/sites-available/drupal

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 127.0.0.1:8090;
    server_name localhost;

    root /var/www/drupal/web;
    index index.php;

    client_max_body_size 20m;

    # Versteckte Dateien und Ordner (z. B. .git, .env) sperren
    location ~ /\.(?!well-known/) {
        return 403;
    }

    # Interne Drupal-Dateien sperren (Konfiguration, Vorlagen, Module)
    location ~* \.(engine|inc|install|module|profile|theme|twig|yml|yaml|sql|lock|log|md)$ {
        return 403;
    }

    # Hochgeladene Dateien dürfen nie als PHP ausgeführt werden
    location ~ ^/sites/[^/]+/files/.*\.php$ {
        return 403;
    }

    # PHP über PHP-FPM ausführen, auch mit Pfad dahinter (update.php/...)
    location ~ \.php(/|$) {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php-fpm.sock;
    }

    # Bilder, CSS und JavaScript: fehlt eine Datei, erzeugt Drupal sie
    location ~* \.(css|js|png|jpe?g|gif|ico|svg|webp|woff2?)$ {
        try_files $uri /index.php?$query_string;
        expires 30d;
        access_log off;
    }

    # Alle übrigen Adressen beantwortet Drupal über index.php
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

10. Konfiguration aktivieren

Erstellt einen symbolischen Link in sites-enabled.

sudo ln -s /etc/nginx/sites-available/drupal /etc/nginx/sites-enabled/drupal

11. nginx-Konfiguration prüfen

Prüft alle Konfigurationsdateien auf Syntaxfehler.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

12. nginx neu laden

Aktiviert die neue Seite im Webserver.

sudo systemctl reload nginx

Drupal initialisieren und testen

13. Drupal über Drush auf der Befehlszeile installieren

Richtet Drupal mit dem Standard-Profil, der PostgreSQL-Datenbank und einem Administrator-Konto ein.

sudo -u www-data /var/www/drupal/vendor/bin/drush site:install standard \
  --db-url='pgsql://drupaluser:geheimes_passwort@127.0.0.1/drupaldb' \
  --site-name='Mein Entwicklungs-Drupal' \
  --account-name='admin' \
  --account-pass='AdminPasswort123' \
  --yes \
  --root=/var/www/drupal/web

(Alternativ kann die Ersteinrichtung über den grafischen Installationsassistenten im Browser unter http://localhost:8090 aufgerufen werden.)

14. Website im Browser aufrufen

Prüft, ob Drupal Webanfragen beantwortet.

curl -sI http://localhost:8090/

Prüfen: Die Antwort liefert HTTP/1.1 200 OK. Im Browser erreichst du deine Drupal-Website unter http://localhost:8090.

Soll die Website unter einer eigenen Domain erreichbar sein, geht es weiter mit Drupal mit nginx unter eigener Domain.

Deinstallieren

1. Seite in nginx deaktivieren

Löscht die Verknüpfung aus sites-enabled.

sudo rm -f /etc/nginx/sites-enabled/drupal

2. nginx-Konfigurationsdatei löschen

Entfernt die Datei aus sites-available.

sudo rm -f /etc/nginx/sites-available/drupal

3. nginx neu laden

Übernimmt die Deaktivierung des Serverblocks.

sudo systemctl reload nginx

4. Drupal-Dateien löschen

Entfernt das gesamte Drupal-Projektverzeichnis.

sudo rm -rf /var/www/drupal

5. Drupal-Datenbank in PostgreSQL löschen

Löscht die Datenbank drupaldb. Achtung: Alle Inhalte und Tabellen gehen dabei verloren.

sudo -u postgres psql -c "DROP DATABASE IF EXISTS drupaldb;"

6. Datenbankbenutzer in PostgreSQL löschen

Entfernt den PostgreSQL-Benutzer drupaluser.

sudo -u postgres psql -c "DROP USER IF EXISTS drupaluser;"

7. Nicht mehr benötigte Pakete entfernen (optional)

Entfernt Composer und zusätzliche Module, falls sie nicht anderweitig gebraucht werden.

sudo apt purge composer php-bcmath

8. Verwaiste Abhängigkeiten bereinigen

Entfernt nicht mehr benötigte Systempakete.

sudo apt autoremove

Prüfen: Unter http://localhost:8090 antwortet kein Webserver mehr.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

MediaWiki

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

MediaWiki ist eine leistungsfähige Open-Source-Wiki-Software, die unter anderem die freie Enzyklopädie Wikipedia antreibt. Auf dem Entwicklungsrechner dient sie dazu, Wissenssammlungen, Dokumentationen oder eigene Erweiterungen lokal mit nginx, PHP und PostgreSQL einzurichten und zu testen.

Vorbemerkungen

  • Voraussetzungen: nginx, PHP mit PHP-FPM und PostgreSQL sind nach den jeweiligen Anleitungen installiert und laufen.
  • Installation über Git: Ubuntu enthält zwar ein Paket mediawiki, diese Anleitung holt MediaWiki aber direkt aus dem Git-Repository des Projekts. So lässt sich der Quellcode leicht untersuchen, auf neue Versionen umstellen und für eigene Erweiterungen nutzen.
  • Version: Verwendet wird die Version mit Langzeitunterstützung (LTS) 1.43 (Git-Zweig REL1_43). Sie läuft auch mit PHP 8.5 aus Ubuntu 26.04 ohne Fehlermeldungen.
  • Passwörter: geheimes_passwort und AdminPasswort123 sind Beispiele. Ersetze sie überall durch eigene Passwörter.

Vorbereitung und Abhängigkeiten

1. Paketlisten aktualisieren

Damit apt die aktuellen Paketstände der Ubuntu-Paketquellen kennt.

sudo apt update

2. PHP-Erweiterungen, Git und Composer installieren

MediaWiki braucht neben git und dem PHP-Paketmanager composer Module für die PostgreSQL-Anbindung (php-pgsql), Unicode-Verarbeitung (php-intl), Bildbearbeitung (php-gd), Zwischenspeicher (php-apcu), Netzwerkzugriffe (php-curl), Zeichenketten (php-mbstring) und XML (php-xml).

sudo apt install git composer php-pgsql php-intl php-gd php-apcu php-curl php-mbstring php-xml

Prüfen: Die Liste enthält apcu, gd, intl und pgsql.

php -m | grep -E "^(pgsql|intl|gd|apcu)$"

3. PHP-FPM neu starten

PHP-FPM lädt neu installierte Module erst nach einem Neustart. Ohne diesen Schritt kennt der Webserver z. B. die PostgreSQL-Anbindung noch nicht.

sudo systemctl restart php8.5-fpm

Datenbank in PostgreSQL einrichten

4. Datenbankbenutzer für MediaWiki anlegen

Erstellt einen eigenen Benutzer wikiuser in PostgreSQL. MediaWiki meldet sich mit diesem Benutzer und Passwort an der Datenbank an.

sudo -u postgres psql -c "CREATE USER wikiuser WITH PASSWORD 'geheimes_passwort';"

5. Datenbank für MediaWiki anlegen

Erstellt die leere Datenbank wikidb und macht wikiuser zu ihrem Eigentümer.

sudo -u postgres psql -c "CREATE DATABASE wikidb OWNER wikiuser;"

Prüfen: Die Datenbank wird in der Datenbankliste aufgeführt.

sudo -u postgres psql -l | grep wikidb

MediaWiki per Git herunterladen und einrichten

6. MediaWiki per Git klonen

Klont die LTS-Version in das Verzeichnis /var/www/mediawiki. Mit --depth 1 wird nur der aktuelle Stand ohne die gesamte Versionsgeschichte geladen, das spart Zeit und Speicherplatz.

sudo git clone -b REL1_43 --depth 1 https://gerrit.wikimedia.org/r/mediawiki/core.git /var/www/mediawiki

Prüfen: Das Verzeichnis enthält unter anderem index.php und composer.json.

ls /var/www/mediawiki

7. Standard-Design (Vector) per Git klonen

MediaWiki trennt den Kern von den Designs (Skins). Das bekannte Design Vector wird separat in den Ordner skins/Vector geklont. Der Git-Zweig muss zur Version von MediaWiki passen.

sudo git clone -b REL1_43 --depth 1 https://gerrit.wikimedia.org/r/mediawiki/skins/Vector /var/www/mediawiki/skins/Vector

8. Eigentümer auf deinen Benutzer ändern

Die Dateien gehören nach dem Klonen root. Als Entwickler sollst du sie ohne sudo bearbeiten, mit Git aktualisieren und Composer ausführen können. Der Webserver braucht nur Lesezugriff, der ohnehin besteht. Schreibrechte bekommt er in Schritt 12 gezielt für zwei Ordner.

sudo chown -R "$USER":"$USER" /var/www/mediawiki

9. Externe PHP-Bibliotheken mit Composer installieren

Installiert alle in composer.json festgelegten Bibliotheken in den Ordner vendor/. --no-dev lässt Werkzeuge weg, die nur zum Testen von MediaWiki selbst gebraucht werden.

composer install --no-dev -d /var/www/mediawiki

Prüfen: Der Ordner vendor enthält jetzt Unterordner, z. B. wikimedia.

ls /var/www/mediawiki/vendor

MediaWiki installieren

10. MediaWiki über die Kommandozeile installieren

Das Installationsskript legt die Tabellen in PostgreSQL an, erstellt das Administratorkonto WikiAdmin und schreibt die zentrale Einstellungsdatei LocalSettings.php. Die wichtigsten Angaben:

  • --server – Adresse, unter der das Wiki erreichbar ist (mit Port, sonst zeigen Links ins Leere)
  • --scriptpath "" – das Wiki liegt direkt unter /, nicht in einem Unterordner
  • --lang de – Oberfläche und Seitennamen auf Deutsch (z. B. „Hauptseite“)
  • die beiden letzten Angaben – Name des Wikis und Name des Administratorkontos

Das Skript erkennt das Design Vector im Ordner skins von selbst und trägt es in LocalSettings.php ein.

php /var/www/mediawiki/maintenance/run.php install \
  --dbtype postgres \
  --dbserver 127.0.0.1 \
  --dbname wikidb \
  --dbuser wikiuser \
  --dbpass 'geheimes_passwort' \
  --pass 'AdminPasswort123' \
  --server http://localhost:8085 \
  --scriptpath "" \
  --lang de \
  "Mein Entwicklungs-Wiki" \
  WikiAdmin

Prüfen: Die Ausgabe endet mit MediaWiki wurde erfolgreich installiert. In LocalSettings.php stehen die Adresse und das Design:

grep -E "wgServer|wfLoadSkin" /var/www/mediawiki/LocalSettings.php

11. Kurze Adressen einschalten

Ohne diese Einstellung erzeugt MediaWiki Links wie /index.php?title=Hauptseite. Mit ihr heißen sie einfach /Hauptseite. Die nginx-Konfiguration in Schritt 14 ist darauf abgestimmt.

nano /var/www/mediawiki/LocalSettings.php

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile an (im Terminal mit Strg+Umschalt+V). Speichere mit Strg+O und Enter und beende nano mit Strg+X:

$wgArticlePath = "/$1";

12. Schreibrechte für den Webserver vergeben

Der Webserver läuft als Benutzer www-data. Er muss hochgeladene Dateien im Ordner images speichern und im Ordner cache Zwischenergebnisse ablegen können.

sudo chown -R www-data:www-data /var/www/mediawiki/images /var/www/mediawiki/cache

13. Einstellungsdatei schützen

LocalSettings.php enthält das Datenbank-Passwort. Diese beiden Befehle erlauben das Lesen nur noch dir und der Gruppe www-data, also dem Webserver.

sudo chgrp www-data /var/www/mediawiki/LocalSettings.php
chmod 640 /var/www/mediawiki/LocalSettings.php

Prüfen: Die Rechte lauten -rw-r-----, die Gruppe ist www-data.

ls -l /var/www/mediawiki/LocalSettings.php

nginx konfigurieren

14. Konfiguration für MediaWiki anlegen

Erstellt einen eigenen Server-Block auf Port 8085, der nur vom eigenen Rechner aus erreichbar ist. Die Reihenfolge der Blöcke ist wichtig: nginx prüft Blöcke mit regulären Ausdrücken (~) von oben nach unten und nimmt den ersten Treffer. Deshalb stehen die Sperren für interne Ordner, versteckte Dateien (z. B. den Ordner .git) und Konfigurationsdateien vor dem Block, der PHP-Dateien ausführt. Für kurze Adressen wie /Hauptseite gibt es keine Datei. try_files übergibt sie deshalb an index.php. MediaWiki liest den Seitennamen aus der ursprünglichen Adresse, die nginx als REQUEST_URI mitschickt, und vergleicht sie mit $wgArticlePath aus Schritt 11.

sudo nano /etc/nginx/sites-available/mediawiki

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 127.0.0.1:8085;
    server_name localhost;

    root /var/www/mediawiki;
    index index.php;

    client_max_body_size 20m;

    # Interne Ordner und versteckte Dateien (z. B. .git) sperren
    location ~ /\. {
        return 403;
    }

    location ~ ^/(cache|includes|languages|maintenance|serialized|tests|vendor)/ {
        return 403;
    }

    location ~ \.(lock|json|yml|yaml|md)$ {
        return 403;
    }

    # Im Upload-Ordner keine PHP-Dateien ausführen
    location ^~ /images/ {
        location ~ \.php$ {
            return 403;
        }
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php-fpm.sock;
    }

    # Statische Dateien zwischenspeichern; fehlt die Datei, ist es eine
    # Wiki-Seite wie /Datei:Bild.png
    location ~* \.(js|css|png|jpe?g|gif|ico|svg|webp|woff2?)$ {
        try_files $uri /index.php?$args;
        expires 7d;
        access_log off;
    }

    # Kurze Adressen: Was es nicht als Datei gibt, bekommt index.php.
    # MediaWiki liest den Seitennamen selbst aus der ursprünglichen Adresse.
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
}

15. Konfiguration aktivieren

Ein Link in sites-enabled sorgt dafür, dass nginx die neue Seite lädt.

sudo ln -s /etc/nginx/sites-available/mediawiki /etc/nginx/sites-enabled/mediawiki

16. nginx-Konfiguration testen

Findet Tippfehler, bevor nginx neu geladen wird.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

17. nginx neu laden

Übernimmt die Konfiguration, ohne laufende Verbindungen abzubrechen.

sudo systemctl reload nginx

Testen

18. Hauptseite abrufen

Prüft, ob das Wiki unter der kurzen Adresse antwortet.

curl -sI http://localhost:8085/Hauptseite

Prüfen: Die erste Zeile lautet HTTP/1.1 200 OK. Im Browser leitet http://localhost:8085 auf die Hauptseite deines Wikis im Vector-Design weiter. Oben rechts kannst du dich mit WikiAdmin und dem Administrator-Passwort anmelden.

19. Sperren prüfen

Stichprobe, ob interne Dateien wirklich gesperrt sind. Hier am Beispiel des Git-Ordners, der sonst die Versionsgeschichte preisgeben würde.

curl -sI http://localhost:8085/.git/config

Prüfen: Die erste Zeile lautet HTTP/1.1 403 Forbidden.

Soll das Wiki unter einer eigenen Domain erreichbar sein, geht es weiter mit MediaWiki mit nginx unter eigener Domain.

Aktualisieren

Innerhalb der Version 1.43 erscheinen regelmäßig Fehler- und Sicherheitskorrekturen. So holst du sie:

1. Neuen Stand von MediaWiki holen

Lädt die Änderungen des Git-Zweigs REL1_43 herunter.

git -C /var/www/mediawiki pull

2. Neuen Stand des Designs holen

Das Design Vector ist ein eigenes Git-Repository und wird getrennt aktualisiert.

git -C /var/www/mediawiki/skins/Vector pull

3. Bibliotheken angleichen

Bringt die Bibliotheken in vendor/ auf den Stand, den die neue MediaWiki-Version erwartet.

composer update --no-dev -d /var/www/mediawiki

4. Datenbank anpassen

Passt die Tabellen an die neue Version an, falls nötig. --quick überspringt die Wartezeit vor dem Start.

php /var/www/mediawiki/maintenance/run.php update --quick

Prüfen: Die Ausgabe endet mit Done. Die Seite http://localhost:8085/Spezial:Version zeigt die neue Versionsnummer.

Deinstallieren

1. Seite in nginx deaktivieren

Löscht den Link aus sites-enabled.

sudo rm -f /etc/nginx/sites-enabled/mediawiki

2. nginx-Konfigurationsdatei löschen

Löscht die Konfigurationsdatei der Seite.

sudo rm -f /etc/nginx/sites-available/mediawiki

3. nginx neu laden

Übernimmt das Abschalten der Seite.

sudo systemctl reload nginx

4. MediaWiki-Dateien löschen

Entfernt den gesamten MediaWiki-Ordner. Achtung: Auch hochgeladene Dateien im Ordner images gehen verloren.

sudo rm -rf /var/www/mediawiki

5. MediaWiki-Datenbank löschen

Löscht die Datenbank wikidb. Achtung: Alle Seiten und Daten des Wikis werden dabei unwiderruflich gelöscht.

sudo -u postgres psql -c "DROP DATABASE IF EXISTS wikidb;"

6. Datenbankbenutzer löschen

Löscht den Benutzer wikiuser.

sudo -u postgres psql -c "DROP USER IF EXISTS wikiuser;"

7. Nicht mehr benötigte Pakete entfernen (optional)

Entfernt Composer und den PHP-Zwischenspeicher, falls sie nicht für andere Projekte gebraucht werden. Die übrigen PHP-Module aus Schritt 2 brauchen oft auch andere PHP-Anwendungen und bleiben deshalb erhalten.

sudo apt purge composer php-apcu
sudo apt autoremove

Prüfen: Unter http://localhost:8085 antwortet kein Webserver mehr, curl meldet einen Verbindungsfehler.

curl -sI http://localhost:8085/

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

LangGraph und LangChain

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

LangChain und LangGraph sind Python-Bibliotheken, mit denen man Anwendungen rund um große Sprachmodelle (LLMs) baut: Chatbots, Agenten, die selbstständig Werkzeuge aufrufen, oder mehrstufige Abläufe. LangGraph beschreibt solche Abläufe als Graph aus Schritten mit gemeinsamem Zustand. LangChain liefert darauf aufbauend fertige Bausteine wie Agenten und Anbindungen an viele Modellanbieter.

Vorbemerkungen

  • Das Ökosystem: Die Pakete bauen aufeinander auf:

    PaketAufgabe
    langchain-coreGemeinsame Grundlagen: Nachrichten, Werkzeuge, Schnittstelle für Chat-Modelle
    langgraphAbläufe als Graph mit Zustand, Verzweigungen, Schleifen und Gedächtnis
    langchainFertige Bausteine, vor allem create_agent für Agenten mit Werkzeugen. Baut intern auf LangGraph auf.
    langchain-anthropicAnbindung an Claude von Anthropic. Für andere Anbieter gibt es entsprechende Pakete, z. B. langchain-openai oder langchain-ollama.
    LangSmithOptionaler Online-Dienst zum Nachverfolgen und Auswerten von Abläufen. Wird in dieser Anleitung nicht verwendet.
  • Installation über pip: Die Pakete sind nicht in den Ubuntu-Paketquellen enthalten. Sie werden mit pip in eine virtuelle Umgebung (venv) installiert. Das ist ein eigener Ordner nur für dieses Projekt. Ubuntu verhindert absichtlich, dass pip Pakete systemweit installiert, damit die Python-Pakete des Systems nicht durcheinandergeraten.

  • Versionen: LangGraph 1.2, LangChain 1.4 und langchain-anthropic 1.7 unter Python 3.14.

  • Sprachmodell: Das Beispiel mit Agent verwendet Claude Opus 5. Dafür brauchst du einen API-Schlüssel von Anthropic (https://console.anthropic.com), und jede Anfrage kostet Geld. Das erste Beispiel kommt ohne Sprachmodell aus.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version des Pakets für virtuelle Umgebungen kennt.

sudo apt update

2. Unterstützung für virtuelle Umgebungen installieren

python3-venv enthält das Werkzeug, mit dem Python virtuelle Umgebungen anlegt. Python selbst ist unter Ubuntu schon installiert.

sudo apt install python3-venv

3. Projektordner anlegen

Ein eigener Ordner für die Beispiele.

mkdir ~/langgraph-test

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/langgraph-test

5. Virtuelle Umgebung anlegen

Legt die Umgebung im Unterordner .venv an. Dort landen später alle Pakete dieses Projekts.

python3 -m venv .venv

6. Virtuelle Umgebung aktivieren

Sorgt dafür, dass python und pip in diesem Terminal die Umgebung verwenden. Das musst du in jedem neuen Terminal wiederholen, bevor du mit dem Projekt arbeitest.

source .venv/bin/activate

Prüfen: Vor der Eingabeaufforderung steht jetzt (.venv).

7. LangGraph, LangChain und die Claude-Anbindung installieren

Installiert die drei Pakete samt Abhängigkeiten (darunter langchain-core und das Anthropic-SDK). -U holt jeweils die neueste Version.

pip install -U langgraph langchain langchain-anthropic

Prüfen: Die Liste zeigt die installierten Versionen, z. B. langgraph 1.2.12.

pip list | grep -E "^(langgraph|langchain|anthropic) "

Beispiel 1: Ein Graph ohne Sprachmodell

8. Beispielprogramm anlegen

Das Programm zeigt die Grundbegriffe von LangGraph, ganz ohne KI:

  • Zustand (Zustand) – die Daten, die durch den Graphen wandern. Hier ein Text und die Anzahl seiner Wörter.
  • Knoten (add_node) – einzelne Schritte, jeweils eine normale Python-Funktion. Sie bekommen den Zustand und geben die Felder zurück, die sie ändern.
  • Kanten (add_edge) – feste Übergänge von einem Knoten zum nächsten. START und END markieren Anfang und Ende.
  • Bedingte Kante (add_conditional_edges) – eine Weiche, die anhand des Zustands entscheidet, welcher Knoten als Nächstes kommt.
nano graph_demo.py

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

from typing import TypedDict

from langgraph.graph import StateGraph, START, END


# Der Zustand: Daten, die von Knoten zu Knoten weitergereicht werden
class Zustand(TypedDict):
    text: str
    woerter: int


# Knoten sind einfache Funktionen: Sie bekommen den Zustand und
# geben die Felder zurück, die sie ändern
def zaehlen(zustand: Zustand) -> dict:
    return {"woerter": len(zustand["text"].split())}


def kurz(zustand: Zustand) -> dict:
    return {"text": zustand["text"].upper()}


def lang(zustand: Zustand) -> dict:
    return {"text": zustand["text"][:20] + " …"}


# Bedingte Kante: entscheidet anhand des Zustands, wohin es weitergeht
def weiche(zustand: Zustand) -> str:
    return "kurz" if zustand["woerter"] <= 3 else "lang"


graph = StateGraph(Zustand)
graph.add_node("zaehlen", zaehlen)
graph.add_node("kurz", kurz)
graph.add_node("lang", lang)
graph.add_edge(START, "zaehlen")
graph.add_conditional_edges("zaehlen", weiche, ["kurz", "lang"])
graph.add_edge("kurz", END)
graph.add_edge("lang", END)
app = graph.compile()

print(app.invoke({"text": "Hallo LangGraph"}))
print(app.invoke({"text": "Dies ist ein etwas längerer Satz zum Testen"}))
print(app.get_graph().draw_mermaid())

9. Beispiel ausführen

Startet das Programm in der virtuellen Umgebung.

python graph_demo.py

Prüfen: Die ersten beiden Zeilen lauten:

{'text': 'HALLO LANGGRAPH', 'woerter': 2}
{'text': 'Dies ist ein etwas l …', 'woerter': 8}

Der kurze Text ging also über den Knoten kurz, der lange über lang. Darunter steht der Aufbau des Graphen als Mermaid-Diagramm. Du kannst es z. B. in mdBook oder MkDocs mit einer Mermaid-Erweiterung oder auf https://mermaid.live anzeigen lassen.

Beispiel 2: Ein Agent mit Claude

10. API-Schlüssel eingeben

Die Claude-Anbindung liest den Schlüssel aus der Umgebungsvariablen ANTHROPIC_API_KEY. read -rs fragt ihn ab, ohne ihn anzuzeigen. So landet er weder auf dem Bildschirm noch im Befehlsverlauf. Füge den Schlüssel ein und drücke Enter.

read -rsp "API-Schlüssel: " ANTHROPIC_API_KEY

11. API-Schlüssel für Programme freigeben

export macht die Variable für Programme sichtbar, die aus diesem Terminal gestartet werden. Sie gilt nur, bis das Terminal geschlossen wird.

export ANTHROPIC_API_KEY

Prüfen: Die Ausgabe ist eine Zahl über 0 (die Länge des Schlüssels), nicht der Schlüssel selbst.

echo ${#ANTHROPIC_API_KEY}

12. Agent-Programm anlegen

Ein Agent ist ein Sprachmodell, das selbst entscheidet, ob und wann es Werkzeuge aufruft. Das Programm verwendet:

  • tage_bis – ein Werkzeug: eine normale Python-Funktion. Aus Name, Parametern und Docstring erkennt das Modell, wofür es da ist.
  • ChatAnthropic – die Anbindung an Claude Opus 5 (claude-opus-5). max_tokens begrenzt die Länge einer Antwort. betas und fallbacks schalten eine Absicherung ein: Lehnen die Sicherheitsfilter von Anthropic eine Anfrage ab, beantwortet sie automatisch ein anderes passendes Claude-Modell.
  • create_agent – baut aus Modell, Werkzeugen und Anweisung (system_prompt) einen fertigen Agenten. Intern ist das ein LangGraph-Graph mit Schleife: Modell fragen → Werkzeug ausführen → Modell erneut fragen, bis eine Antwort vorliegt.
  • InMemorySaver – das Gedächtnis. Es speichert den Gesprächsverlauf pro Unterhaltung, erkennbar an der thread_id. Deshalb versteht der Agent bei der zweiten Frage, worauf sich „Und in Wochen?“ bezieht.
nano agent_demo.py

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

from datetime import date

from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
from langgraph.checkpoint.memory import InMemorySaver


# Ein Werkzeug (Tool): eine normale Python-Funktion. Der Docstring
# erklärt dem Modell, wofür das Werkzeug da ist.
def tage_bis(datum: str) -> str:
    """Berechnet, wie viele Tage es noch bis zu einem Datum (JJJJ-MM-TT) sind."""
    ziel = date.fromisoformat(datum)
    return f"Noch {(ziel - date.today()).days} Tage bis {datum}."


modell = ChatAnthropic(
    model="claude-opus-5",
    max_tokens=16000,
    # Bei einer Ablehnung durch Sicherheitsfilter automatisch auf ein
    # geeignetes anderes Claude-Modell ausweichen
    betas=["server-side-fallback-2026-07-01"],
    model_kwargs={"fallbacks": "default"},
)

agent = create_agent(
    modell,
    tools=[tage_bis],
    system_prompt="Du bist ein hilfreicher Assistent. Antworte kurz und auf Deutsch.",
    # Merkt sich den Gesprächsverlauf pro Unterhaltung (thread_id)
    checkpointer=InMemorySaver(),
)

unterhaltung = {"configurable": {"thread_id": "test-1"}}

antwort = agent.invoke(
    {"messages": [{"role": "user", "content": "Wie viele Tage sind es noch bis Silvester 2026?"}]},
    unterhaltung,
)
print(antwort["messages"][-1].text)

antwort = agent.invoke(
    {"messages": [{"role": "user", "content": "Und in Wochen?"}]},
    unterhaltung,
)
print(antwort["messages"][-1].text)

13. Agent ausführen

Startet den Agenten. Er stellt zwei Anfragen an Claude, die erste davon mit einem Werkzeugaufruf. Das dauert einige Sekunden und kostet wenige Cent.

python agent_demo.py

Prüfen: Es erscheinen zwei deutsche Antworten: zuerst die Anzahl der Tage bis zum 31.12.2026 (vom Werkzeug berechnet), dann dieselbe Zeitspanne in Wochen. Der genaue Wortlaut ändert sich bei jedem Aufruf.

Erscheint stattdessen ein Fehler mit authentication_error, ist der Schlüssel falsch oder fehlt. Wiederhole dann die Schritte 10 und 11.

Wie geht es weiter?

  • Eigene Graphen mit Modell: Ein Knoten kann auch modell.invoke(...) aufrufen. So lassen sich feste Abläufe bauen, in denen das Modell nur an bestimmten Stellen gefragt wird, z. B. erst Text zusammenfassen, dann prüfen, dann übersetzen.
  • Dauerhaftes Gedächtnis: InMemorySaver vergisst alles, wenn das Programm endet. Das Paket langgraph-checkpoint-postgres speichert den Verlauf stattdessen in PostgreSQL.
  • Wissen aus eigenen Dokumenten (RAG): Mit Embeddings und einem Vektorspeicher wie pgvector findet der Agent passende Textstellen und bezieht sie in seine Antworten ein.
  • Menschliche Freigabe: Mit interrupt_before hält der Agent vor bestimmten Schritten an und wartet auf eine Bestätigung.

Deinstallieren

1. Virtuelle Umgebung verlassen

Schaltet das Terminal zurück auf das Python des Systems. (.venv) verschwindet aus der Eingabeaufforderung.

deactivate

2. Projekt entfernen

Löscht den Projektordner samt virtueller Umgebung und allen darin installierten Paketen. Außerhalb dieses Ordners hat pip nichts installiert.

rm -rf ~/langgraph-test

3. Zwischenspeicher von pip leeren (optional)

pip hebt heruntergeladene Pakete in einem Zwischenspeicher auf, um spätere Installationen zu beschleunigen.

rm -rf ~/.cache/pip

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/langgraph-test

Hinweis: Den API-Schlüssel kannst du in der Anthropic Console jederzeit sperren oder löschen, wenn du ihn nicht mehr brauchst.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Qdrant

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Qdrant ist eine Vektordatenbank. Sie speichert Vektoren, etwa Embeddings von Texten oder Bildern, zusammen mit beliebigen Zusatzdaten und findet in Millisekunden die Einträge, die einem Suchvektor am ähnlichsten sind. Damit ist sie ein typischer Baustein für semantische Suche und RAG-Anwendungen (Sprachmodelle, die in eigenen Dokumenten nachschlagen).

Vorbemerkungen

  • Kein apt-Paket und kein offizielles Snap: Qdrant ist nicht in den Ubuntu-Paketquellen enthalten. Die Entwickler veröffentlichen aber auf GitHub ein fertiges .deb-Paket, das diese Anleitung mit apt installiert.
  • Das Paket ist schlicht: Es enthält nur das Programm /usr/bin/qdrant, eine Einstellungsdatei und die Weboberfläche. Einen Systembenutzer und einen systemd-Dienst legt es nicht an. Das erledigst du in den Schritten 7 bis 12.
  • Version: Die Befehle verwenden Version 1.19.1. Ist eine neuere Version erschienen, ersetzt du in den Befehlen die Versionsnummer und die Prüfsumme. Beides steht auf https://github.com/qdrant/qdrant/releases/latest.
  • Nur lokal erreichbar: Ohne weitere Einstellung lauscht Qdrant auf allen Netzwerkschnittstellen, ohne Passwort. Diese Anleitung beschränkt es auf den eigenen Rechner (127.0.0.1) und schaltet die anonyme Nutzungsstatistik ab, die Qdrant sonst an die Hersteller sendet.
  • Alternative: Wer Vektoren direkt neben seinen übrigen Daten ablegen möchte, kann auch PostgreSQL mit pgvector verwenden. Qdrant ist dagegen auf Vektorsuche spezialisiert und bringt eigene Filter, eine Weboberfläche und Werkzeuge zum Skalieren mit.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen der Hilfsprogramme kennt.

sudo apt update

2. Hilfsprogramme installieren

wget lädt das Paket herunter, mit curl sprichst du später die Datenbank an. Beide sind meist schon vorhanden.

sudo apt install wget curl

3. In den Download-Ordner wechseln

Das Paket wird hier abgelegt.

cd ~/Downloads

4. Paket herunterladen

Lädt das offizielle .deb-Paket für 64-Bit-PCs (amd64) herunter, etwa 25 MB.

wget https://github.com/qdrant/qdrant/releases/download/v1.19.1/qdrant_1.19.1-1_amd64.deb

5. Paket prüfen

Vergleicht die Prüfsumme der heruntergeladenen Datei mit dem Wert, den GitHub auf der Release-Seite neben der Datei anzeigt (sha256:…). So erkennst du, ob die Datei vollständig und unverändert angekommen ist.

echo "858dda511c5c05bb5ceb19d7f79669c1e13a64390df205eee6f33b929a0a9a84  qdrant_1.19.1-1_amd64.deb" | sha256sum -c

Prüfen: Die Ausgabe lautet qdrant_1.19.1-1_amd64.deb: OK. Bei FEHLSCHLAG bzw. FAILED löschst du die Datei und lädst sie erneut herunter.

6. Qdrant installieren

Installiert das Paket. Das ./ vor dem Dateinamen sagt apt, dass es eine lokale Datei installieren soll.

sudo apt install ./qdrant_1.19.1-1_amd64.deb

Prüfen: Die Ausgabe lautet qdrant 1.19.1.

qdrant --version

Die heruntergeladene Datei kannst du danach löschen:

rm qdrant_1.19.1-1_amd64.deb

Als Dienst einrichten

7. Systembenutzer anlegen

Qdrant soll nicht mit Administratorrechten laufen, sondern als eigener Benutzer qdrant ohne Anmeldemöglichkeit. --system legt einen Benutzer für Dienste an, --home-dir setzt sein Verzeichnis auf den Datenordner.

sudo useradd --system --home-dir /var/lib/qdrant --shell /usr/sbin/nologin qdrant

8. Datenordner übergeben

Der Benutzer qdrant muss in /var/lib/qdrant schreiben dürfen. Dort legt Qdrant die Unterordner storage (Daten) und snapshots (Sicherungen) an. Die Weboberfläche liegt ebenfalls hier, im Ordner static.

sudo chown -R qdrant:qdrant /var/lib/qdrant

9. systemd-Dienst anlegen

Die Dienstdatei sorgt dafür, dass systemd Qdrant startet, beim Systemstart automatisch hochfährt und nach einem Absturz neu startet. Die wichtigsten Angaben:

  • User, Group – Qdrant läuft als Benutzer qdrant
  • ExecStart – startet Qdrant mit der Einstellungsdatei aus dem Paket
  • QDRANT__SERVICE__HOST=127.0.0.1 – nur vom eigenen Rechner aus erreichbar
  • QDRANT__TELEMETRY_DISABLED=true – keine Nutzungsstatistik an die Hersteller
  • LimitNOFILE – erlaubt viele gleichzeitig geöffnete Dateien, die Qdrant bei vielen Daten braucht

Umgebungsvariablen, die mit QDRANT__ beginnen, überschreiben Einstellungen aus der Datei. So bleibt /etc/qdrant/config.yaml unverändert und wird bei Updates nicht zum Konflikt.

sudo nano /etc/systemd/system/qdrant.service

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

[Unit]
Description=Qdrant Vektordatenbank
After=network.target

[Service]
User=qdrant
Group=qdrant
WorkingDirectory=/var/lib/qdrant
ExecStart=/usr/bin/qdrant --config-path /etc/qdrant/config.yaml
Environment=QDRANT__SERVICE__HOST=127.0.0.1
Environment=QDRANT__TELEMETRY_DISABLED=true
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

10. systemd die neue Datei bekannt machen

systemd liest neue oder geänderte Dienstdateien erst nach diesem Befehl ein.

sudo systemctl daemon-reload

11. Dienst starten und Autostart einschalten

enable sorgt für den Start bei jedem Hochfahren, --now startet den Dienst zusätzlich sofort.

sudo systemctl enable --now qdrant

Prüfen: In der Ausgabe steht Active: active (running). Mit q verlässt du die Anzeige.

systemctl status qdrant

12. Adresse und Telemetrie prüfen

Zeigt die Startmeldungen des Dienstes. Die zwei Warnungen Config file not found: config/… sind harmlos: Qdrant sucht zusätzlich nach Einstellungsdateien im Arbeitsordner, die es hier nicht gibt.

sudo journalctl -u qdrant --no-pager | grep -E "Telemetry|listening on:"

Prüfen: Die Ausgabe enthält Telemetry reporting disabled und listening on: 127.0.0.1:6333.

Erste Schritte

Qdrant wird über eine REST-Schnittstelle auf Port 6333 angesprochen (und über gRPC auf Port 6334 für schnelle Programmanbindungen). Die folgenden Schritte verwenden curl und das gleiche Beispiel wie die pgvector-Anleitung: drei Einträge mit kleinen Vektoren aus drei Zahlen. Echte Embeddings haben meist mehrere hundert Zahlen.

13. Verbindung testen

Fragt Name und Version des Servers ab.

curl -s http://localhost:6333/

Prüfen: Die Antwort enthält "version":"1.19.1".

14. Sammlung anlegen

Eine Sammlung (Collection) entspricht einer Tabelle. Beim Anlegen legst du fest, wie viele Zahlen jeder Vektor hat (size) und wie Ähnlichkeit gemessen wird (distance). Cosine vergleicht die Richtung der Vektoren, das ist für Text-Embeddings üblich.

curl -s -X PUT http://localhost:6333/collections/notizen -H 'Content-Type: application/json' -d '{"vectors": {"size": 3, "distance": "Cosine"}}'

Prüfen: Die Antwort lautet {"result":true,"status":"ok",…}.

15. Einträge einfügen

Ein Eintrag heißt in Qdrant Punkt (Point). Er besteht aus einer id, dem Vektor und einer frei gestaltbaren Payload mit Zusatzdaten im JSON-Format. wait=true wartet, bis die Daten gespeichert sind.

curl -s -X PUT 'http://localhost:6333/collections/notizen/points?wait=true' -H 'Content-Type: application/json' -d '{
  "points": [
    {"id": 1, "vector": [1, 0, 0],     "payload": {"text": "Apfel", "art": "obst"}},
    {"id": 2, "vector": [0.9, 0.1, 0], "payload": {"text": "Birne", "art": "obst"}},
    {"id": 3, "vector": [0, 0, 1],     "payload": {"text": "Auto",  "art": "fahrzeug"}}
  ]
}'

Prüfen: Die Antwort enthält "status":"completed".

16. Ähnlichkeitssuche

Sucht die zwei Punkte, die dem Suchvektor am ähnlichsten sind. score gibt die Ähnlichkeit an: Je näher an 1, desto ähnlicher. with_payload liefert die Zusatzdaten mit.

curl -s -X POST http://localhost:6333/collections/notizen/points/query -H 'Content-Type: application/json' -d '{"query": [1, 0.05, 0], "limit": 2, "with_payload": true}'

Prüfen: Die Antwort enthält zuerst Apfel, dann Birne, beide mit einem score knapp unter 1. Auto fehlt, weil es nicht ähnlich ist.

17. Suche mit Filter

Eine Stärke von Qdrant: Suche und Filter auf die Payload lassen sich kombinieren. Dieselbe Suche wie oben, aber nur unter Einträgen mit art = fahrzeug.

curl -s -X POST http://localhost:6333/collections/notizen/points/query -H 'Content-Type: application/json' -d '{"query": [1, 0.05, 0], "limit": 2, "with_payload": true, "filter": {"must": [{"key": "art", "match": {"value": "fahrzeug"}}]}}'

Prüfen: Die Antwort enthält nur noch Auto, obwohl es dem Suchvektor gar nicht ähnlich ist. Der Filter wird zuerst angewendet.

18. Weboberfläche öffnen

Qdrant bringt eine Weboberfläche mit. Dort siehst du Sammlungen und Punkte, kannst Vektoren grafisch darstellen und Anfragen in einer Konsole ausprobieren.

Prüfen: http://localhost:6333/dashboard zeigt die Sammlung notizen mit 3 Punkten.

19. Beispiel-Sammlung löschen

Entfernt die Sammlung samt aller Punkte wieder.

curl -s -X DELETE http://localhost:6333/collections/notizen

Aus Programmen verwenden

Für viele Sprachen gibt es offizielle Client-Bibliotheken, z. B. qdrant-client für Python (mit pip in einer virtuellen Umgebung, siehe LangGraph-Anleitung) oder @qdrant/js-client-rest für JavaScript. LangChain bindet Qdrant über das Paket langchain-qdrant als Vektorspeicher an.

Optional: Zugriff mit API-Schlüssel schützen

Auf einem Entwicklungsrechner, auf dem nur du arbeitest, reicht die Beschränkung auf 127.0.0.1. Nutzen weitere Personen den Rechner, kannst du einen Schlüssel verlangen. Dazu ergänzt du in der Dienstdatei aus Schritt 9 im Abschnitt [Service] eine Zeile wie Environment=QDRANT__SERVICE__API_KEY=ein-langes-geheimes-wort und wiederholst die Schritte 10 und 11 (bei laufendem Dienst: sudo systemctl restart qdrant). Anfragen müssen den Schlüssel dann im Kopf api-key mitschicken, z. B. curl -H 'api-key: ein-langes-geheimes-wort' ….

Aktualisieren

Das Paket stammt nicht aus einem Paketarchiv, deshalb aktualisiert sudo apt upgrade Qdrant nicht. Für eine neue Version wiederholst du die Schritte 3 bis 6 mit neuer Versionsnummer und Prüfsumme und startest danach den Dienst neu:

sudo systemctl restart qdrant

Deine Daten in /var/lib/qdrant/storage bleiben dabei erhalten. Lies vorher die Versionshinweise: Qdrant unterstützt Updates nur schrittweise über jeweils eine Nebenversion (z. B. von 1.18 auf 1.19, nicht direkt von 1.17 auf 1.19).

Deinstallieren

1. Dienst stoppen und Autostart ausschalten

Beendet Qdrant und verhindert den Start beim Hochfahren.

sudo systemctl disable --now qdrant

2. Dienstdatei löschen

Entfernt die Datei aus Schritt 9.

sudo rm /etc/systemd/system/qdrant.service

3. systemd neu einlesen

Damit systemd den gelöschten Dienst vergisst.

sudo systemctl daemon-reload

4. Qdrant entfernen

purge entfernt das Programm, die Weboberfläche und die Einstellungsdatei /etc/qdrant/config.yaml.

sudo apt purge qdrant

5. Daten löschen

Achtung: Löscht alle Sammlungen, Punkte und Sicherungen endgültig.

sudo rm -rf /var/lib/qdrant

6. Systembenutzer löschen

Entfernt den Benutzer qdrant aus Schritt 7.

sudo userdel qdrant

Prüfen: Der Befehl wird nicht mehr gefunden.

qdrant --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Milvus

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Milvus ist eine quelloffene Vektordatenbank. Sie speichert Vektoren, etwa Embeddings von Texten oder Bildern, zusammen mit weiteren Feldern und findet die Einträge, die einem Suchvektor am ähnlichsten sind. Milvus ist für sehr große Datenmengen gebaut und wird oft für semantische Suche und RAG-Anwendungen eingesetzt.

Vorbemerkungen

  • Welche Variante? Milvus gibt es in mehreren Formen:

    VarianteBeschreibungIn dieser Anleitung
    Milvus LiteOffizielle, schlanke Ausgabe für Python. Läuft im eigenen Programm oder als kleiner Server, die Daten liegen in einem Ordner.ja
    Milvus Standalone / DistributedVollständiger Server für große Datenmengen. Wird offiziell über Docker oder Kubernetes betrieben.nein
    .deb-Paket von Milvus StandaloneGab es auf GitHub, zuletzt für Version 2.6.18 (Juni 2026). Neuere Versionen erscheinen nicht mehr als Paket. Der Dienst läuft außerdem als root und ist ohne Anpassung aus dem Netz erreichbar.nein

    Diese Anleitung verwendet Milvus Lite. Es ist aktuell, braucht weder Docker noch Administratorrechte und ist für Entwicklung, Tests und Datenmengen bis etwa eine Million Vektoren gedacht.

  • Gleiche Schnittstelle: Programme sprechen Milvus Lite und den großen Milvus-Server mit derselben Python-Bibliothek pymilvus an. Für den Umstieg reicht es, beim Verbinden statt eines Ordnernamens die Adresse des Servers anzugeben. Nicht alle Funktionen des großen Servers stehen in Milvus Lite zur Verfügung.

  • Installation über pip: Milvus Lite ist nicht in den Ubuntu-Paketquellen enthalten. Es wird mit pip in eine virtuelle Umgebung (venv) installiert, also in einen eigenen Ordner nur für dieses Projekt.

  • Versionen: pymilvus 3.0 und Milvus Lite 3.2 unter Python 3.14.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version des Pakets für virtuelle Umgebungen kennt.

sudo apt update

2. Unterstützung für virtuelle Umgebungen installieren

python3-venv enthält das Werkzeug, mit dem Python virtuelle Umgebungen anlegt. Ist es schon vorhanden (z. B. aus der LangGraph-Anleitung), meldet apt das nur.

sudo apt install python3-venv

3. Projektordner anlegen

Ein eigener Ordner für die Beispiele.

mkdir ~/milvus-test

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/milvus-test

5. Virtuelle Umgebung anlegen

Legt die Umgebung im Unterordner .venv an.

python3 -m venv .venv

6. Virtuelle Umgebung aktivieren

Sorgt dafür, dass python und pip in diesem Terminal die Umgebung verwenden. Das musst du in jedem neuen Terminal wiederholen.

source .venv/bin/activate

Prüfen: Vor der Eingabeaufforderung steht jetzt (.venv).

7. pymilvus mit Milvus Lite installieren

Installiert die Python-Bibliothek pymilvus. Der Zusatz [milvus-lite] holt Milvus Lite gleich mit. Die Anführungszeichen verhindern, dass die Shell die eckigen Klammern selbst auswertet.

pip install -U "pymilvus[milvus-lite]"

Prüfen: Die Liste zeigt milvus-lite und pymilvus mit ihren Versionen, z. B. 3.2.1 und 3.0.2.

pip list | grep -i milvus

Erstes Beispiel

8. Beispielprogramm anlegen

Das Programm verwendet dasselbe Beispiel wie die Anleitungen zu pgvector und Qdrant: drei Einträge mit kleinen Vektoren aus drei Zahlen. Echte Embeddings haben meist mehrere hundert Zahlen. Die wichtigsten Befehle:

  • MilvusClient("notizen.db") – öffnet die Datenbank im Ordner notizen.db und legt ihn beim ersten Mal an
  • create_collection – legt eine Sammlung an (entspricht einer Tabelle). dimension ist die Anzahl der Zahlen pro Vektor, metric_type="COSINE" misst Ähnlichkeit über die Richtung der Vektoren.
  • insert – fügt Einträge ein. Neben id und vector sind beliebige weitere Felder erlaubt.
  • search – sucht die ähnlichsten Einträge. filter schränkt die Suche mit einer Bedingung auf die Felder ein, output_fields legt fest, welche Felder zurückkommen.
nano milvus_demo.py

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

from pymilvus import MilvusClient

# Milvus Lite: Die ganze Datenbank steckt in diesem einen Ordner
client = MilvusClient("notizen.db")

# Sammlung neu anlegen: Vektoren mit 3 Zahlen, Ähnlichkeit per Kosinus
if client.has_collection("notizen"):
    client.drop_collection("notizen")
client.create_collection("notizen", dimension=3, metric_type="COSINE")

# Einträge einfügen: id, Vektor und beliebige weitere Felder
client.insert("notizen", [
    {"id": 1, "vector": [1, 0, 0],     "text": "Apfel", "art": "obst"},
    {"id": 2, "vector": [0.9, 0.1, 0], "text": "Birne", "art": "obst"},
    {"id": 3, "vector": [0, 0, 1],     "text": "Auto",  "art": "fahrzeug"},
])

# Ähnlichkeitssuche: die zwei ähnlichsten Einträge
treffer = client.search("notizen", data=[[1, 0.05, 0]], limit=2, output_fields=["text"])
for t in treffer[0]:
    print("Suche:", t["entity"]["text"], round(t["distance"], 4))

# Suche mit Filter auf ein Feld
treffer = client.search("notizen", data=[[1, 0.05, 0]], limit=2,
                        filter='art == "fahrzeug"', output_fields=["text"])
for t in treffer[0]:
    print("Mit Filter:", t["entity"]["text"], round(t["distance"], 4))

print("Anzahl:", client.get_collection_stats("notizen")["row_count"])
client.close()

9. Beispiel ausführen

Startet das Programm in der virtuellen Umgebung.

python milvus_demo.py

Prüfen: Die Ausgabe lautet:

Suche: Apfel 0.9988
Suche: Birne 0.9982
Mit Filter: Auto 0.0
Anzahl: 3

Beim Kosinus-Maß bedeutet ein Wert nahe 1 „sehr ähnlich“. Mit dem Filter bleibt nur Auto übrig, obwohl es dem Suchvektor gar nicht ähnlich ist (Wert 0): Der Filter wird zuerst angewendet.

10. Datenordner ansehen

Milvus Lite speichert alles im Ordner notizen.db. Um die Datenbank zu sichern oder weiterzugeben, kopierst du diesen Ordner, während kein Programm darauf zugreift.

ls notizen.db

Prüfen: Es werden LOCK, collections und databases angezeigt. LOCK verhindert, dass zwei Programme gleichzeitig in denselben Ordner schreiben.

Optional: Milvus Lite als Server

Im ersten Beispiel läuft die Datenbank im Programm selbst, und nur dieses Programm kann auf sie zugreifen. Sollen mehrere Programme gleichzeitig dieselben Daten nutzen, startest du Milvus Lite als kleinen Server. Programme verbinden sich dann über das Netzwerkprotokoll gRPC auf Port 19530, genau wie mit einem großen Milvus-Server.

11. Server starten

--data-dir legt den Datenordner fest. --host 127.0.0.1 ist wichtig: Ohne diese Angabe wäre der Server aus dem ganzen Netz erreichbar, ohne Passwort. Der Server läuft im Vordergrund, das Terminal bleibt dabei belegt.

milvus-lite server --data-dir ~/milvus-test/serverdaten --host 127.0.0.1

12. Zweites Terminal vorbereiten

Öffne ein zweites Terminal, wechsle in den Projektordner und aktiviere dort ebenfalls die virtuelle Umgebung.

cd ~/milvus-test && source .venv/bin/activate

13. Beispiel auf den Server umstellen

Erstellt eine Kopie des Beispielprogramms, die sich statt mit dem Ordner notizen.db mit dem Server verbindet. Das ist die einzige Änderung, der übrige Code bleibt gleich.

cp milvus_demo.py milvus_server_demo.py
nano milvus_server_demo.py

Suche mit Strg+W nach MilvusClient( und drücke Enter. Die Zeile lautet client = MilvusClient("notizen.db"). Ändere die gefundene Zeile so, dass sie lautet:

client = MilvusClient("http://127.0.0.1:19530")

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

14. Beispiel gegen den Server ausführen

Startet die Kopie. Sie legt die Sammlung jetzt im Server an.

python milvus_server_demo.py

Prüfen: Die Ausgabe ist dieselbe wie in Schritt 9. Im Ordner ~/milvus-test/serverdaten liegen jetzt die Daten des Servers.

15. Server beenden

Wechsle in das erste Terminal und drücke Strg+C. Die Daten bleiben im Ordner serverdaten erhalten und stehen beim nächsten Start wieder zur Verfügung.

Wie geht es weiter?

  • Mit LangChain: Das Paket langchain-milvus bindet Milvus als Vektorspeicher an, siehe LangGraph und LangChain.
  • Umzug auf einen großen Milvus-Server: milvus-lite dump schreibt eine Sammlung in JSON-Dateien, die ein vollständiger Milvus-Server einlesen kann, z. B. milvus-lite dump -d notizen.db -c notizen -p ./export. Dafür brauchst du einmalig den Zusatz pip install "pymilvus[bulk_writer]".
  • Vergleich: Für kleinere Projekte ohne Python-Bindung ist Qdrant als eigenständiger Dienst oft einfacher. Liegen die übrigen Daten ohnehin in PostgreSQL, reicht häufig pgvector.

Aktualisieren

Milvus Lite wird pro Projekt aktualisiert. In der aktivierten virtuellen Umgebung holt dieser Befehl die neuesten Versionen:

pip install -U "pymilvus[milvus-lite]"

Sichere vorher den Datenordner und lies bei einem Sprung der Hauptversion (z. B. von 3 auf 4) die Versionshinweise von Milvus Lite.

Deinstallieren

1. Virtuelle Umgebung verlassen

Schaltet das Terminal zurück auf das Python des Systems. (.venv) verschwindet aus der Eingabeaufforderung.

deactivate

2. Projekt entfernen

Löscht den Projektordner samt virtueller Umgebung, Beispielprogrammen und beiden Datenordnern. Achtung: Alle darin gespeicherten Sammlungen gehen verloren. Außerhalb dieses Ordners hat pip nichts installiert.

rm -rf ~/milvus-test

3. Zwischenspeicher von pip leeren (optional)

pip hebt heruntergeladene Pakete in einem Zwischenspeicher auf, um spätere Installationen zu beschleunigen.

rm -rf ~/.cache/pip

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/milvus-test

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Spring Boot

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Spring Boot ist ein Framework für Java, mit dem man Webanwendungen, REST-Schnittstellen und Hintergrunddienste schnell aufsetzt. Es bringt einen eingebauten Webserver mit und richtet vieles selbst ein. Eine fertige Anwendung ist eine einzelne .jar-Datei, die sich mit java -jar starten lässt.

Vorbemerkungen

  • Keine Installation im engeren Sinn: Spring Boot wird nicht auf dem System installiert, sondern gehört als Abhängigkeit zu jedem Projekt. Aus den Ubuntu-Paketquellen kommt nur das Java-Entwicklungspaket (JDK).
  • Projekt anlegen mit Spring Initializr: Der offizielle Dienst https://start.spring.io erzeugt ein fertiges Projektgerüst. Diese Anleitung ruft ihn mit curl auf, im Browser geht es genauso.
  • Maven Wrapper: Das Projekt enthält das Skript ./mvnw. Es lädt beim ersten Aufruf automatisch das Build-Werkzeug Maven in der passenden Version herunter. Ein systemweites Maven ist nicht nötig.
  • Versionen: Spring Boot 4.1.1 und Java 25. Java 25 ist die aktuelle Version mit Langzeitunterstützung (LTS) und das Standard-JDK von Ubuntu 26.04.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von JDK und Hilfsprogrammen kennt.

sudo apt update

2. JDK und Hilfsprogramme installieren

  • default-jdk – Java-Entwicklungspaket (Compiler und Laufzeitumgebung) in der Standardversion von Ubuntu. Ist es schon vorhanden (z. B. aus der IntelliJ-IDEA-Anleitung), meldet apt das nur.
  • curl – lädt das Projektgerüst von Spring Initializr herunter
  • unzip – entpackt es
sudo apt install default-jdk curl unzip

Prüfen: Die Ausgabe nennt eine Java-Version ab 25, z. B. openjdk version "25…".

java -version

Ist zusätzlich eine neuere Java-Version installiert (z. B. 26), wird diese angezeigt. Das ist in Ordnung: Sie kann Projekte für Java 25 ebenfalls übersetzen.

Erstes Projekt

3. In das Home-Verzeichnis wechseln

Das Projekt wird im Ordner ~/hallo angelegt.

cd ~

4. Projektgerüst herunterladen

Fordert bei Spring Initializr ein fertiges Projekt als ZIP-Datei an. Die Angaben bedeuten:

  • type=maven-project – Build mit Maven (Alternative: gradle-project)
  • bootVersion, javaVersion – Spring-Boot- und Java-Version
  • groupId, artifactId, packageName – Namen für Projekt und Java-Paket. Die groupId ist üblicherweise eine umgedrehte Domain.
  • dependencies=web,actuator – die gewünschten Bausteine: web für Webanwendungen und REST-Schnittstellen mit eingebautem Webserver (Tomcat), actuator für Betriebsinformationen wie den Gesundheitszustand
curl https://start.spring.io/starter.zip -d type=maven-project -d bootVersion=4.1.1 -d javaVersion=25 -d groupId=de.beispiel -d artifactId=hallo -d packageName=de.beispiel.hallo -d dependencies=web,actuator -o hallo.zip

Prüfen: Die Datei ist ein ZIP-Archiv.

file hallo.zip

5. Projekt entpacken

Entpackt das Archiv in den Ordner ~/hallo.

unzip hallo.zip -d hallo

6. ZIP-Datei löschen

Das Archiv wird nicht mehr gebraucht.

rm hallo.zip

7. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/hallo

Prüfen: Unter anderem werden pom.xml (Projektbeschreibung für Maven), mvnw (Maven Wrapper) und der Ordner src angezeigt.

ls

Eine REST-Schnittstelle schreiben

8. Controller anlegen

Ein Controller beantwortet HTTP-Anfragen. Die Klasse liegt neben der von Initializr erzeugten Startklasse HalloApplication.java, damit Spring Boot sie automatisch findet. Die Anmerkungen (Annotationen) steuern das Verhalten:

  • @RestController – die Klasse liefert Daten (hier JSON), keine HTML-Seiten
  • @GetMapping("/hallo") – die Methode beantwortet GET-Anfragen an /hallo
  • @RequestParam(defaultValue = "Welt") – liest den Parameter name aus der Adresse, ohne Angabe gilt „Welt“

Spring Boot wandelt die zurückgegebene Map automatisch in JSON um.

nano src/main/java/de/beispiel/hallo/HalloController.java

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

package de.beispiel.hallo;

import java.util.Map;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

// Eine REST-Schnittstelle: Die Klasse beantwortet HTTP-Anfragen
@RestController
public class HalloController {

    // GET /hallo?name=... liefert eine Begrüßung als JSON
    @GetMapping("/hallo")
    public Map<String, String> hallo(@RequestParam(defaultValue = "Welt") String name) {
        return Map.of("gruss", "Hallo " + name + "!");
    }
}

9. Anwendung nur lokal erreichbar machen

Ohne weitere Angabe ist der eingebaute Webserver aus dem ganzen Netz erreichbar. Diese Zeilen in der Einstellungsdatei beschränken ihn auf den eigenen Rechner und legen den Port 8080 ausdrücklich fest.

nano src/main/resources/application.properties

Springe mit Strg+Ende ans Ende der Datei und füge in eigenen Zeilen an (im Terminal mit Strg+Umschalt+V). Speichere mit Strg+O und Enter und beende nano mit Strg+X:

server.address=127.0.0.1
server.port=8080

Prüfen: Die Datei enthält drei Zeilen: den Anwendungsnamen und die beiden neuen Einstellungen.

cat src/main/resources/application.properties

Starten und testen

10. Anwendung im Entwicklungsmodus starten

spring-boot:run übersetzt das Projekt und startet die Anwendung direkt. Beim ersten Aufruf lädt der Maven Wrapper Maven und alle Bibliotheken herunter (etwa 70 MB, nach ~/.m2). Das dauert eine Weile, spätere Starts gehen schnell. Das Terminal bleibt belegt, solange die Anwendung läuft.

./mvnw spring-boot:run

Prüfen: Die Ausgabe endet mit Zeilen wie Tomcat started on port 8080 und Started HalloApplication in … seconds.

11. REST-Schnittstelle aufrufen

Öffne ein zweites Terminal und frage die neue Schnittstelle ab.

curl "http://localhost:8080/hallo?name=Thorsten"

Prüfen: Die Antwort lautet {"gruss":"Hallo Thorsten!"}. Ohne ?name=… kommt {"gruss":"Hallo Welt!"}.

12. Gesundheitszustand abfragen

Der Baustein Actuator stellt unter /actuator/health den Zustand der Anwendung bereit. Überwachungswerkzeuge fragen diese Adresse regelmäßig ab. Weitere Actuator-Endpunkte sind aus Sicherheitsgründen zunächst abgeschaltet.

curl http://localhost:8080/actuator/health

Prüfen: Die Antwort enthält "status":"UP".

13. Anwendung beenden

Wechsle in das erste Terminal und drücke Strg+C.

Fertige Anwendung bauen

14. JAR-Datei erzeugen

package übersetzt das Projekt, führt die mitgelieferten Tests aus und packt alles, einschließlich Webserver und Bibliotheken, in eine einzige Datei. Die Warnungen zu Mockito und Java agent während der Tests sind harmlos.

./mvnw package

Prüfen: Die Ausgabe endet mit BUILD SUCCESS, und im Ordner target liegt die Datei hallo-0.0.1-SNAPSHOT.jar (etwa 22 MB).

ls -lh target/*.jar

15. JAR-Datei starten

So wird die Anwendung auch auf einem Server gestartet. Außer Java wird dort nichts gebraucht.

java -jar target/hallo-0.0.1-SNAPSHOT.jar

Prüfen: Im zweiten Terminal liefert curl http://localhost:8080/hallo wieder {"gruss":"Hallo Welt!"}. Mit Strg+C beendest du die Anwendung.

Wie geht es weiter?

  • Entwicklungsumgebung: IntelliJ IDEA öffnet das Projekt direkt über die Datei pom.xml. In VS Code helfen die Erweiterungen „Extension Pack for Java“ und „Spring Boot Extension Pack“, in Eclipse die „Spring Tools“ aus dem Eclipse Marketplace.
  • Weitere Bausteine: Auf https://start.spring.io findest du alle verfügbaren Abhängigkeiten, z. B. data-jpa und postgresql für den Zugriff auf PostgreSQL, security für Anmeldung und Rechte oder devtools für automatischen Neustart bei Codeänderungen.
  • KI-Anbindung: Mit dem Projekt Spring AI lassen sich Sprachmodelle und Vektordatenbanken wie pgvector, Qdrant oder Milvus einbinden.

Deinstallieren

1. Projekt entfernen

Löscht den Projektordner mit Quellcode und gebauter JAR-Datei. Achtung: Eigene Änderungen am Projekt gehen verloren.

rm -rf ~/hallo

2. Maven-Downloads entfernen

Der Maven Wrapper hat Maven nach ~/.m2/wrapper und alle Bibliotheken nach ~/.m2/repository geladen. Behalte den Ordner, wenn du weitere Java-Projekte mit Maven hast, sonst müssen sie alles neu herunterladen.

rm -rf ~/.m2

3. Optional: JDK entfernen

Nur ausführen, wenn kein anderes Programm Java braucht (z. B. IntelliJ IDEA oder Eclipse). curl und unzip brauchen viele andere Programme, sie bleiben deshalb installiert.

sudo apt purge default-jdk
sudo apt autoremove

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/hallo

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Django

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Django ist ein Web-Framework für Python. Es bringt vieles schon mit, was Webanwendungen brauchen: Datenbankzugriff über Python-Klassen statt SQL, Benutzerverwaltung, Formulare, Schutz vor typischen Angriffen und eine fertige Verwaltungsoberfläche (Admin), mit der sich Daten ohne eigenen Code pflegen lassen.

Vorbemerkungen

  • Installation über apt: Ubuntu 26.04 liefert Django 5.2. Das ist die aktuelle Version mit Langzeitunterstützung (LTS), sie bekommt bis April 2028 Sicherheitskorrekturen. Die neueren Versionen 6.x gibt es nur über pip, siehe Abschnitt am Ende.
  • Datenbank: Für den Anfang verwendet Django SQLite. Die Daten liegen dann in einer einzelnen Datei im Projektordner, ein Datenbankserver ist nicht nötig. Später lässt sich auf PostgreSQL umstellen.
  • Projekt und App: Ein Django-Projekt ist die gesamte Website mit ihren Einstellungen. Es besteht aus einer oder mehreren Apps, die jeweils einen Bereich abdecken, hier eine App notizen.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version von Django aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Django installieren

Installiert Django und den Befehl django-admin. Die benötigten Hilfsbibliotheken (python3-asgiref, python3-sqlparse) installiert apt automatisch mit.

sudo apt install python3-django

Prüfen: Die Ausgabe ist die Versionsnummer, z. B. 5.2.9.

django-admin --version

Erstes Projekt

3. Projektordner anlegen

Ein eigener Ordner für das Projekt.

mkdir ~/meinprojekt

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/meinprojekt

5. Projekt anlegen

Erzeugt das Grundgerüst. Der Punkt am Ende bedeutet: direkt in diesen Ordner, ohne zusätzlichen Unterordner. Es entstehen die Datei manage.py (das Werkzeug für alle weiteren Befehle) und der Ordner meinprojekt mit den Einstellungen (settings.py) und den Adressen (urls.py).

django-admin startproject meinprojekt .

Prüfen: Es werden manage.py und meinprojekt angezeigt.

ls

6. Sprache und Zeitzone einstellen

Stellt die Oberfläche auf Deutsch und die Zeitzone auf Mitteleuropa um. Das betrifft vor allem die Verwaltungsoberfläche und die Anzeige von Datum und Uhrzeit.

nano meinprojekt/settings.py

Suche mit Strg+W nach LANGUAGE_CODE und drücke Enter. Ändere diese Zeile und die Zeile TIME_ZONE zwei Zeilen darunter, sodass sie lauten:

LANGUAGE_CODE = 'de-de'

TIME_ZONE = 'Europe/Berlin'

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Ausgabe zeigt LANGUAGE_CODE = 'de-de' und TIME_ZONE = 'Europe/Berlin'.

grep -E "^(LANGUAGE_CODE|TIME_ZONE)" meinprojekt/settings.py

7. App anlegen

Erzeugt die App notizen als eigenen Ordner mit Dateien für Datenmodelle (models.py), Seitenlogik (views.py) und Verwaltungsoberfläche (admin.py).

python3 manage.py startapp notizen

8. App im Projekt anmelden

Django berücksichtigt eine App erst, wenn sie in der Liste INSTALLED_APPS in settings.py steht. notizen kommt ans Ende der Liste.

nano meinprojekt/settings.py

Suche mit Strg+W nach staticfiles und drücke Enter. Der Cursor steht in der letzten Zeile der Liste INSTALLED_APPS. Drücke Ende und Enter und tippe darunter die neue Zeile, eingerückt mit vier Leerzeichen:

    'notizen',

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die letzte Zeile der Liste lautet 'notizen',.

grep -A 8 '^INSTALLED_APPS' meinprojekt/settings.py

Daten, Verwaltung und eine Seite

9. Datenmodell anlegen

Ein Modell ist eine Python-Klasse, aus der Django eine Datenbanktabelle macht. Jedes Feld wird zu einer Spalte. Die Texte in Anführungszeichen (z. B. "Titel") sind die Beschriftungen in der Verwaltungsoberfläche. auto_now_add trägt beim Anlegen automatisch Datum und Uhrzeit ein. Meta legt den Namen in Einzahl und Mehrzahl sowie die Sortierung fest (neueste zuerst).

nano notizen/models.py

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

from django.db import models


class Notiz(models.Model):
    titel = models.CharField("Titel", max_length=200)
    text = models.TextField("Text", blank=True)
    erstellt = models.DateTimeField("Erstellt", auto_now_add=True)

    class Meta:
        verbose_name = "Notiz"
        verbose_name_plural = "Notizen"
        ordering = ["-erstellt"]

    def __str__(self):
        return self.titel

10. Migration erzeugen

Eine Migration ist eine Datei, die beschreibt, wie die Datenbank an das Modell angepasst wird. Django erzeugt sie selbst aus dem Modell. Bei jeder späteren Änderung am Modell wiederholst du diesen und den nächsten Schritt.

python3 manage.py makemigrations notizen

Prüfen: Die Ausgabe enthält + Create model Notiz.

11. Datenbank anlegen

Führt alle Migrationen aus: die eigenen und die der mitgelieferten Apps (Benutzer, Sitzungen, Verwaltung). Dabei entsteht die Datenbankdatei db.sqlite3.

python3 manage.py migrate

Prüfen: Die letzten Zeilen enden jeweils mit OK, darunter Applying notizen.0001_initial... OK.

12. Notizen in der Verwaltungsoberfläche anzeigen

Meldet das Modell bei der Verwaltungsoberfläche an. list_display legt die Spalten der Übersicht fest, search_fields die Felder, in denen die Suche sucht.

nano notizen/admin.py

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

from django.contrib import admin

from .models import Notiz


@admin.register(Notiz)
class NotizAdmin(admin.ModelAdmin):
    list_display = ["titel", "erstellt"]
    search_fields = ["titel", "text"]

13. Administrator anlegen

Legt ein Benutzerkonto mit vollen Rechten für die Verwaltungsoberfläche an. Der Befehl fragt nach Benutzername, E-Mail-Adresse (darf leer bleiben) und zweimal nach dem Passwort. Die Eingabe des Passworts wird nicht angezeigt.

python3 manage.py createsuperuser

Prüfen: Die Ausgabe endet mit Superuser created successfully.

14. Eine eigene Seite schreiben

Eine View ist eine Funktion, die eine Anfrage bekommt und eine Antwort zurückgibt. Diese hier liefert alle Notizen als JSON, also als einfache REST-Schnittstelle. Für HTML-Seiten würde man stattdessen eine Vorlage (Template) verwenden.

nano notizen/views.py

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

from django.http import JsonResponse

from .models import Notiz


def liste(request):
    notizen = Notiz.objects.values("id", "titel", "erstellt")
    return JsonResponse({"notizen": list(notizen)})

15. Adresse für die Seite festlegen

Ersetzt die Adressliste des Projekts. Neben der Verwaltungsoberfläche unter /admin/ ist die neue View jetzt unter /notizen/ erreichbar.

nano meinprojekt/urls.py

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

from django.contrib import admin
from django.urls import path

from notizen import views

urlpatterns = [
    path("admin/", admin.site.urls),
    path("notizen/", views.liste),
]

16. Projekt prüfen

Django untersucht Einstellungen, Modelle und Adressen auf Fehler, ohne den Server zu starten.

python3 manage.py check

Prüfen: Die Ausgabe lautet System check identified no issues (0 silenced).

Starten und testen

17. Entwicklungsserver starten

Startet den eingebauten Webserver auf http://127.0.0.1:8000. Er ist nur vom eigenen Rechner aus erreichbar und lädt geänderte Python-Dateien automatisch neu. Das Terminal bleibt dabei belegt. Für den echten Betrieb ist er nicht gedacht.

python3 manage.py runserver

Prüfen: Die Ausgabe enthält Starting development server at http://127.0.0.1:8000/. Die gelbe Warnung darunter erinnert nur daran, dass dieser Server nicht für den echten Betrieb gedacht ist.

18. Notiz in der Verwaltungsoberfläche anlegen

Öffne http://127.0.0.1:8000/admin/ im Browser und melde dich mit dem Konto aus Schritt 13 an. Die Oberfläche heißt „Django-Systemverwaltung“. Unter Notizen klickst du auf Hinzufügen, gibst einen Titel und einen Text ein und klickst auf Sichern.

Prüfen: Die Notiz erscheint in der Übersicht mit Titel und Erstellungszeit.

19. Eigene Seite abrufen

Öffne ein zweites Terminal und frage die View aus Schritt 14 ab.

curl http://127.0.0.1:8000/notizen/

Prüfen: Die Antwort enthält die angelegte Notiz, z. B. {"notizen": [{"id": 1, "titel": "Erste Notiz", "erstellt": "…"}]}.

20. Server beenden

Wechsle in das erste Terminal und drücke Strg+C.

Wie geht es weiter?

  • PostgreSQL statt SQLite: Mit dem Paket python3-psycopg (über apt) und einer angepassten Einstellung DATABASES in settings.py verwendet Django eine PostgreSQL-Datenbank.
  • Betrieb mit nginx: Für den echten Betrieb startet man Django mit einem Anwendungsserver wie Gunicorn (Paket gunicorn) und setzt nginx davor. In settings.py müssen dann DEBUG = False gesetzt und ALLOWED_HOSTS sowie SECRET_KEY angepasst werden.
  • REST-Schnittstellen: Das Django REST Framework (Paket python3-djangorestframework) erleichtert umfangreichere Schnittstellen.
  • Entwicklungsumgebung: VS Code mit der Python-Erweiterung oder PyCharm unterstützen Django-Projekte.

Alternative: neueste Version über pip

Die aktuelle Version Django 6.1 bekommst du nur über pip in einer virtuellen Umgebung, genau wie in der LangGraph-Anleitung beschrieben. Im Projektordner:

python3 -m venv .venv
source .venv/bin/activate
pip install django

Solange die virtuelle Umgebung aktiv ist, verwenden django-admin und python3 manage.py diese Version. Sie bekommt aber keine Updates über apt, und du musst sie selbst mit pip install -U django aktuell halten.

Deinstallieren

1. Projekt entfernen

Löscht den Projektordner samt Datenbank db.sqlite3. Achtung: Alle darin gespeicherten Daten gehen verloren.

rm -rf ~/meinprojekt

2. Django entfernen

Entfernt das Paket.

sudo apt purge python3-django

3. Nicht mehr benötigte Pakete entfernen

Entfernt die Hilfsbibliotheken, die nur für Django installiert wurden.

sudo apt autoremove

Prüfen: Der Befehl wird nicht mehr gefunden.

django-admin --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

ASP.NET Core

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

ASP.NET Core ist das Web-Framework von Microsoft für die Plattform .NET. Damit baut man in C# Webanwendungen, REST-Schnittstellen und Echtzeitdienste. Es ist quelloffen, läuft unter Linux genauso wie unter Windows und bringt mit Kestrel einen eigenen, schnellen Webserver mit.

Vorbemerkungen

  • Installation über apt: Ubuntu 26.04 liefert .NET 10 selbst, die aktuelle Version mit Langzeitunterstützung (LTS) bis November 2028. Das .NET SDK enthält ASP.NET Core bereits, ein Paketarchiv von Microsoft ist nicht nötig.

  • Vorlagen: Neue Projekte legt man mit dotnet new aus Vorlagen an. Die wichtigsten für Webanwendungen:

    VorlageInhalt
    webLeeres Projekt mit Minimal API: Endpunkte werden direkt in Program.cs festgelegt. Wird in dieser Anleitung verwendet.
    webapiREST-Schnittstelle mit Beispiel-Endpunkt und OpenAPI-Beschreibung
    mvcWebanwendung nach dem Muster Model-View-Controller
    webappWebanwendung mit Razor Pages (eine Datei pro Seite)
    blazorInteraktive Weboberfläche in C# statt JavaScript
  • Nur HTTP: Auf dem Entwicklungsrechner läuft die Anwendung hier über einfaches HTTP an 127.0.0.1. HTTPS übernimmt im echten Betrieb meist ein vorgeschalteter Webserver wie nginx.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version des .NET SDK aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. .NET SDK installieren

Installiert den Befehl dotnet, den C#-Compiler, die Laufzeitumgebungen für .NET und ASP.NET Core sowie die Projektvorlagen. Ist es schon vorhanden (z. B. aus der Anleitung Microsoft Visual Studio), meldet apt das nur.

sudo apt install dotnet-sdk-10.0

Prüfen: In der Liste steht Microsoft.AspNetCore.App 10.0…, also die Laufzeitumgebung für ASP.NET Core.

dotnet --list-runtimes

3. Optional: Nutzungsstatistik abschalten

Die Befehlszeile dotnet kann anonyme Nutzungsdaten an Microsoft senden. Diese Zeile in ~/.bashrc schaltet das für alle künftigen Terminals ab. Danach ein neues Terminal öffnen.

nano ~/.bashrc

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile an (im Terminal mit Strg+Umschalt+V). Speichere mit Strg+O und Enter und beende nano mit Strg+X:

export DOTNET_CLI_TELEMETRY_OPTOUT=1

Erstes Projekt

4. Projekt anlegen

Erzeugt aus der Vorlage web ein leeres Projekt im Ordner ~/HalloWeb. Beim allerersten Aufruf von dotnet erscheint einmalig ein Begrüßungstext.

dotnet new web -o ~/HalloWeb

5. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/HalloWeb

Prüfen: Es werden unter anderem Program.cs (der Programmcode), HalloWeb.csproj (die Projektbeschreibung) und appsettings.json (Einstellungen) angezeigt.

ls

6. Programmcode schreiben

Ersetzt Program.cs durch eine kleine REST-Schnittstelle für Notizen. Die wichtigsten Bausteine:

  • WebApplication.CreateBuilder und Build – richten die Anwendung mit Webserver, Protokollierung und Einstellungen ein
  • MapGet, MapPost – legen fest, welche Funktion eine Anfrage an eine Adresse beantwortet. Parameter wie name liest ASP.NET Core automatisch aus der Adresse, Objekte wie eingabe aus dem mitgeschickten JSON.
  • Rückgabewerte werden automatisch in JSON umgewandelt. Results.Created antwortet zusätzlich mit dem HTTP-Status 201 Created.
  • record – eine kurze Schreibweise für einfache Datenklassen

Die Notizen liegen nur im Arbeitsspeicher und sind nach einem Neustart weg. Für dauerhafte Speicherung verwendet man eine Datenbank, siehe „Wie geht es weiter?“.

nano Program.cs

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// Notizen nur im Arbeitsspeicher: Nach einem Neustart sind sie weg
var notizen = new List<Notiz>();

// GET /hallo?name=... liefert eine Begrüßung als JSON
app.MapGet("/hallo", (string? name) => new { gruss = $"Hallo {name ?? "Welt"}!" });

// GET /notizen liefert alle Notizen
app.MapGet("/notizen", () => notizen);

// POST /notizen legt eine Notiz an; der Inhalt kommt als JSON
app.MapPost("/notizen", (NeueNotiz eingabe) =>
{
    var notiz = new Notiz(notizen.Count + 1, eingabe.Titel, DateTime.Now);
    notizen.Add(notiz);
    return Results.Created($"/notizen/{notiz.Id}", notiz);
});

app.Run();

// Datentypen: "record" ist eine kurze Schreibweise für einfache Datenklassen
record NeueNotiz(string Titel);
record Notiz(int Id, string Titel, DateTime Erstellt);

7. Projekt übersetzen

Übersetzt das Projekt und meldet Fehler im Code, ohne die Anwendung zu starten. Beim ersten Mal dauert das einige Sekunden länger.

dotnet build

Prüfen: Die Ausgabe endet mit 0 Warnung(en) und 0 Fehler.

Starten und testen

8. Anwendung starten

dotnet run übersetzt das Projekt bei Bedarf und startet es. Ohne weitere Angabe würde die Anwendung auf einem zufällig bei der Projektanlage gewählten Port laufen (festgelegt in Properties/launchSettings.json). --urls legt stattdessen Adresse und Port fest: nur der eigene Rechner, Port 5000. Das Terminal bleibt belegt, solange die Anwendung läuft.

dotnet run --urls http://127.0.0.1:5000

Prüfen: Die Ausgabe enthält Now listening on: http://127.0.0.1:5000 und Hosting environment: Development.

9. Begrüßung abrufen

Öffne ein zweites Terminal und frage den ersten Endpunkt ab.

curl "http://localhost:5000/hallo?name=Thorsten"

Prüfen: Die Antwort lautet {"gruss":"Hallo Thorsten!"}.

10. Notiz anlegen

Schickt eine neue Notiz als JSON an den Server. -i zeigt zusätzlich die Kopfzeilen der Antwort an.

curl -i -X POST http://localhost:5000/notizen -H "Content-Type: application/json" -d '{"titel": "Erste Notiz"}'

Prüfen: Die erste Zeile lautet HTTP/1.1 201 Created, darunter steht Location: /notizen/1. Die letzte Zeile enthält die Notiz mit "id":1 und dem Erstellungszeitpunkt.

11. Alle Notizen abrufen

Fragt die Liste ab.

curl http://localhost:5000/notizen

Prüfen: Die Antwort ist eine Liste mit der Notiz aus dem vorigen Schritt.

12. Anwendung beenden

Wechsle in das erste Terminal und drücke Strg+C.

Tipp: Statt dotnet run kannst du beim Entwickeln dotnet watch run --urls http://127.0.0.1:5000 verwenden. Dann übernimmt die laufende Anwendung Änderungen am Code sofort, ohne dass du sie neu starten musst.

Fertige Anwendung erstellen

13. Anwendung veröffentlichen

publish übersetzt das Projekt in der optimierten Einstellung Release und legt alles, was zum Betrieb nötig ist, in den Ordner veroeffentlicht. Auf dem Zielrechner muss dafür nur die ASP.NET-Core-Laufzeitumgebung installiert sein (Paket aspnetcore-runtime-10.0), nicht das ganze SDK.

dotnet publish -c Release -o veroeffentlicht

Prüfen: Im Ordner liegen unter anderem HalloWeb (das Startprogramm) und HalloWeb.dll.

ls veroeffentlicht

14. Veröffentlichte Anwendung starten

Startet die fertige Anwendung so, wie sie auch auf einem Server laufen würde.

./veroeffentlicht/HalloWeb --urls http://127.0.0.1:5000

Prüfen: Die Ausgabe enthält jetzt Hosting environment: Production. Im zweiten Terminal liefert curl http://localhost:5000/hallo die Antwort {"gruss":"Hallo Welt!"}. Mit Strg+C beendest du die Anwendung.

Wie geht es weiter?

  • Datenbank: Entity Framework Core bildet C#-Klassen auf Tabellen ab. Für PostgreSQL fügst du mit dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL den passenden Treiber hinzu.
  • Betrieb: Auf einem Server lässt man die veröffentlichte Anwendung als systemd-Dienst laufen und setzt nginx als Reverse Proxy davor, der auch HTTPS übernimmt.
  • Entwicklungsumgebung: VS Code mit dem C# Dev Kit, siehe Microsoft Visual Studio, oder JetBrains Rider.

Deinstallieren

1. Projekt entfernen

Löscht den Projektordner samt übersetzter und veröffentlichter Dateien.

rm -rf ~/HalloWeb

2. Einstellung zur Nutzungsstatistik entfernen

Nur nötig, wenn du Schritt 3 ausgeführt hast.

nano ~/.bashrc

Suche mit Strg+W nach DOTNET_CLI_TELEMETRY_OPTOUT und drücke Enter. Lösche die Zeile export DOTNET_CLI_TELEMETRY_OPTOUT=1 mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

3. Optional: .NET SDK entfernen

Nur ausführen, wenn kein anderes Projekt .NET braucht.

sudo apt purge dotnet-sdk-10.0
sudo apt autoremove

4. Optional: Zwischenspeicher entfernen

~/.dotnet enthält Einstellungen des Befehls dotnet, ~/.nuget heruntergeladene Bibliotheken. Andere .NET-Projekte laden sie bei Bedarf neu.

rm -rf ~/.dotnet ~/.nuget

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/HalloWeb

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Axum und Actix-web

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Axum und Actix-web sind die beiden verbreitetsten Web-Frameworks für die Programmiersprache Rust. Mit ihnen baut man sehr schnelle und speichersichere Webserver und REST-Schnittstellen. Das Ergebnis ist ein einzelnes, eigenständiges Programm ohne Laufzeitumgebung.

Vorbemerkungen

  • Die beiden Frameworks im Vergleich:

    AxumActix-web
    LizenzMITMIT oder Apache 2.0 (nach Wahl)
    HerkunftVom Tokio-Projekt, das auch die Grundlage für asynchrones Rust liefertEigenständiges Projekt, eines der ältesten Rust-Web-Frameworks
    Routen festlegenZentral im Router, Funktionen bleiben gewöhnliche async fnÜber Makros wie #[get("/pfad")] direkt an der Funktion
    LaufzeitTokio, gemeinsam für den ganzen ServerEigenes System auf Tokio-Basis, ein Arbeitsbereich pro Prozessorkern
    BesonderheitPasst nahtlos zu anderen Tokio- und Tower-BausteinenSehr ausgereift, eigenes Ökosystem an Erweiterungen

    Beide sind schnell genug für praktisch jeden Einsatz. Die Wahl ist vor allem eine Frage des Geschmacks.

  • Installation: Den Rust-Compiler rustc und das Build-Werkzeug cargo liefert Ubuntu 26.04 in Version 1.93. Das genügt für beide Frameworks (Axum braucht mindestens 1.80, Actix-web mindestens 1.88). Die Frameworks selbst werden pro Projekt von cargo aus dem Paketverzeichnis crates.io geladen.

  • Gleiches Beispiel: Beide Projekte bekommen dieselbe kleine Notiz-Schnittstelle wie in der ASP.NET-Core-Anleitung, damit man sie gut vergleichen kann.

  • Versionen: Axum 0.8, Actix-web 4.15, Tokio 1.53.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Rust und Cargo aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Rust und Cargo installieren

Installiert den Compiler rustc und das Build-Werkzeug cargo, das Projekte anlegt, Abhängigkeiten lädt und übersetzt. Den C-Compiler gcc, den Rust zum Zusammenfügen (Linken) der Programme braucht, installiert apt automatisch mit.

sudo apt install rustc cargo

Prüfen: Die Ausgabe nennt die Version, z. B. cargo 1.93.1.

cargo --version

Hast du Rust zusätzlich über rustup installiert (Befehle im Ordner ~/.cargo/bin), wird dessen neuere Version angezeigt. Das ist in Ordnung, beide Wege funktionieren.

Axum

3. Projekt anlegen

cargo new legt ein neues Rust-Programm im Ordner ~/hallo-axum an: die Projektbeschreibung Cargo.toml und den Quellcode src/main.rs.

cargo new ~/hallo-axum

4. In den Projektordner wechseln

Die Befehle bis Schritt 10 beziehen sich auf diesen Ordner.

cd ~/hallo-axum

5. Abhängigkeiten hinzufügen

cargo add trägt Bibliotheken (in Rust Crates genannt) in Cargo.toml ein:

  • axum – das Web-Framework
  • tokio mit allen Funktionen (full) – die Laufzeitumgebung für asynchrone Programme, auf der Axum aufbaut
  • serde mit derive – wandelt eigene Datentypen in JSON um und zurück
  • serde_json – für JSON-Werte ohne eigenen Datentyp
cargo add axum tokio serde serde_json --features tokio/full,serde/derive

Prüfen: Im Abschnitt [dependencies] stehen die vier Crates mit ihren Versionen.

cat Cargo.toml

6. Programmcode schreiben

Ersetzt src/main.rs. Die wichtigsten Bausteine:

  • #[derive(Serialize, Deserialize)] – erzeugt automatisch den Code zum Umwandeln in und aus JSON
  • Handler – gewöhnliche async fn. Was sie brauchen, geben sie als Parameter an: Query liest Werte aus der Adresse, Json aus dem mitgeschickten Inhalt, State greift auf gemeinsame Daten zu.
  • Arc<Mutex<…>> – eine Liste, die sich alle gleichzeitig laufenden Anfragen sicher teilen können
  • Router – legt zentral fest, welcher Handler welche Adresse und Methode beantwortet
  • TcpListener::bind("127.0.0.1:3000") – der Server ist nur vom eigenen Rechner aus erreichbar, auf Port 3000
nano src/main.rs

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

use std::sync::{Arc, Mutex};

use axum::{
    extract::{Query, State},
    http::StatusCode,
    routing::get,
    Json, Router,
};
use serde::{Deserialize, Serialize};

// Datentypen: Serialize/Deserialize wandeln automatisch in JSON um und zurück
#[derive(Clone, Serialize)]
struct Notiz {
    id: usize,
    titel: String,
}

#[derive(Deserialize)]
struct NeueNotiz {
    titel: String,
}

#[derive(Deserialize)]
struct Name {
    name: Option<String>,
}

// Gemeinsamer Zustand: die Notizliste, sicher für gleichzeitige Zugriffe
type Notizen = Arc<Mutex<Vec<Notiz>>>;

// GET /hallo?name=... liefert eine Begrüßung als JSON
async fn hallo(Query(abfrage): Query<Name>) -> Json<serde_json::Value> {
    let name = abfrage.name.unwrap_or_else(|| "Welt".to_string());
    Json(serde_json::json!({ "gruss": format!("Hallo {name}!") }))
}

// GET /notizen liefert alle Notizen
async fn liste(State(notizen): State<Notizen>) -> Json<Vec<Notiz>> {
    Json(notizen.lock().unwrap().clone())
}

// POST /notizen legt eine Notiz an; der Inhalt kommt als JSON
async fn anlegen(
    State(notizen): State<Notizen>,
    Json(eingabe): Json<NeueNotiz>,
) -> (StatusCode, Json<Notiz>) {
    let mut liste = notizen.lock().unwrap();
    let notiz = Notiz { id: liste.len() + 1, titel: eingabe.titel };
    liste.push(notiz.clone());
    (StatusCode::CREATED, Json(notiz))
}

#[tokio::main]
async fn main() {
    let notizen: Notizen = Arc::new(Mutex::new(Vec::new()));

    // Router: welche Funktion beantwortet welche Adresse und Methode
    let app = Router::new()
        .route("/hallo", get(hallo))
        .route("/notizen", get(liste).post(anlegen))
        .with_state(notizen);

    // Nur vom eigenen Rechner aus erreichbar, Port 3000
    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
    println!("Axum läuft auf http://127.0.0.1:3000");
    axum::serve(listener, app).await.unwrap();
}

7. Übersetzen und starten

cargo run lädt beim ersten Mal alle Crates herunter (nach ~/.cargo/registry), übersetzt sie und startet das Programm. Das dauert beim ersten Mal etwa eine halbe Minute, danach nur noch Sekunden. Das Terminal bleibt belegt, solange der Server läuft.

cargo run

Prüfen: Die letzte Zeile lautet Axum läuft auf http://127.0.0.1:3000.

8. Schnittstelle testen

Öffne ein zweites Terminal und lege eine Notiz an.

curl -i -X POST http://localhost:3000/notizen -H "Content-Type: application/json" -d '{"titel": "Erste Notiz"}'

Prüfen: Die erste Zeile lautet HTTP/1.1 201 Created, die letzte {"id":1,"titel":"Erste Notiz"}. Außerdem liefern:

  • curl http://localhost:3000/notizen → [{"id":1,"titel":"Erste Notiz"}]
  • curl "http://localhost:3000/hallo?name=Thorsten" → {"gruss":"Hallo Thorsten!"}

Fehlt beim Anlegen die Angabe Content-Type: application/json, antwortet Axum mit 415 Unsupported Media Type.

9. Server beenden

Wechsle in das erste Terminal und drücke Strg+C.

10. Fertiges Programm erstellen

--release übersetzt mit allen Optimierungen. Das Ergebnis ist ein einzelnes Programm von etwa 2 MB, das ohne Rust oder weitere Dateien auf jedem vergleichbaren Linux-System läuft.

cargo build --release

Prüfen: Das Programm liegt unter target/release/hallo-axum und lässt sich direkt starten:

./target/release/hallo-axum

Mit Strg+C beendest du es wieder.

Actix-web

11. Projekt anlegen

Legt das zweite Projekt im Ordner ~/hallo-actix an.

cargo new ~/hallo-actix

12. In den Projektordner wechseln

Die Befehle bis Schritt 18 beziehen sich auf diesen Ordner.

cd ~/hallo-actix

13. Abhängigkeiten hinzufügen

Actix-web bringt seine Laufzeitumgebung selbst mit, deshalb ist tokio hier nicht nötig.

cargo add actix-web serde serde_json --features serde/derive

14. Programmcode schreiben

Ersetzt src/main.rs. Die Unterschiede zu Axum:

  • #[get("/hallo")], #[post("/notizen")] – die Adresse steht als Makro direkt über der Funktion
  • web::Query, web::Json, web::Data – entsprechen Query, Json und State bei Axum
  • impl Responder – die Funktion gibt „irgendetwas Beantwortbares“ zurück, hier eine HttpResponse mit Status und JSON
  • HttpServer::new(move || App::new() …) – Actix-web startet mehrere Arbeitsbereiche (einen pro Prozessorkern) und baut für jeden eine eigene App. Die gemeinsame Notizliste reicht web::Data an alle weiter.
  • bind(("127.0.0.1", 8081)) – nur vom eigenen Rechner aus erreichbar, auf Port 8081

Hinweis: Das Makro #[get("/notizen")] macht aus der Funktion liste einen gleichnamigen Datentyp. Eine Variable darf deshalb im selben Programm nicht ebenfalls liste heißen. Im Code unten heißt sie darum alle.

nano src/main.rs

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

use std::sync::Mutex;

use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};

// Datentypen: Serialize/Deserialize wandeln automatisch in JSON um und zurück
#[derive(Clone, Serialize)]
struct Notiz {
    id: usize,
    titel: String,
}

#[derive(Deserialize)]
struct NeueNotiz {
    titel: String,
}

#[derive(Deserialize)]
struct Name {
    name: Option<String>,
}

// Gemeinsamer Zustand: die Notizliste, sicher für gleichzeitige Zugriffe
struct Notizen(Mutex<Vec<Notiz>>);

// GET /hallo?name=... liefert eine Begrüßung als JSON
#[get("/hallo")]
async fn hallo(abfrage: web::Query<Name>) -> impl Responder {
    let name = abfrage.name.clone().unwrap_or_else(|| "Welt".to_string());
    HttpResponse::Ok().json(serde_json::json!({ "gruss": format!("Hallo {name}!") }))
}

// GET /notizen liefert alle Notizen
#[get("/notizen")]
async fn liste(notizen: web::Data<Notizen>) -> impl Responder {
    HttpResponse::Ok().json(notizen.0.lock().unwrap().clone())
}

// POST /notizen legt eine Notiz an; der Inhalt kommt als JSON
#[post("/notizen")]
async fn anlegen(notizen: web::Data<Notizen>, eingabe: web::Json<NeueNotiz>) -> impl Responder {
    let mut alle = notizen.0.lock().unwrap();
    let notiz = Notiz { id: alle.len() + 1, titel: eingabe.titel.clone() };
    alle.push(notiz.clone());
    HttpResponse::Created().json(notiz)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let notizen = web::Data::new(Notizen(Mutex::new(Vec::new())));

    println!("Actix-web läuft auf http://127.0.0.1:8081");

    // Für jeden Arbeits-Thread wird eine App mit denselben Routen gebaut;
    // die Notizliste teilen sich alle über web::Data
    HttpServer::new(move || {
        App::new()
            .app_data(notizen.clone())
            .service(hallo)
            .service(liste)
            .service(anlegen)
    })
    // Nur vom eigenen Rechner aus erreichbar, Port 8081
    .bind(("127.0.0.1", 8081))?
    .run()
    .await
}

15. Übersetzen und starten

Lädt die Crates, übersetzt und startet den Server. Crates, die schon für Axum geladen wurden, holt cargo aus dem Zwischenspeicher.

cargo run

Prüfen: Die letzte Zeile lautet Actix-web läuft auf http://127.0.0.1:8081.

16. Schnittstelle testen

Im zweiten Terminal dieselbe Anfrage wie bei Axum, nur mit Port 8081.

curl -i -X POST http://localhost:8081/notizen -H "Content-Type: application/json" -d '{"titel": "Erste Notiz"}'

Prüfen: Die Antworten sind identisch mit denen von Axum: HTTP/1.1 201 Created und {"id":1,"titel":"Erste Notiz"}. Auch /notizen und /hallo?name=… verhalten sich gleich.

17. Server beenden

Wechsle in das erste Terminal und drücke Strg+C.

18. Fertiges Programm erstellen

Übersetzt mit allen Optimierungen. Das Programm ist mit etwa 7 MB etwas größer als bei Axum, weil Actix-web mehr Funktionen fest einbaut (z. B. Komprimierung).

cargo build --release

Prüfen: Das Programm liegt unter target/release/hallo-actix.

ls -lh target/release/hallo-actix

Wie geht es weiter?

  • Datenbank: Die Crate sqlx greift asynchron auf PostgreSQL oder SQLite zu und prüft SQL-Abfragen schon beim Übersetzen.
  • Betrieb: Das fertige Programm lässt sich als systemd-Dienst starten (siehe die Dienstdatei in der Qdrant-Anleitung als Vorlage). Davor setzt man nginx, der auch HTTPS übernimmt.
  • Entwicklungsumgebung: VS Code mit der Erweiterung „rust-analyzer“, Neovim mit rust-analyzer oder JetBrains RustRover.

Deinstallieren

1. Projekte entfernen

Löscht beide Projektordner samt übersetzter Programme.

rm -rf ~/hallo-axum ~/hallo-actix

2. Heruntergeladene Crates entfernen

cargo hat die Crates in ~/.cargo/registry zwischengespeichert. Achtung: Hast du Rust über rustup installiert, liegt in ~/.cargo auch die Rust-Installation selbst. Lösche dann nur diesen Unterordner, nicht ganz ~/.cargo.

rm -rf ~/.cargo/registry

3. Optional: Rust und Cargo entfernen

Nur ausführen, wenn du Rust aus den Ubuntu-Paketen nicht mehr brauchst.

sudo apt purge rustc cargo
sudo apt autoremove

Prüfen: Die Projektordner existieren nicht mehr.

ls ~/hallo-axum ~/hallo-actix

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Express.js

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Express ist das bekannteste Web-Framework für Node.js. Es ist bewusst klein gehalten: Es kümmert sich um Adressen (Routen), Anfragen und Antworten und lässt sich über Middleware beliebig erweitern. Damit baut man in JavaScript Webserver und REST-Schnittstellen.

Vorbemerkungen

  • Installation pro Projekt: Express wird mit npm in jedes Projekt einzeln installiert. Aus den Ubuntu-Paketquellen kommen nur Node.js und npm. Ubuntu enthält zwar auch ein Paket node-express (Version 5.1), es hinkt der aktuellen Version aber hinterher und wird in package.json nicht vermerkt. Ein Projekt, das darauf aufbaut, lässt sich deshalb nicht ohne Weiteres auf einen anderen Rechner übertragen.
  • Version: Express 5.2. Gegenüber Express 4, das noch in vielen Beispielen im Netz steht, gibt es kleine Änderungen, etwa bei Mustern in Adressen und der Behandlung von Fehlern in async-Funktionen.
  • Gleiches Beispiel: Das Projekt bekommt dieselbe kleine Notiz-Schnittstelle wie die Anleitungen zu ASP.NET Core und Axum und Actix-web.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen von Node.js und npm aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Node.js und npm installieren

Node.js führt den Server aus, npm lädt Express herunter. Ist beides schon vorhanden (z. B. aus der Docusaurus-Anleitung), meldet apt das nur.

sudo apt install nodejs npm

Prüfen: Die Versionsnummer beginnt mit v18 oder höher, z. B. v22.22.1. Express 5 braucht mindestens Node.js 18.

node --version

Erstes Projekt

3. Projektordner anlegen

Ein eigener Ordner für das Projekt.

mkdir ~/hallo-express

4. In den Projektordner wechseln

Alle weiteren Befehle beziehen sich auf diesen Ordner.

cd ~/hallo-express

5. Projekt anlegen

Legt die Datei package.json an. Darin hält npm fest, welche Pakete das Projekt braucht. -y übernimmt alle Vorgaben, ohne nachzufragen.

npm init -y

6. Moderne Modul-Schreibweise einschalten

Erlaubt im Code die Schreibweise import … from …, die heute in JavaScript üblich ist.

npm pkg set type=module

7. Express installieren

Lädt Express mit seinen Abhängigkeiten in den Ordner node_modules (etwa 4 MB) und trägt es in package.json ein.

npm install express

Prüfen: Die Ausgabe zeigt express@5.2.1 (oder eine neuere 5er-Version).

npm ls

8. Server schreiben

Legt die Datei server.js an. Die wichtigsten Bausteine:

  • Middleware (app.use) – Funktionen, die jede Anfrage der Reihe nach durchläuft, bevor eine Route sie beantwortet. express.json() liest mitgeschickte JSON-Inhalte in req.body ein. Die eigene Middleware darunter schreibt jede Anfrage ins Terminal und reicht sie mit next() weiter.
  • Routen (app.get, app.post) – legen fest, welche Funktion welche Adresse und Methode beantwortet. req enthält die Anfrage (z. B. req.query für Werte aus der Adresse), mit res wird geantwortet.
  • res.json() wandelt ein Objekt in JSON um, res.status() setzt den HTTP-Status, z. B. 201 Created oder 400 Bad Request.
  • Die letzte Middleware fängt alle Adressen ab, für die es keine Route gibt, und antwortet mit 404 als JSON.
  • app.listen(3000, '127.0.0.1', …) – nur vom eigenen Rechner aus erreichbar, auf Port 3000. Ohne die Adresse wäre der Server aus dem ganzen Netz erreichbar.
nano server.js

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

import express from 'express'

const app = express()

// Middleware: läuft vor jeder Anfrage. express.json() liest JSON-Inhalte ein
app.use(express.json())

// Eigene Middleware: protokolliert jede Anfrage im Terminal
app.use((req, res, next) => {
  console.log(`${new Date().toLocaleTimeString('de-DE')} ${req.method} ${req.url}`)
  next()
})

// Notizen nur im Arbeitsspeicher: Nach einem Neustart sind sie weg
const notizen = []

// GET /hallo?name=... liefert eine Begrüßung als JSON
app.get('/hallo', (req, res) => {
  res.json({ gruss: `Hallo ${req.query.name ?? 'Welt'}!` })
})

// GET /notizen liefert alle Notizen
app.get('/notizen', (req, res) => {
  res.json(notizen)
})

// POST /notizen legt eine Notiz an; der Inhalt kommt als JSON
app.post('/notizen', (req, res) => {
  if (!req.body?.titel) {
    return res.status(400).json({ fehler: 'Feld "titel" fehlt' })
  }
  const notiz = { id: notizen.length + 1, titel: req.body.titel }
  notizen.push(notiz)
  res.status(201).location(`/notizen/${notiz.id}`).json(notiz)
})

// Alles andere: 404 als JSON statt der Standard-HTML-Seite
app.use((req, res) => {
  res.status(404).json({ fehler: 'Nicht gefunden' })
})

// Nur vom eigenen Rechner aus erreichbar, Port 3000
app.listen(3000, '127.0.0.1', () => {
  console.log('Express läuft auf http://127.0.0.1:3000')
})

9. Startbefehle festlegen

Trägt zwei Kurzbefehle in package.json ein:

  • npm start – startet den Server normal
  • npm run dev – startet ihn mit --watch: Node.js startet den Server bei jeder gespeicherten Änderung an server.js automatisch neu
npm pkg set scripts.start="node server.js" scripts.dev="node --watch server.js"

Starten und testen

10. Server im Entwicklungsmodus starten

Das Terminal bleibt belegt, solange der Server läuft. Hier erscheinen auch die Zeilen der Protokoll-Middleware.

npm run dev

Prüfen: Die letzte Zeile lautet Express läuft auf http://127.0.0.1:3000.

11. Notiz anlegen

Öffne ein zweites Terminal und schicke eine neue Notiz als JSON an den Server. -i zeigt zusätzlich die Kopfzeilen der Antwort.

curl -i -X POST http://localhost:3000/notizen -H "Content-Type: application/json" -d '{"titel": "Erste Notiz"}'

Prüfen: Die erste Zeile lautet HTTP/1.1 201 Created, weiter unten steht Location: /notizen/1, die letzte Zeile ist {"id":1,"titel":"Erste Notiz"}. Im ersten Terminal erscheint eine Zeile wie 22:18:41 POST /notizen.

12. Weitere Adressen testen

Diese Aufrufe zeigen die übrigen Routen und die Fehlerbehandlung:

AufrufAntwort
curl http://localhost:3000/notizen[{"id":1,"titel":"Erste Notiz"}]
curl "http://localhost:3000/hallo?name=Thorsten"{"gruss":"Hallo Thorsten!"}
curl -X POST http://localhost:3000/notizen -H "Content-Type: application/json" -d '{}'{"fehler":"Feld \"titel\" fehlt"} (Status 400)
curl http://localhost:3000/gibtsnicht{"fehler":"Nicht gefunden"} (Status 404)

13. Automatischen Neustart ausprobieren

Ändere in server.js das Wort Hallo in der Route /hallo z. B. in Servus und speichere die Datei. Im ersten Terminal erscheint Restarting 'server.js', danach startet der Server neu.

Prüfen: curl http://localhost:3000/hallo liefert jetzt {"gruss":"Servus Welt!"}. Die Notizen aus Schritt 11 sind durch den Neustart verloren, weil sie nur im Arbeitsspeicher lagen.

14. Server beenden

Wechsle in das erste Terminal und drücke Strg+C.

Wie geht es weiter?

  • Betrieb: Auf einem Server startet man die Anwendung mit npm start über einen systemd-Dienst (siehe die Dienstdatei in der Qdrant-Anleitung als Vorlage) und setzt nginx davor, der auch HTTPS übernimmt. Setze dort die Umgebungsvariable NODE_ENV=production, damit Express Fehlermeldungen knapper ausgibt.
  • Datenbank: Das Paket pg verbindet Node.js mit PostgreSQL, Werkzeuge wie Prisma oder Drizzle bilden Tabellen auf JavaScript-Objekte ab.
  • HTML-Seiten: Mit express.static('public') liefert Express Dateien aus einem Ordner aus. Für dynamische Seiten gibt es Vorlagensysteme wie EJS oder Pug.
  • Sicherheit: Die Middleware helmet setzt sinnvolle Sicherheits-Kopfzeilen, express-rate-limit bremst zu viele Anfragen.

Deinstallieren

1. Projekt entfernen

Löscht den Projektordner samt node_modules.

rm -rf ~/hallo-express

2. Optional: Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (z. B. Antora, Docusaurus, VitePress, Starlight oder Excalidraw).

sudo apt purge nodejs npm
sudo apt autoremove

Prüfen: Der Projektordner existiert nicht mehr.

ls ~/hallo-express

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

C

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

C ist eine schlanke, maschinennahe Programmiersprache, in der Betriebssysteme, Treiber und viele Grundprogramme von Linux geschrieben sind. Wer C lernt, versteht, wie Speicher und Prozessor tatsächlich arbeiten.

Vorbemerkungen

  • Compiler: C-Quelltext wird vor dem Start in ein ausführbares Programm übersetzt. Unter Ubuntu ist dafür der GCC (GNU Compiler Collection) üblich, in Ubuntu 26.04 in Version 15. Als Alternative gibt es Clang (Version 21), das oft verständlichere Fehlermeldungen ausgibt.
  • Paket build-essential: Dieses Sammelpaket enthält alles, was man zum Übersetzen braucht: gcc, g++, make und die Header-Dateien der C-Standardbibliothek. Es ist auch die Grundlage für die Anleitung C++.
  • Editor: Zum Schreiben reicht jeder Texteditor, z. B. GNU nano, Vim oder Visual Studio Code mit der Erweiterung „C/C++“.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Compiler und Build-Werkzeuge installieren

Installiert GCC, make und die Header-Dateien der Standardbibliothek. Ohne diese Dateien kennt der Compiler z. B. printf nicht.

sudo apt install build-essential

Prüfen: Die Versionsnummer von GCC wird angezeigt, z. B. gcc (Ubuntu 15.2.0-…) 15.2.0.

gcc --version

3. Debugger installieren

gdb lässt ein Programm Zeile für Zeile ablaufen und zeigt dabei die Werte der Variablen. Das hilft enorm bei der Fehlersuche, gerade bei Abstürzen durch falsche Speicherzugriffe.

sudo apt install gdb

Prüfen:

gdb --version

4. Optional: Clang installieren

Ein zweiter Compiler ist nützlich, um zu prüfen, ob der eigene Code nicht nur mit GCC funktioniert. Der Befehl heißt danach clang.

sudo apt install clang

Prüfen:

clang --version

Erstes Programm

5. Arbeitsordner anlegen

Ein eigener Ordner hält die Übungsdateien zusammen.

mkdir -p ~/c-uebung

6. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/c-uebung

7. Quelltext anlegen

Legt die Datei hallo.c an. Das Programm gibt einen Gruß aus und addiert in einer Schleife die Zahlen von 1 bis 10.

nano hallo.c

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

#include <stdio.h>

int main(void)
{
    const char *name = "Ubuntu";
    int summe = 0;

    for (int i = 1; i <= 10; i++) {
        summe += i;
    }

    printf("Hallo %s!\n", name);
    printf("Summe von 1 bis 10: %d\n", summe);
    return 0;
}

8. Programm übersetzen

Erzeugt aus hallo.c die ausführbare Datei hallo. Die Schalter bedeuten:

  • -Wall -Wextra – Warnungen bei verdächtigem Code einschalten; für Einsteiger sehr zu empfehlen.
  • -g – Informationen für den Debugger einbauen.
  • -o hallo – Name der erzeugten Datei.
gcc -Wall -Wextra -g -o hallo hallo.c

Prüfen: Der Befehl gibt nichts aus, und im Ordner liegt jetzt die Datei hallo.

ls -l hallo

9. Programm starten

Das ./ sagt der Shell, dass das Programm im aktuellen Ordner liegt.

./hallo

Prüfen: Die Ausgabe lautet:

Hallo Ubuntu!
Summe von 1 bis 10: 55

10. Optional: Mit dem Debugger untersuchen

Startet gdb mit dem Programm. Innerhalb von gdb setzt break main einen Haltepunkt am Anfang von main, run startet, next geht eine Zeile weiter, print summe zeigt den Wert der Variablen und quit beendet den Debugger.

gdb ./hallo

Mehrere Dateien mit make übersetzen

Sobald ein Projekt aus mehreren Dateien besteht, ist es mühsam, gcc jedes Mal von Hand aufzurufen. make liest die Bauanleitung aus einer Datei Makefile und übersetzt nur, was sich geändert hat.

11. Makefile anlegen

Legt ein einfaches Makefile für hallo.c an. Wichtig: Die eingerückten Zeilen müssen mit einem Tabulator beginnen, nicht mit Leerzeichen. Sonst bricht make mit missing separator ab.

nano Makefile

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V). Beim Einfügen bleiben die Tabulatoren erhalten. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Willst du den Inhalt lieber abtippen und hast in ~/.nanorc die Einstellungen aus der Anleitung GNU nano, schalte vorher zwei davon für diese Sitzung ab. Alt+O sorgt dafür, dass die Taste Tab einen echten Tabulator statt Leerzeichen einfügt. Alt+I verhindert, dass nano die Einrückung in die nächste Zeile übernimmt und so auch clean: einrückt. Drücke dann vor $(CC) und vor rm jeweils Tab.

CFLAGS = -Wall -Wextra -g

hallo: hallo.c
	$(CC) $(CFLAGS) -o hallo hallo.c

clean:
	rm -f hallo

Prüfen: Vor $(CC) und rm steht ^I, das Zeichen für einen Tabulator.

cat -A Makefile

12. Mit make bauen

Löscht zuerst die alte Programmdatei und übersetzt dann neu.

make clean && make

Prüfen: make zeigt den ausgeführten Befehl an (cc ist unter Ubuntu ein anderer Name für gcc), und ./hallo läuft wie in Schritt 9. Ein zweiter Aufruf von make meldet „hallo“ ist bereits aktuell, weil sich nichts geändert hat.

Wie geht es weiter?

  • Größere Projekte: Für Projekte mit vielen Dateien und Bibliotheken ist CMake verbreitet; ein Beispiel steht in der Anleitung C++.
  • Speicherfehler finden: Der Schalter -fsanitize=address beim Übersetzen lässt das Programm bei falschen Speicherzugriffen sofort mit einer genauen Meldung abbrechen. Das Paket valgrind leistet Ähnliches ohne neues Übersetzen.
  • Handbuchseiten: Zu fast jeder Funktion der Standardbibliothek gibt es eine Beschreibung im Terminal, z. B. man 3 printf. Dafür das Paket manpages-dev installieren.

Deinstallieren

1. Übungsordner entfernen

Löscht die Beispieldateien.

rm -rf ~/c-uebung

2. Debugger und Clang entfernen

Entfernt die Zusatzwerkzeuge aus dieser Anleitung.

sudo apt purge gdb clang

3. Optional: Compiler entfernen

Nur ausführen, wenn nichts anderes den Compiler braucht. Auch die Anleitung C++ sowie Programme, die bei der Installation Code übersetzen (z. B. Treiber über DKMS oder Python-Pakete mit C-Erweiterungen), sind darauf angewiesen.

sudo apt purge build-essential

4. Nicht mehr benötigte Abhängigkeiten entfernen

Räumt Pakete auf, die nur für die entfernten Programme installiert wurden, z. B. gcc und make.

sudo apt autoremove

Prüfen: Die Meldung lautet gdb: Befehl nicht gefunden bzw. command not found.

gdb --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

C++

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

C++ erweitert C um Klassen, Vorlagen (Templates) und eine umfangreiche Standardbibliothek. Die Sprache wird überall dort eingesetzt, wo hohe Geschwindigkeit zählt: in Spielen, Browsern, Datenbanken, Grafikprogrammen und eingebetteten Systemen.

Vorbemerkungen

  • Compiler: Unter Ubuntu übersetzt meist g++ aus der GNU Compiler Collection (Version 15 in Ubuntu 26.04) den Quelltext. Alternativ gibt es clang++ (Version 21).
  • Sprachstandard: C++ erscheint etwa alle drei Jahre in einer neuen Fassung (C++17, C++20, C++23 …). Diese Anleitung nutzt C++23, weil es die bequeme Ausgabefunktion std::println mitbringt. Der Standard wird beim Übersetzen mit -std=c++23 gewählt.
  • CMake: Größere C++-Projekte beschreibt man nicht mit handgeschriebenen Compiler-Aufrufen, sondern mit CMake. CMake erzeugt daraus die eigentlichen Bauanweisungen und wird von den meisten Entwicklungsumgebungen direkt verstanden.
  • Grundlagen aus C: Das Paket build-essential ist dasselbe wie in der Anleitung C. Wer die schon durchgearbeitet hat, kann Schritt 2 überspringen.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Compiler und Build-Werkzeuge installieren

Installiert g++, gcc, make und die Header-Dateien der Standardbibliotheken.

sudo apt install build-essential

Prüfen: Die Versionsnummer wird angezeigt, z. B. g++ (Ubuntu 15.2.0-…) 15.2.0.

g++ --version

3. CMake installieren

Installiert das Build-System CMake.

sudo apt install cmake

Prüfen:

cmake --version

4. Debugger installieren

Mit gdb lässt sich ein Programm schrittweise ausführen, um Fehler zu finden.

sudo apt install gdb

Prüfen:

gdb --version

5. Optional: Clang und Hilfswerkzeuge installieren

clang bringt den Compiler clang++ mit, clang-format rückt Quelltext einheitlich ein und clangd liefert Editoren wie Visual Studio Code oder Neovim Autovervollständigung und Fehlerhinweise.

sudo apt install clang clang-format clangd

Prüfen:

clang++ --version

Erstes Programm

6. Arbeitsordner anlegen

Ein eigener Ordner für die Übungsdateien.

mkdir -p ~/cpp-uebung

7. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/cpp-uebung

8. Quelltext anlegen

Legt die Datei main.cpp an. Das Programm speichert einige Namen in einem std::vector, gibt sie nacheinander aus und zählt sie.

nano main.cpp

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

#include <print>
#include <string>
#include <vector>

int main()
{
    std::vector<std::string> sprachen{"C", "C++", "Java", "Python"};

    for (const auto& sprache : sprachen) {
        std::println("Ich lerne {}", sprache);
    }
    std::println("Anzahl: {}", sprachen.size());
}

9. Programm übersetzen

Übersetzt main.cpp nach dem Standard C++23 mit eingeschalteten Warnungen in die Datei hallo.

g++ -std=c++23 -Wall -Wextra -g -o hallo main.cpp

Prüfen: Es erscheint keine Fehlermeldung. Meldet der Compiler print: No such file or directory, fehlt der Schalter -std=c++23.

10. Programm starten

./hallo

Prüfen: Die Ausgabe lautet:

Ich lerne C
Ich lerne C++
Ich lerne Java
Ich lerne Python
Anzahl: 4

Projekt mit CMake bauen

11. CMake-Beschreibung anlegen

Die Datei CMakeLists.txt sagt CMake, wie das Projekt heißt, welcher Sprachstandard gilt und aus welchen Quelldateien das Programm entsteht.

nano CMakeLists.txt

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

cmake_minimum_required(VERSION 3.28)
project(hallo LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(hallo main.cpp)

12. Build-Ordner einrichten

CMake prüft den Compiler und legt im Unterordner build alle Bauanweisungen ab. So bleiben die erzeugten Dateien vom Quelltext getrennt.

cmake -S . -B build

Prüfen: Die letzte Zeile lautet -- Build files have been written to: …/cpp-uebung/build.

13. Projekt bauen

Übersetzt das Projekt. Nach Änderungen am Quelltext genügt es, diesen Befehl erneut auszuführen.

cmake --build build

Prüfen: Die Meldung [100%] Built target hallo erscheint.

14. Programm starten

Das fertige Programm liegt im Build-Ordner.

./build/hallo

Prüfen: Die Ausgabe ist dieselbe wie in Schritt 10.

Wie geht es weiter?

  • Entwicklungsumgebung: Visual Studio Code mit den Erweiterungen „C/C++“ und „CMake Tools“ öffnet CMake-Projekte direkt. Auch CLion von JetBrains arbeitet mit CMake.
  • Bibliotheken: Viele verbreitete C++-Bibliotheken gibt es als Pakete mit der Endung -dev, z. B. libboost-all-dev für Boost oder libfmt-dev. CMake findet sie über find_package(...).
  • Speicherfehler finden: Die Schalter -fsanitize=address,undefined machen falsche Speicherzugriffe und undefiniertes Verhalten beim Ausführen sichtbar.

Deinstallieren

1. Übungsordner entfernen

Löscht Quelltext und Build-Ordner.

rm -rf ~/cpp-uebung

2. Zusatzwerkzeuge entfernen

Entfernt CMake, den Debugger und die Clang-Werkzeuge.

sudo apt purge cmake gdb clang clang-format clangd

3. Optional: Compiler entfernen

Nur ausführen, wenn nichts anderes den Compiler braucht, z. B. die Anleitung C oder Treiber, die über DKMS übersetzt werden.

sudo apt purge build-essential

4. Nicht mehr benötigte Abhängigkeiten entfernen

Räumt Pakete auf, die nur für die entfernten Programme installiert wurden.

sudo apt autoremove

Prüfen: Die Meldung lautet cmake: Befehl nicht gefunden bzw. command not found.

cmake --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Java

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Java ist eine objektorientierte Programmiersprache, deren Programme auf einer virtuellen Maschine laufen und dadurch ohne Änderung unter Linux, Windows und macOS funktionieren. Sie ist in Unternehmensanwendungen, Android-Apps und Serverprogrammen weit verbreitet.

Vorbemerkungen

  • JDK und JRE: Zum Programmieren braucht man das JDK (Java Development Kit) mit Compiler javac. Die JRE (Java Runtime Environment) allein kann Programme nur ausführen. Das JDK enthält die Laufzeitumgebung bereits.
  • OpenJDK 25: Ubuntu 26.04 liefert OpenJDK 25, die aktuelle Version mit Langzeitunterstützung (LTS). Das Paket default-jdk verweist darauf und wird bei künftigen Ubuntu-Versionen automatisch auf die dann aktuelle LTS-Version umgestellt. Ältere und neuere Versionen (z. B. openjdk-21-jdk, openjdk-26-jdk) lassen sich zusätzlich installieren.
  • Kompakte Quelldateien: Seit Java 25 darf ein kleines Programm ohne Klassendeklaration und ohne public static geschrieben werden. Das senkt die Einstiegshürde deutlich; die Anleitung zeigt beide Schreibweisen.
  • Entwicklungsumgebung: Für größere Projekte eignen sich IntelliJ IDEA, Eclipse IDE oder Visual Studio Code mit dem „Extension Pack for Java“.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. JDK installieren

Installiert OpenJDK 25 mit Compiler javac, Laufzeitumgebung java und weiteren Werkzeugen wie jshell.

sudo apt install default-jdk

Prüfen: Die Ausgabe beginnt mit openjdk version "25…".

java -version

Prüfen: Auch der Compiler ist vorhanden.

javac -version

3. Optional: Build-Werkzeug Maven installieren

Maven lädt benötigte Bibliotheken automatisch herunter und baut Projekte nach einem festen Schema. Es wird z. B. für Spring Boot gebraucht.

sudo apt install maven

Prüfen:

mvn -version

4. Optional: Zwischen mehreren Java-Versionen wechseln

Nur nötig, wenn mehrere JDKs installiert sind. Der Befehl zeigt eine nummerierte Liste; die Eingabe der Nummer legt fest, welche Version der Befehl java startet. Für javac gibt es den gleichen Befehl mit javac am Ende.

sudo update-alternatives --config java

Erstes Programm

5. Arbeitsordner anlegen

Ein eigener Ordner für die Übungsdateien.

mkdir -p ~/java-uebung

6. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/java-uebung

7. Kompakte Quelldatei anlegen

Legt Hallo.java in der kurzen Schreibweise ab Java 25 an. Die Klasse IO liest eine Zeile von der Tastatur und gibt Text aus.

nano Hallo.java

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

void main() {
    String name = IO.readln("Wie heißt du? ");
    IO.println("Hallo " + name + "!");
}

8. Quelldatei direkt starten

Bei einzelnen Dateien kann java den Quelltext selbst übersetzen und sofort ausführen. Ein getrennter Aufruf von javac ist nicht nötig.

java Hallo.java

Prüfen: Das Programm fragt nach einem Namen. Nach der Eingabe von z. B. Thorsten erscheint Hallo Thorsten!.

Klassische Schreibweise mit javac

9. Klasse anlegen

So sehen Java-Programme in Büchern, älteren Projekten und größeren Anwendungen aus: Jede Datei enthält eine Klasse, deren Name dem Dateinamen entspricht.

nano Rechner.java

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

public class Rechner {
    public static void main(String[] args) {
        int summe = 0;
        for (int i = 1; i <= 10; i++) {
            summe += i;
        }
        System.out.println("Summe von 1 bis 10: " + summe);
    }
}

10. Quelltext übersetzen

javac erzeugt die Datei Rechner.class mit dem Bytecode für die virtuelle Maschine.

javac Rechner.java

Prüfen: Im Ordner liegt jetzt Rechner.class.

ls

11. Programm starten

Beim Start wird nur der Klassenname angegeben, ohne .class.

java Rechner

Prüfen: Die Ausgabe lautet Summe von 1 bis 10: 55.

12. Optional: Mit JShell ausprobieren

jshell nimmt einzelne Java-Anweisungen entgegen und zeigt das Ergebnis sofort. Ideal zum Ausprobieren, z. B. Math.sqrt(2) oder "Java".repeat(3). Beenden mit /exit.

jshell

Wie geht es weiter?

  • Projekte mit Maven: mvn archetype:generate legt ein vollständiges Projekt mit Ordnerstruktur und Testrahmen an. Gradle ist die verbreitete Alternative.
  • Webanwendungen: Die Anleitung Spring Boot baut darauf auf.
  • Dokumentation: Die Beschreibung aller Klassen der Standardbibliothek steht als Javadoc auf den Seiten von Oracle bzw. OpenJDK; das Paket openjdk-25-doc installiert sie lokal.

Deinstallieren

1. Übungsordner entfernen

Löscht die Beispieldateien.

rm -rf ~/java-uebung

2. Maven entfernen

Nur nötig, wenn Maven installiert wurde.

sudo apt purge maven

3. JDK entfernen

Entfernt das Verweispaket und OpenJDK 25. Programme wie IntelliJ IDEA oder Eclipse bringen meist ein eigenes JDK mit und laufen weiter.

sudo apt purge default-jdk default-jdk-headless openjdk-25-jdk openjdk-25-jdk-headless

4. Laufzeitumgebung und Abhängigkeiten entfernen

Räumt die Laufzeitumgebung (openjdk-25-jre…) und weitere nur für Java installierte Pakete auf.

sudo apt autoremove

5. Heruntergeladene Maven-Bibliotheken löschen

Maven speichert Bibliotheken im Ordner ~/.m2. Wird Maven nicht mehr gebraucht, kann er weg.

rm -rf ~/.m2

Prüfen: Die Meldung lautet javac: Befehl nicht gefunden bzw. command not found.

javac -version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Python

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Python ist eine leicht lesbare Programmiersprache, die sich gleichermaßen für kleine Skripte, Datenanalyse, Webanwendungen und künstliche Intelligenz eignet. Wegen ihrer klaren Syntax ist sie auch eine beliebte erste Programmiersprache.

Vorbemerkungen

  • Bereits vorinstalliert: Ubuntu 26.04 bringt Python 3.14 mit, weil viele Systemprogramme darauf aufbauen. Der Befehl heißt python3. Es fehlen nur die Werkzeuge, um zusätzliche Pakete zu installieren.
  • Systempython nicht entfernen: Das Paket python3 darf nicht deinstalliert werden, sonst funktionieren Teile von Ubuntu nicht mehr (u. a. Paketverwaltung und Desktop-Werkzeuge).
  • Virtuelle Umgebungen: Ubuntu verhindert, dass pip Pakete aus dem Internet direkt in das Systempython schreibt. Ein Versuch endet mit der Meldung externally-managed-environment. Stattdessen legt man pro Projekt eine virtuelle Umgebung (venv) an: einen Ordner mit eigenem Python und eigenen Paketen, der das System nicht berührt.
  • Pakete aus apt: Viele verbreitete Bibliotheken gibt es auch als Ubuntu-Paket mit dem Präfix python3-, z. B. python3-requests. Diese sind für das ganze System verfügbar, aber oft etwas älter als die Fassung auf PyPI.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Vorhandenes Python prüfen

Zeigt, welche Python-Version bereits installiert ist.

python3 --version

Prüfen: Die Ausgabe lautet Python 3.14.….

3. pip und venv installieren

python3-venv erstellt virtuelle Umgebungen, python3-pip installiert Pakete aus dem Python-Paketverzeichnis PyPI. python3-dev enthält Header-Dateien, die manche Pakete zum Übersetzen von C-Erweiterungen brauchen.

sudo apt install python3-venv python3-pip python3-dev

Prüfen:

pip3 --version

4. Optional: Befehl python einrichten

Viele Anleitungen im Internet schreiben python statt python3. Dieses kleine Paket legt den Befehl python als Verweis auf python3 an.

sudo apt install python-is-python3

Prüfen: Die Ausgabe ist dieselbe wie bei python3 --version.

python --version

Erstes Programm

5. Arbeitsordner anlegen

Ein eigener Ordner für das Übungsprojekt.

mkdir -p ~/python-uebung

6. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/python-uebung

7. Skript anlegen

Legt hallo.py an. Das Skript nummeriert eine Liste von Programmiersprachen und gibt das heutige Datum im deutschen Format aus.

nano hallo.py

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

from datetime import date

sprachen = ["C", "C++", "Java", "Python", "C#", "JavaScript"]

for nummer, sprache in enumerate(sprachen, start=1):
    print(f"{nummer}. {sprache}")

print(f"Heute ist der {date.today():%d.%m.%Y}.")

8. Skript ausführen

Python übersetzt nichts vorab, sondern führt den Quelltext direkt aus.

python3 hallo.py

Prüfen: Es erscheinen sechs nummerierte Zeilen von 1. C bis 6. JavaScript und danach das heutige Datum.

Virtuelle Umgebung und Pakete

9. Virtuelle Umgebung anlegen

Erstellt im Projektordner den Unterordner .venv mit einer eigenen Python-Installation.

python3 -m venv .venv

10. Virtuelle Umgebung aktivieren

Sorgt dafür, dass python und pip im aktuellen Terminal aus .venv kommen. Das muss in jedem neuen Terminal wiederholt werden.

source .venv/bin/activate

Prüfen: Vor der Eingabeaufforderung steht jetzt (.venv), und der folgende Befehl zeigt einen Pfad innerhalb von ~/python-uebung/.venv.

which python

11. Paket installieren

Installiert als Beispiel die Bibliothek requests für HTTP-Anfragen. Sie landet nur in dieser virtuellen Umgebung, sudo ist deshalb nicht nötig.

pip install requests

Prüfen: Die installierte Version wird angezeigt.

python -c "import requests; print(requests.__version__)"

12. Abhängigkeiten festhalten

Schreibt alle installierten Pakete mit Versionsnummer in requirements.txt. Mit dieser Datei lässt sich die Umgebung auf einem anderen Rechner per pip install -r requirements.txt genauso wieder aufbauen.

pip freeze > requirements.txt

13. Virtuelle Umgebung verlassen

Schaltet wieder auf das Systempython um. (.venv) verschwindet aus der Eingabeaufforderung.

deactivate

Wie geht es weiter?

  • Interaktiv ausprobieren: python3 ohne Dateiname startet eine Eingabezeile, in der jede Anweisung sofort ausgeführt wird. Beenden mit exit() oder Strg+D.
  • Programme mit Kommandozeile: Werkzeuge, die als Befehl genutzt werden sollen (z. B. mkdocs), installiert man am besten mit pipx (sudo apt install pipx). Jedes bekommt automatisch eine eigene virtuelle Umgebung.
  • Webanwendungen: Die Anleitung Django baut auf dieser Grundlage auf.
  • Editor: Visual Studio Code mit der Erweiterung „Python“ erkennt .venv im Projektordner automatisch.

Deinstallieren

1. Übungsordner entfernen

Löscht das Skript und die virtuelle Umgebung samt installierter Pakete.

rm -rf ~/python-uebung

2. Zusatzpakete entfernen

Entfernt die Werkzeuge aus dieser Anleitung. Das vorinstallierte python3 bleibt erhalten und darf nicht entfernt werden.

sudo apt purge python3-venv python3-pip python3-dev python-is-python3

3. Nicht mehr benötigte Abhängigkeiten entfernen

Räumt Pakete auf, die nur für die entfernten Werkzeuge installiert wurden.

sudo apt autoremove

Prüfen: pip3 ist nicht mehr vorhanden (Befehl nicht gefunden), python3 --version funktioniert aber weiterhin.

pip3 --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

C#

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

C# (gesprochen „C Sharp“) ist die wichtigste Programmiersprache der Plattform .NET von Microsoft. Mit ihr entstehen Kommandozeilenprogramme, Webanwendungen, Desktop-Programme und Spiele (z. B. mit Unity), und sie läuft heute genauso unter Linux wie unter Windows.

Vorbemerkungen

  • .NET SDK: Zum Programmieren in C# braucht man das .NET SDK. Es enthält den Befehl dotnet, den C#-Compiler, die Laufzeitumgebung und Projektvorlagen.
  • Installation über apt: Ubuntu 26.04 liefert .NET 10 in den eigenen Paketquellen. Das ist die aktuelle Version mit Langzeitunterstützung (LTS) bis November 2028 und bringt C# 14 mit. Ein Paketarchiv von Microsoft ist nicht nötig.
  • Zwei Arbeitsweisen: Seit .NET 10 lässt sich eine einzelne .cs-Datei direkt mit dotnet run starten, ganz ohne Projektdatei. Für richtige Programme legt man ein Projekt mit dotnet new an. Diese Anleitung zeigt beides.
  • Entwicklungsumgebung: Visual Studio Code mit der Erweiterung „C# Dev Kit“ oder JetBrains Rider. Das klassische Visual Studio gibt es nur für Windows, siehe Microsoft Visual Studio.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuelle Version des .NET SDK kennt.

sudo apt update

2. .NET SDK installieren

Installiert das SDK mitsamt Laufzeitumgebungen. Ist es schon vorhanden (z. B. aus der Anleitung ASP.NET Core), meldet apt das nur.

sudo apt install dotnet-sdk-10.0

Prüfen: Die Ausgabe beginnt mit 10.0..

dotnet --version

3. Optional: Nutzungsstatistik abschalten

Die Befehlszeile dotnet kann anonyme Nutzungsdaten an Microsoft senden. Diese Zeile in ~/.bashrc schaltet das für alle künftigen Terminals ab. Danach ein neues Terminal öffnen.

nano ~/.bashrc

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile an (im Terminal mit Strg+Umschalt+V). Speichere mit Strg+O und Enter und beende nano mit Strg+X:

export DOTNET_CLI_TELEMETRY_OPTOUT=1

Einzelne Datei ausführen

4. Arbeitsordner anlegen

Ein eigener Ordner für die Übungsdateien.

mkdir -p ~/csharp-uebung

5. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/csharp-uebung

6. Quelltext anlegen

Legt hallo.cs an. Die Anweisungen stehen direkt in der Datei, eine Klasse mit Main-Methode ist nicht nötig. Sum() und Max() stammen aus LINQ, den Abfragefunktionen von .NET.

nano hallo.cs

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

var zahlen = new[] { 3, 1, 4, 1, 5 };
Console.WriteLine($"Hallo aus C# {Environment.Version}!");
Console.WriteLine($"Summe: {zahlen.Sum()}, größte Zahl: {zahlen.Max()}");

7. Datei ausführen

dotnet übersetzt die Datei im Hintergrund und startet sie. Der erste Aufruf dauert einige Sekunden, weitere Aufrufe gehen schneller.

dotnet run hallo.cs

Prüfen: Die Ausgabe lautet:

Hallo aus C# 10.0.…!
Summe: 14, größte Zahl: 5

Konsolenprojekt anlegen

8. Projekt erzeugen

Erzeugt aus der Vorlage console ein Projekt im Unterordner Rechner. Darin liegen die Projektdatei Rechner.csproj und der Quelltext Program.cs.

dotnet new console -o Rechner

9. In den Projektordner wechseln

dotnet run und dotnet build arbeiten mit dem Projekt im aktuellen Ordner.

cd Rechner

10. Quelltext ersetzen

Überschreibt die Vorlage mit einem kleinen Programm, das eine Klasse Konto anlegt und benutzt. Klassen stehen in dieser Schreibweise unterhalb der Anweisungen.

nano Program.cs

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

var konto = new Konto("Thorsten");
konto.Einzahlen(100m);
konto.Abheben(30m);
Console.WriteLine($"{konto.Inhaber}: {konto.Stand:C}");

class Konto(string inhaber)
{
    public string Inhaber { get; } = inhaber;
    public decimal Stand { get; private set; }

    public void Einzahlen(decimal betrag) => Stand += betrag;

    public void Abheben(decimal betrag)
    {
        if (betrag > Stand)
            throw new InvalidOperationException("Nicht genug Guthaben");
        Stand -= betrag;
    }
}

11. Projekt starten

Übersetzt das Projekt und startet es.

dotnet run

Prüfen: Die Ausgabe lautet Thorsten: 70,00 € (Währungsformat abhängig von der Spracheinstellung des Systems).

12. Optional: Fertiges Programm erzeugen

Erstellt eine optimierte Fassung im Ordner bin/Release/net10.0/publish. Das Programm dort lässt sich auf jedem Rechner mit .NET-10-Laufzeitumgebung per ./Rechner starten.

dotnet publish -c Release

Prüfen:

./bin/Release/net10.0/publish/Rechner

Wie geht es weiter?

  • Bibliotheken: Pakete aus dem Verzeichnis NuGet fügt man mit dotnet add package <Name> zum Projekt hinzu.
  • Tests: Die Vorlage xunit legt ein Testprojekt an; dotnet test führt die Tests aus.
  • Webanwendungen: Die Anleitung ASP.NET Core baut darauf auf.
  • Weitere Vorlagen: dotnet new list zeigt alle installierten Projektvorlagen.

Deinstallieren

1. Übungsordner entfernen

Löscht die Beispieldatei und das Projekt.

rm -rf ~/csharp-uebung

2. .NET SDK entfernen

Nur ausführen, wenn .NET auch nicht mehr für ASP.NET Core gebraucht wird.

sudo apt purge dotnet-sdk-10.0

3. Nicht mehr benötigte Abhängigkeiten entfernen

Entfernt die Laufzeitumgebungen und weitere nur für .NET installierte Pakete.

sudo apt autoremove

4. Zwischenspeicher im Benutzerordner löschen

dotnet legt heruntergeladene NuGet-Pakete und Einstellungen in ~/.nuget und ~/.dotnet ab.

rm -rf ~/.nuget ~/.dotnet

5. Optional: Eintrag für die Nutzungsstatistik entfernen

Nur nötig, wenn Schritt 3 der Installation ausgeführt wurde. Löscht die Zeile wieder aus ~/.bashrc.

nano ~/.bashrc

Suche mit Strg+W nach DOTNET_CLI_TELEMETRY_OPTOUT und drücke Enter. Lösche die Zeile export DOTNET_CLI_TELEMETRY_OPTOUT=1 mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Meldung lautet dotnet: Befehl nicht gefunden bzw. command not found.

dotnet --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

JavaScript

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

JavaScript ist die Programmiersprache des Webs: Jeder Browser führt sie aus, um Webseiten interaktiv zu machen. Mit Node.js läuft JavaScript auch außerhalb des Browsers, etwa für Kommandozeilenwerkzeuge, Webserver und Build-Werkzeuge.

Vorbemerkungen

  • Browser oder Node.js: Zum Ausprobieren reicht die Entwicklerkonsole jedes Browsers (in Firefox und Chromium mit F12). Für Programme auf dem Rechner und für fast alle Werkzeuge der Webentwicklung braucht man aber Node.js. Diese Anleitung richtet Node.js ein.
  • Versionen: Ubuntu 26.04 liefert Node.js 22 (LTS) und npm 9. Für die Anleitungen in diesem Buch reicht das aus.
  • npm: Der Paketmanager npm lädt Bibliotheken aus dem npm-Verzeichnis und speichert sie pro Projekt im Ordner node_modules. Welche Pakete ein Projekt braucht, steht in der Datei package.json.
  • Grundlage für andere Anleitungen: Node.js wird u. a. für Express.js, Yjs und Automerge, Docusaurus, VitePress und Astro Starlight gebraucht.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Node.js und npm installieren

Installiert die JavaScript-Laufzeitumgebung node und den Paketmanager npm.

sudo apt install nodejs npm

Prüfen: Die Ausgabe beginnt mit v22..

node --version

Prüfen: Auch npm meldet seine Version.

npm --version

Erstes Programm

3. Arbeitsordner anlegen

Ein eigener Ordner für das Übungsprojekt.

mkdir -p ~/js-uebung

4. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/js-uebung

5. Skript anlegen

Legt hallo.js an. Das Skript filtert aus einer Liste alle Namen mit mehr als zwei Zeichen heraus und gibt sie zusammen mit der Node.js-Version aus.

nano hallo.js

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

const sprachen = ['C', 'C++', 'Java', 'Python', 'C#', 'JavaScript'];
const lang = sprachen.filter((s) => s.length > 2);

console.log(`Hallo aus Node.js ${process.version}!`);
console.log('Lange Namen:', lang.join(', '));

6. Skript ausführen

node liest die Datei und führt sie sofort aus, ein Übersetzungsschritt ist nicht nötig.

node hallo.js

Prüfen: Die Ausgabe lautet:

Hallo aus Node.js v22.…!
Lange Namen: C++, Java, Python, JavaScript

Projekt mit npm

7. Projekt anlegen

Erzeugt die Datei package.json mit Standardwerten. Sie beschreibt das Projekt und listet später die benötigten Pakete auf.

npm init -y

Prüfen: Die Datei package.json wird im Terminal angezeigt.

8. Moderne Modulschreibweise einschalten

Stellt das Projekt auf ES-Module um. Dann können Dateien andere Dateien und Pakete mit import … from … einbinden, so wie es auch im Browser üblich ist.

npm pkg set type=module

9. Paket installieren

Installiert als Beispiel die Bibliothek dayjs zum Rechnen mit Datum und Uhrzeit. Sie landet in node_modules, und package.json erhält einen Eintrag unter dependencies.

npm install dayjs

Prüfen: Das Paket erscheint in der Liste.

npm ls

10. Skript mit dem Paket anlegen

Legt datum.js an. Das Skript bindet dayjs ein und rechnet aus, welches Datum in 100 Tagen ist.

nano datum.js

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

import dayjs from 'dayjs';

const heute = dayjs();
const spaeter = heute.add(100, 'day');

console.log(`Heute:        ${heute.format('DD.MM.YYYY')}`);
console.log(`In 100 Tagen: ${spaeter.format('DD.MM.YYYY')}`);

11. Skript ausführen

node datum.js

Prüfen: Es erscheinen zwei Zeilen mit dem heutigen Datum und dem Datum in 100 Tagen.

12. Optional: Bei Änderungen automatisch neu starten

Mit --watch startet Node.js das Skript bei jedem Speichern neu. Das ist praktisch während der Entwicklung. Beenden mit Strg+C.

node --watch datum.js

Wie geht es weiter?

  • Interaktiv ausprobieren: node ohne Dateiname öffnet eine Eingabezeile für einzelne Anweisungen. Beenden mit .exit.
  • Neuere Node.js-Version: Wer eine aktuellere Version als 22 braucht, kann mit dem Versionsverwalter nvm weitere Versionen im eigenen Benutzerordner installieren, ohne die Ubuntu-Pakete zu verändern.
  • TypeScript: TypeScript ergänzt JavaScript um Typangaben und findet so viele Fehler schon beim Schreiben. Es wird pro Projekt mit npm install --save-dev typescript eingebunden.
  • Webserver: Die Anleitung Express.js baut darauf auf.
  • Editor: Visual Studio Code unterstützt JavaScript und TypeScript ohne zusätzliche Erweiterung.

Deinstallieren

1. Übungsordner entfernen

Löscht das Projekt samt node_modules.

rm -rf ~/js-uebung

2. Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (siehe Vorbemerkungen).

sudo apt purge nodejs npm

3. Nicht mehr benötigte Abhängigkeiten entfernen

Räumt Pakete auf, die nur für Node.js und npm installiert wurden.

sudo apt autoremove

4. Zwischenspeicher von npm löschen

npm speichert heruntergeladene Pakete in ~/.npm.

rm -rf ~/.npm

Prüfen: Die Meldung lautet node: Befehl nicht gefunden bzw. command not found.

node --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Go

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Go ist eine von Google entwickelte, bewusst einfach gehaltene Programmiersprache, die schnell übersetzt und eigenständige Programme ohne Abhängigkeiten erzeugt. Sie ist besonders beliebt für Netzwerkdienste, Kommandozeilenwerkzeuge und Cloud-Software wie Docker oder Kubernetes.

Vorbemerkungen

  • Installation über apt: Ubuntu 26.04 liefert Go 1.26 im Paket golang-go. Das Paket enthält den Befehl go, der übersetzt, testet, formatiert und Abhängigkeiten verwaltet.
  • Module: Jedes Go-Projekt ist ein Modul mit einer Datei go.mod. Darin stehen der Name des Moduls und die benötigten Bibliotheken. Fremde Bibliotheken lädt go selbst aus dem Internet; ein eigener Paketmanager ist nicht nötig.
  • Ordner ~/go: Heruntergeladene Bibliotheken landen in ~/go/pkg/mod, mit go install installierte Programme in ~/go/bin.
  • Neuere Version: Wer eine neuere Version als die von Ubuntu braucht, kann Go zusätzlich von der offiziellen Downloadseite nach /usr/local/go entpacken. Für den Einstieg reicht die apt-Version.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Go installieren

Installiert den Go-Compiler mit allen Werkzeugen und der Standardbibliothek.

sudo apt install golang-go

Prüfen: Die Ausgabe lautet z. B. go version go1.26… linux/amd64. Steht dort eine andere Version, liegt noch eine ältere Installation in /usr/local/go, die im Suchpfad zuerst gefunden wird.

go version

3. Ordner für installierte Programme in den Suchpfad aufnehmen

Programme, die später mit go install installiert werden, liegen in ~/go/bin. Damit die Shell sie findet, kommt dieser Ordner in den Suchpfad. Danach ein neues Terminal öffnen.

nano ~/.bashrc

Springe mit Strg+Ende ans Ende der Datei und füge in einer eigenen Zeile an (im Terminal mit Strg+Umschalt+V). Speichere mit Strg+O und Enter und beende nano mit Strg+X:

export PATH="$PATH:$HOME/go/bin"

Prüfen: Im neuen Terminal enthält die Ausgabe /go/bin.

echo $PATH

Erstes Programm

4. Projektordner anlegen

Ein eigener Ordner für das Übungsprojekt.

mkdir -p ~/hallo-go

5. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/hallo-go

6. Modul anlegen

Erzeugt die Datei go.mod. Der Name beispiel/hallo ist frei wählbar; bei veröffentlichten Projekten nimmt man meist die Adresse des Repositorys, z. B. github.com/name/projekt.

go mod init beispiel/hallo

Prüfen: Die Meldung lautet go: creating new go.mod: module beispiel/hallo.

7. Quelltext anlegen

Legt main.go an. Das Programm nummeriert eine Liste und gibt sie danach in einer Zeile aus. Go rückt mit Tabulatoren ein; das Werkzeug gofmt sorgt später automatisch dafür.

nano main.go

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

package main

import (
	"fmt"
	"strings"
)

func main() {
	sprachen := []string{"Go", "Rust", "PHP", "Kotlin", "TypeScript"}

	for i, s := range sprachen {
		fmt.Printf("%d. %s\n", i+1, s)
	}
	fmt.Println("Alle:", strings.Join(sprachen, ", "))
}

8. Programm starten

go run . übersetzt das Modul im aktuellen Ordner in einen temporären Ordner und startet es sofort.

go run .

Prüfen: Die Ausgabe lautet:

1. Go
2. Rust
3. PHP
4. Kotlin
5. TypeScript
Alle: Go, Rust, PHP, Kotlin, TypeScript

9. Eigenständiges Programm erzeugen

go build erzeugt die Datei hallo (benannt nach dem letzten Teil des Modulnamens). Sie enthält alles Nötige und läuft auch auf Rechnern ohne Go.

go build

Prüfen: Das Programm liefert dieselbe Ausgabe wie in Schritt 8.

./hallo

10. Quelltext prüfen und formatieren

go vet sucht nach typischen Fehlern, gofmt -l . listet Dateien auf, die nicht einheitlich formatiert sind. Mit gofmt -w . werden sie korrigiert.

go vet ./... && gofmt -l .

Prüfen: Beide Befehle geben nichts aus – der Code ist in Ordnung.

Wie geht es weiter?

  • Bibliotheken: go get <Adresse> fügt eine Bibliothek zu go.mod hinzu, z. B. go get github.com/google/uuid. go mod tidy räumt nicht mehr benutzte Einträge auf.
  • Tests: Dateien mit der Endung _test.go enthalten Tests; go test ./... führt alle aus.
  • Andere Systeme: Go übersetzt ohne weitere Werkzeuge auch für andere Plattformen, z. B. GOOS=windows GOARCH=amd64 go build für Windows.
  • Editor: Visual Studio Code mit der Erweiterung „Go“ bietet Autovervollständigung über das Werkzeug gopls, das die Erweiterung auf Nachfrage selbst installiert. In Neovim lässt sich gopls ebenfalls einbinden.

Deinstallieren

1. Übungsprojekt entfernen

Löscht den Projektordner.

rm -rf ~/hallo-go

2. Heruntergeladene Bibliotheken löschen

Go legt Bibliotheken schreibgeschützt ab, damit sie nicht versehentlich verändert werden. Deshalb nicht mit rm, sondern mit diesem Befehl entfernen. Er muss vor Schritt 4 laufen, solange go noch installiert ist.

go clean -modcache

3. Zwischenspeicher und Go-Ordner löschen

Entfernt die Übersetzungszwischenstände und den nun leeren Ordner ~/go samt ~/go/bin.

rm -rf ~/go ~/.cache/go-build

4. Go entfernen

Entfernt das Paket golang-go.

sudo apt purge golang-go

5. Nicht mehr benötigte Abhängigkeiten entfernen

Räumt die eigentlichen Versionspakete (z. B. golang-1.26-go) auf, die mit golang-go installiert wurden.

sudo apt autoremove

6. Suchpfad-Eintrag entfernen

Löscht die Zeile aus Schritt 3 der Installation wieder aus ~/.bashrc.

nano ~/.bashrc

Suche mit Strg+W nach go/bin und drücke Enter. Lösche die Zeile export PATH="$PATH:$HOME/go/bin" mit Strg+K. Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Prüfen: Die Meldung lautet go: Befehl nicht gefunden bzw. command not found.

go version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Rust

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Rust ist eine Programmiersprache für schnelle und zugleich sichere Programme: Der Compiler verhindert schon beim Übersetzen typische Fehler wie ungültige Speicherzugriffe oder gleichzeitige Schreibzugriffe mehrerer Threads. Rust wird für Systemprogramme, Kommandozeilenwerkzeuge, Webdienste und WebAssembly eingesetzt.

Vorbemerkungen

  • Compiler und Cargo: Der Compiler heißt rustc. Im Alltag ruft man ihn aber fast nie selbst auf, sondern nutzt Cargo: Cargo legt Projekte an, lädt Bibliotheken (in Rust Crates genannt) von crates.io, übersetzt, testet und erstellt Dokumentation.
  • Installation über apt: Ubuntu 26.04 liefert Rust 1.93. Dazu gibt es passende Pakete für die Werkzeuge Clippy (findet verbesserungswürdigen Code) und rustfmt (formatiert Quelltext einheitlich). Für die Anleitung Axum und Actix-web genügt diese Version.
  • Alternative rustup: Rust erscheint alle sechs Wochen in einer neuen Version. Wer immer die neueste Version oder mehrere Versionen nebeneinander braucht, installiert Rust mit dem Werkzeug rustup (ebenfalls als apt-Paket vorhanden) in den eigenen Benutzerordner. Beide Wege sollte man nicht mischen; siehe Schritt 4.
  • Ordner ~/.cargo: Hier speichert Cargo heruntergeladene Crates und mit cargo install installierte Programme (~/.cargo/bin).

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Rust und Cargo installieren

Installiert Compiler und Cargo. Den C-Compiler gcc, den Rust zum Zusammenfügen (Linken) der Programme braucht, installiert apt automatisch mit.

sudo apt install rustc cargo

Prüfen: Die Ausgabe nennt die Version, z. B. rustc 1.93.1.

rustc --version

3. Clippy und rustfmt installieren

Installiert die beiden Werkzeuge, die danach als cargo clippy und cargo fmt aufgerufen werden.

sudo apt install rust-clippy rustfmt

Prüfen:

cargo clippy --version

4. Prüfen, welches Rust gefunden wird

Ist Rust zusätzlich über rustup installiert, liegen dessen Befehle in ~/.cargo/bin und haben meist Vorrang. Dieser Befehl zeigt, welcher cargo tatsächlich benutzt wird.

which cargo

Prüfen: /usr/bin/cargo bedeutet: die Version aus apt. ~/.cargo/bin/cargo bedeutet: die Version aus rustup. Beides funktioniert, die Versionsnummern unterscheiden sich dann aber von denen in dieser Anleitung.

Erstes Programm

5. Projekt anlegen

cargo new erzeugt den Ordner ~/hallo-rust mit der Projektbeschreibung Cargo.toml, dem Quelltext src/main.rs und einem leeren Git-Repository.

cargo new ~/hallo-rust

6. In den Projektordner wechseln

Cargo-Befehle arbeiten immer mit dem Projekt im aktuellen Ordner.

cd ~/hallo-rust

7. Quelltext ersetzen

Überschreibt das vorgegebene „Hello, world!“. Das Programm enthält eine eigene Funktion lange_namen und einen Test dafür, der mit #[test] markiert ist.

nano src/main.rs

Die Datei hat schon Inhalt aus der Vorlage, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

fn lange_namen<'a>(namen: &[&'a str], mindestens: usize) -> Vec<&'a str> {
    namen.iter().copied().filter(|n| n.len() >= mindestens).collect()
}

fn main() {
    let sprachen = ["Go", "Rust", "PHP", "Kotlin", "TypeScript"];

    for (i, s) in sprachen.iter().enumerate() {
        println!("{}. {s}", i + 1);
    }
    println!("Lange Namen: {}", lange_namen(&sprachen, 4).join(", "));
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn filtert_kurze_namen() {
        assert_eq!(lange_namen(&["Go", "Rust", "C"], 3), vec!["Rust"]);
    }
}

8. Programm übersetzen und starten

cargo run übersetzt das Projekt in den Ordner target/debug und startet es.

cargo run

Prüfen: Nach der Meldung Running target/debug/hallo-rust erscheint:

1. Go
2. Rust
3. PHP
4. Kotlin
5. TypeScript
Lange Namen: Rust, Kotlin, TypeScript

9. Tests ausführen

Übersetzt das Projekt mit den Tests und führt sie aus.

cargo test

Prüfen: Die Ausgabe enthält test tests::filtert_kurze_namen ... ok und test result: ok. 1 passed.

10. Code prüfen lassen

Clippy kennt Hunderte Regeln für besseren Rust-Code und schlägt konkrete Änderungen vor.

cargo clippy

Prüfen: Es erscheinen keine Warnungen (warning: …).

11. Fertiges Programm erstellen

Übersetzt mit allen Optimierungen. Das Ergebnis ist deutlich schneller als die Debug-Fassung und liegt in target/release.

cargo build --release

Prüfen:

./target/release/hallo-rust

Wie geht es weiter?

  • Crates hinzufügen: cargo add <Name> trägt eine Bibliothek in Cargo.toml ein, z. B. cargo add rand. Beim nächsten Übersetzen lädt Cargo sie herunter.
  • Dokumentation offline: cargo doc --open erzeugt die Dokumentation des eigenen Projekts und aller benutzten Crates und öffnet sie im Browser.
  • Lernmaterial: Das kostenlose Buch „The Rust Programming Language“ gibt es online auf rust-lang.org; es ist selbst mit mdBook erstellt.
  • Editor: Visual Studio Code mit der Erweiterung „rust-analyzer“. Das gleichnamige Werkzeug gibt es auch für Neovim.
  • Webanwendungen: Die Anleitung Axum und Actix-web baut darauf auf.

Deinstallieren

1. Übungsprojekt entfernen

Löscht den Projektordner samt target mit allen übersetzten Dateien.

rm -rf ~/hallo-rust

2. Rust-Pakete entfernen

Nur ausführen, wenn Rust auch nicht mehr für andere Projekte gebraucht wird.

sudo apt purge rustc cargo rust-clippy rustfmt

3. Nicht mehr benötigte Abhängigkeiten entfernen

Räumt Bibliotheken auf, die nur für Rust installiert wurden.

sudo apt autoremove

4. Zwischenspeicher von Cargo löschen

Entfernt heruntergeladene Crates. Gelöscht werden bewusst nur diese beiden Unterordner und nicht ganz ~/.cargo: In ~/.cargo/bin liegen Programme, die mit cargo install oder rustup installiert wurden, auf diesem Rechner z. B. mdbook.

rm -rf ~/.cargo/registry ~/.cargo/git

Prüfen: Der Befehl meldet rustc: Befehl nicht gefunden bzw. command not found. Erscheint stattdessen eine Version, stammt sie aus rustup in ~/.cargo/bin.

rustc --version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

PHP

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

PHP ist eine weit verbreitete Skriptsprache für die Webentwicklung. Auf dem Entwicklungsrechner dient sie dazu, serverseitige Skripte auszuführen und dynamische Webanwendungen lokal zu testen.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Paketversionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. PHP (CLI) installieren

Installiert den PHP-Kommandozeileninterpreter. Damit kannst du PHP-Skripte direkt im Terminal ausführen oder den integrierten Webserver starten.

sudo apt install php-cli

Prüfen: Die Versionsnummer wird angezeigt (unter Ubuntu 26.04 ist dies PHP 8.5).

php -v

3. PHP-FPM für Webserver installieren

Installiert PHP-FPM (FastCGI Process Manager). Dieser Dienst verarbeitet PHP-Anfragen im Hintergrund für Webserver wie nginx.

sudo apt install php-fpm

4. Prüfen, ob der PHP-FPM-Dienst läuft

PHP-FPM läuft als Hintergrunddienst (systemd). Hier siehst du, ob er aktiv ist.

systemctl status php8.5-fpm

Prüfen: In der Ausgabe steht Active: active (running). Mit der Taste q verlässt du die Anzeige.

5. Häufig benötigte Erweiterungen installieren

Die meisten modernen PHP-Projekte und Frameworks (wie Laravel oder Symfony) benötigen zusätzliche Module für Netzwerkabfragen, Textverarbeitung, XML, ZIP-Archive und SQLite-Datenbanken.

sudo apt install php-curl php-mbstring php-xml php-zip php-sqlite3

Prüfen: Listet alle aktiven PHP-Module auf.

php -m

PHP testen

6. Skript auf der Kommandozeile ausführen

Prüft mit einem kurzen Einzeiler, ob der PHP-Interpreter Code fehlerfrei ausführt.

php -r 'echo "PHP funktioniert!\n";'

Prüfen: Im Terminal wird PHP funktioniert! ausgegeben.

7. Integrierten Entwicklungsserver testen

PHP bringt einen schlanken Webserver mit. Damit kannst du Webseiten sofort lokal im Browser testen, ohne einen externen Server konfigurieren zu müssen.

php -S 127.0.0.1:8000

Prüfen: Im Browser unter http://localhost:8000 ist der Server erreichbar. Zum Beenden des Servers drückst du im Terminal Strg + C.

Erstes Programm

8. Arbeitsordner anlegen

Ein eigener Ordner für die Übungsdateien.

mkdir -p ~/php-uebung

9. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/php-uebung

10. Skript anlegen

Legt hallo.php an. Jede PHP-Datei beginnt mit <?php. declare(strict_types=1) sorgt dafür, dass PHP die angegebenen Typen (hier string) streng prüft, statt Werte stillschweigend umzuwandeln. Variablen beginnen in PHP immer mit $.

nano hallo.php

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<?php

declare(strict_types=1);

function begruessung(string $name): string
{
    return "Hallo $name!";
}

$sprachen = ['Go', 'Rust', 'PHP', 'Kotlin', 'TypeScript'];

echo begruessung('Ubuntu'), PHP_EOL;
echo 'PHP-Version: ', PHP_VERSION, PHP_EOL;

foreach ($sprachen as $i => $sprache) {
    printf("%d. %s\n", $i + 1, $sprache);
}

11. Skript ausführen

Der Interpreter php liest die Datei und führt sie sofort aus.

php hallo.php

Prüfen: Die Ausgabe beginnt mit Hallo Ubuntu! und PHP-Version: 8.5.…, danach folgen fünf nummerierte Zeilen.

12. Syntax prüfen

php -l untersucht eine Datei auf Syntaxfehler, ohne sie auszuführen. Praktisch vor dem Hochladen auf einen Server.

php -l hallo.php

Prüfen: Die Meldung lautet No syntax errors detected in hallo.php.

Bibliotheken mit Composer

Composer ist der Paketmanager für PHP. Er lädt Bibliotheken aus dem Verzeichnis Packagist in den Projektordner vendor und erzeugt eine Datei, die sie automatisch einbindet.

13. Composer installieren

Installiert Composer aus den Ubuntu-Paketquellen.

sudo apt install composer

Prüfen: Die Ausgabe nennt die Version, z. B. Composer version 2.9.5.

composer --version

14. Bibliothek hinzufügen

Installiert als Beispiel ramsey/uuid, eine Bibliothek zum Erzeugen eindeutiger Kennungen. Composer legt dabei composer.json (gewünschte Pakete), composer.lock (genau installierte Versionen) und den Ordner vendor an.

composer require ramsey/uuid

Prüfen: Die Ausgabe enthält Using version ^4.… for ramsey/uuid.

15. Skript mit der Bibliothek anlegen

Legt uuid.php an. Die Zeile mit vendor/autoload.php bindet alle über Composer installierten Bibliotheken ein; use macht die Klasse unter ihrem kurzen Namen verfügbar.

nano uuid.php

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use Ramsey\Uuid\Uuid;

$id = Uuid::uuid4();
echo "Neue ID: $id", PHP_EOL;
echo 'Version: ', $id->getFields()->getVersion(), PHP_EOL;

16. Skript ausführen

php uuid.php

Prüfen: Es erscheint eine zufällige Kennung wie Neue ID: d227883a-79b7-4e80-825f-e60098dc7e3e und darunter Version: 4. Bei jedem Aufruf ist die Kennung eine andere.

Zusammenspiel mit nginx (optional)

Wenn du nginx nach der nginx-Anleitung eingerichtet hast, kannst du PHP über PHP-FPM anbinden.

17. PHP in der nginx-Konfiguration aktivieren

Ergänzt in der bestehenden Konfiguration /etc/nginx/sites-available/dev die Startdatei index.php und den location ~ \.php$-Block für PHP-FPM.

sudo nano /etc/nginx/sites-available/dev

Die Datei hat schon Inhalt, der vollständig ersetzt wird. Lösche ihn zuerst: Alt+\ springt an den Anfang, Alt+A beginnt eine Markierung, Alt+/ springt ans Ende, Strg+K schneidet alles Markierte aus. Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

server {
    listen 127.0.0.1:8081;
    server_name localhost;

    root /var/www/dev;
    index index.php index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php-fpm.sock;
    }
}

18. nginx-Konfiguration testen

Stellt sicher, dass die neue Konfiguration fehlerfrei ist.

sudo nginx -t

Prüfen: Die Ausgabe endet mit test is successful.

19. nginx neu laden

Aktiviert die geänderte Konfiguration im Webserver.

sudo systemctl reload nginx

20. PHP-Testdatei anlegen

Erstellt eine PHP-Informationsseite im Entwicklungsordner /var/www/dev.

nano /var/www/dev/info.php

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

<?php phpinfo(); ?>

21. Testseite aufrufen

Fragt die PHP-Testseite über nginx ab.

curl -s http://localhost:8081/info.php | head -n 10

Prüfen: Im Browser siehst du unter http://localhost:8081/info.php die ausführliche PHP-Konfiguration.

Optional: Autostart ausschalten

Auf einem Entwicklungsrechner muss PHP-FPM nicht zwingend bei jedem Rechnerstart im Hintergrund laufen.

Autostart ausschalten:

sudo systemctl disable php8.5-fpm

Bei Bedarf von Hand starten und stoppen:

sudo systemctl start php8.5-fpm
sudo systemctl stop php8.5-fpm

Deinstallieren

1. Testdatei entfernen

Löscht die PHP-Testdatei aus dem Entwicklungsverzeichnis, falls sie angelegt wurde.

rm -f /var/www/dev/info.php

2. Übungsordner entfernen

Löscht die Beispielskripte und den Ordner vendor.

rm -rf ~/php-uebung

3. Composer entfernen

Entfernt Composer sowie seinen Zwischenspeicher und seine Einstellungen im Benutzerordner.

sudo apt purge composer
rm -rf ~/.cache/composer ~/.config/composer

4. PHP und Erweiterungen entfernen

purge entfernt die Pakete sowie deren Konfigurationsdateien unter /etc/php.

sudo apt purge "php*"

5. Nicht mehr benötigte Pakete entfernen

Entfernt Abhängigkeiten und Bibliotheken, die nur für PHP installiert wurden.

sudo apt autoremove

Prüfen: Der PHP-Befehl ist nicht mehr vorhanden.

php -v

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Kotlin

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Kotlin ist eine moderne Programmiersprache von JetBrains, die auf der Java-Plattform läuft und mit Java-Code direkt zusammenarbeitet. Sie ist die bevorzugte Sprache für Android-Apps und wird zunehmend auch für Serveranwendungen, z. B. mit Spring Boot, eingesetzt.

Vorbemerkungen

  • Warum nicht apt? Ubuntu 26.04 enthält zwar ein Paket kotlin, aber in der sehr alten Version 1.3 von 2019. Viele heutige Sprachmerkmale und Bibliotheken funktionieren damit nicht. Diese Anleitung installiert deshalb den Compiler als Snap, die JetBrains selbst veröffentlicht und aktuell hält (derzeit Kotlin 2.4).
  • Java wird gebraucht: Kotlin übersetzt Programme in Bytecode für die Java Virtual Machine. Zum Übersetzen und Ausführen braucht man deshalb ein JDK. Das kommt wie in der Anleitung Java aus apt.
  • Kommandozeile oder Gradle: Für einzelne Dateien und zum Lernen reicht der Kommandozeilen-Compiler kotlinc. Größere Projekte baut man mit Gradle, das meist von der Entwicklungsumgebung mitgebracht wird. Auch das Gradle-Paket von Ubuntu ist stark veraltet und wird hier nicht verwendet.
  • Entwicklungsumgebung: IntelliJ IDEA stammt ebenfalls von JetBrains und unterstützt Kotlin ohne Erweiterung am besten. Neue Kotlin-Projekte legt man dort mit dem Assistenten an; er richtet Gradle automatisch ein.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. JDK installieren

Installiert OpenJDK 25, das Kotlin zum Übersetzen und Ausführen braucht. Ist es aus der Anleitung Java schon vorhanden, meldet apt das nur.

sudo apt install default-jdk

Prüfen: Die Ausgabe beginnt mit openjdk version "25…".

java -version

3. Kotlin-Compiler als Snap installieren

Installiert die Befehle kotlinc (Compiler) und kotlin (startet Programme und Skripte). Der Schalter --classic ist nötig, weil der Compiler auf das JDK und auf Dateien außerhalb der Snap-Umgebung zugreifen muss.

sudo snap install kotlin --classic

Prüfen: Die Ausgabe nennt die Version, z. B. info: kotlinc-jvm 2.4.20 (JRE 25…).

kotlinc -version

Erstes Programm

4. Arbeitsordner anlegen

Ein eigener Ordner für die Übungsdateien.

mkdir -p ~/kotlin-uebung

5. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/kotlin-uebung

6. Quelltext anlegen

Legt hallo.kt an. Eine data class ist eine Klasse, die nur Daten hält; Kotlin erzeugt dafür Vergleich, Textausgabe und Kopierfunktion automatisch. sortedBy und maxBy arbeiten mit einer kurzen Funktion in geschweiften Klammern, in der it für das jeweilige Element steht.

nano hallo.kt

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

data class Sprache(val name: String, val jahr: Int)

fun main() {
    val sprachen = listOf(
        Sprache("Java", 1995),
        Sprache("Kotlin", 2016),
        Sprache("Go", 2009),
    )

    for (s in sprachen.sortedBy { it.jahr }) {
        println("${s.name} (${s.jahr})")
    }

    val neueste = sprachen.maxBy { it.jahr }
    println("Am neuesten: ${neueste.name}")
}

7. Programm übersetzen

Übersetzt den Quelltext in die Datei hallo.jar. Der Schalter -include-runtime packt die Kotlin-Standardbibliothek mit hinein, damit das Programm später mit dem gewöhnlichen Befehl java läuft. Das Übersetzen dauert einige Sekunden.

kotlinc hallo.kt -include-runtime -d hallo.jar

Prüfen: Im Ordner liegt jetzt hallo.jar.

ls -l hallo.jar

8. Programm starten

Startet das Programm mit der Java-Laufzeitumgebung. Kotlin selbst muss auf dem Zielrechner nicht installiert sein.

java -jar hallo.jar

Prüfen: Die Sprachen erscheinen nach Erscheinungsjahr sortiert:

Java (1995)
Go (2009)
Kotlin (2016)
Am neuesten: Kotlin

Kotlin-Skripte

9. Skript anlegen

Dateien mit der Endung .main.kts sind Skripte: Die Anweisungen stehen direkt in der Datei, eine Funktion main ist nicht nötig. Das eignet sich für kleine Hilfsprogramme.

nano rechnen.main.kts

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

val zahlen = (1..10).toList()
println("Summe: ${zahlen.sum()}")
println("Gerade Zahlen: ${zahlen.filter { it % 2 == 0 }}")

10. Skript ausführen

Der Befehl kotlin übersetzt das Skript im Hintergrund und führt es sofort aus.

kotlin rechnen.main.kts

Prüfen: Die Ausgabe lautet:

Summe: 55
Gerade Zahlen: [2, 4, 6, 8, 10]

Wie geht es weiter?

  • Projekte mit Gradle: In IntelliJ IDEA über File → New → Project → Kotlin ein Projekt mit „Gradle“ als Build-System anlegen. Das Projekt enthält dann ein Startskript ./gradlew, das die passende Gradle-Version selbst herunterlädt; ./gradlew run startet das Programm.
  • Interaktiv ausprobieren: kotlinc ohne weitere Angaben öffnet eine Eingabezeile für einzelne Anweisungen. Beenden mit :quit.
  • Aktualisierungen: Snaps werden automatisch im Hintergrund aktualisiert. Wer bei einer Hauptversion bleiben möchte, wechselt den Kanal, z. B. sudo snap refresh kotlin --channel=2.4/stable.
  • Serveranwendungen: Spring Boot unterstützt Kotlin als gleichwertige Alternative zu Java.

Deinstallieren

1. Übungsordner entfernen

Löscht die Beispieldateien.

rm -rf ~/kotlin-uebung

2. Kotlin-Snap entfernen

Entfernt den Compiler. --purge löscht dabei auch die automatische Sicherung, die snap sonst beim Entfernen anlegt.

sudo snap remove --purge kotlin

3. Optional: JDK entfernen

Nur ausführen, wenn Java auch nicht mehr gebraucht wird, z. B. für die Anleitungen Java oder Spring Boot. Die genauen Schritte stehen im Abschnitt „Deinstallieren“ der Anleitung Java.

sudo apt purge default-jdk default-jdk-headless openjdk-25-jdk openjdk-25-jdk-headless
sudo apt autoremove

Prüfen: Die Meldung lautet kotlinc: Befehl nicht gefunden bzw. command not found.

kotlinc -version

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

TypeScript

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

TypeScript ist JavaScript mit Typangaben: Man legt fest, welche Art von Werten Variablen und Funktionen erwarten, und der Compiler meldet Fehler, bevor das Programm überhaupt läuft. Heraus kommt gewöhnliches JavaScript, das in jedem Browser und in Node.js läuft.

Vorbemerkungen

  • Grundlage: TypeScript baut auf JavaScript auf und braucht Node.js mit npm. Die Anleitung installiert beides aus den Ubuntu-Paketquellen (Node.js 22).
  • Pro Projekt über npm: Ubuntu enthält zwar das Paket node-typescript, aber nur in Version 5.2 von 2023. Üblich und empfohlen ist, TypeScript pro Projekt mit npm zu installieren. Dann legt jedes Projekt seine TypeScript-Version selbst fest, und alle Beteiligten übersetzen mit derselben. Aktuell ist TypeScript 7, dessen Compiler für deutlich kürzere Übersetzungszeiten neu geschrieben wurde.
  • Compiler tsc: Er prüft die Typen und erzeugt aus .ts-Dateien .js-Dateien. Die Einstellungen stehen in der Datei tsconfig.json.
  • Direkt ausführen: Node.js kann .ts-Dateien auch ohne Übersetzen starten, indem es die Typangaben einfach entfernt. Die Typen prüft dabei aber niemand; dafür bleibt tsc zuständig.

Installation

1. Paketlisten aktualisieren

Damit apt die aktuellen Versionen aus den Ubuntu-Paketquellen kennt.

sudo apt update

2. Node.js und npm installieren

Installiert die Laufzeitumgebung und den Paketmanager. Sind sie aus einer anderen Anleitung schon vorhanden, meldet apt das nur.

sudo apt install nodejs npm

Prüfen: Die Ausgabe beginnt mit v22..

node --version

Erstes Projekt

3. Projektordner anlegen

Ein eigener Ordner für das Übungsprojekt, mit Unterordner src für den Quelltext.

mkdir -p ~/hallo-ts/src

4. In den Ordner wechseln

Alle folgenden Befehle beziehen sich auf diesen Ordner.

cd ~/hallo-ts

5. npm-Projekt anlegen

Erzeugt package.json und stellt das Projekt auf ES-Module (import … from …) um.

npm init -y && npm pkg set type=module

6. TypeScript installieren

Installiert den Compiler und die Typbeschreibungen für Node.js (z. B. für process) als Entwicklungsabhängigkeit (--save-dev). Sie werden nur beim Entwickeln gebraucht, nicht im fertigen Programm.

npm install --save-dev typescript @types/node

Prüfen: npx startet den Compiler aus node_modules des Projekts. Die Ausgabe lautet z. B. Version 7.0.2.

npx tsc --version

7. Compiler-Einstellungen anlegen

Legt tsconfig.json an. Die wichtigsten Angaben:

  • rootDir / outDir – TypeScript-Quelltext liegt in src, das erzeugte JavaScript landet in dist.
  • module: nodenext – Module so behandeln, wie Node.js es tut.
  • strict – alle strengen Prüfungen einschalten; für neue Projekte dringend empfohlen.
nano tsconfig.json

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

{
  "compilerOptions": {
    "target": "es2023",
    "module": "nodenext",
    "rootDir": "src",
    "outDir": "dist",
    "strict": true,
    "types": ["node"]
  }
}

8. Quelltext anlegen

Legt src/hallo.ts an. Das interface beschreibt, wie ein Eintrag aussehen muss; die Funktion beschreibe nimmt nur solche Einträge an und gibt garantiert einen Text zurück.

nano src/hallo.ts

Füge diesen Inhalt ein (im Terminal mit Strg+Umschalt+V), speichere mit Strg+O und Enter und beende nano mit Strg+X:

interface Sprache {
  name: string;
  jahr: number;
}

const sprachen: Sprache[] = [
  { name: 'Go', jahr: 2009 },
  { name: 'Rust', jahr: 2015 },
  { name: 'TypeScript', jahr: 2012 },
];

function beschreibe(s: Sprache): string {
  return `${s.name} erschien ${s.jahr}.`;
}

for (const s of sprachen) {
  console.log(beschreibe(s));
}
console.log(`Node.js ${process.version}`);

9. Übersetzen

tsc liest tsconfig.json, prüft alle Typen und schreibt das Ergebnis nach dist.

npx tsc

Prüfen: Der Befehl gibt nichts aus, und die Datei dist/hallo.js ist entstanden.

ls dist

10. Programm starten

Führt das erzeugte JavaScript mit Node.js aus.

node dist/hallo.js

Prüfen: Die Ausgabe lautet:

Go erschien 2009.
Rust erschien 2015.
TypeScript erschien 2012.
Node.js v22.…

11. Typprüfung ausprobieren

Ändert absichtlich die Jahreszahl von Rust in einen Text ('2015' statt 2015) und übersetzt erneut.

nano src/hallo.ts

Suche mit Strg+W nach 2015 und drücke Enter. Setze die Zahl in Anführungszeichen. Ändere die gefundene Zeile so, dass sie lautet:

  { name: 'Rust', jahr: '2015' },

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Dann erneut übersetzen:

npx tsc

Prüfen: Der Compiler bricht ab mit src/hallo.ts(8,19): error TS2322: Type 'string' is not assignable to type 'number'. Genau solche Fehler würden in reinem JavaScript erst beim Ausführen – oder gar nicht – auffallen.

12. Fehler wieder beheben

Stellt die Zahl wieder her.

nano src/hallo.ts

Suche mit Strg+W nach 2015 und drücke Enter. Entferne die Anführungszeichen wieder. Ändere die gefundene Zeile so, dass sie lautet:

  { name: 'Rust', jahr: 2015 },

Speichere mit Strg+O und Enter und beende nano mit Strg+X.

Dann erneut übersetzen:

npx tsc

Prüfen: Der Befehl läuft wieder ohne Meldung durch.

13. Optional: Direkt ausführen

Node.js entfernt die Typangaben und startet den Quelltext ohne dist. Je nach Node.js-Version erscheint dazu ein Hinweis ExperimentalWarning: Type Stripping…, der sich ignorieren lässt.

node src/hallo.ts

Wie geht es weiter?

  • Laufend prüfen: npx tsc --watch übersetzt bei jedem Speichern neu und zeigt Fehler sofort an.
  • Skripte in package.json: Mit npm pkg set scripts.build=tsc genügt künftig npm run build.
  • Webentwicklung: Werkzeuge wie Vite, VitePress, Astro Starlight und Docusaurus verstehen TypeScript ohne weitere Einrichtung. Auch Express.js lässt sich mit TypeScript nutzen.
  • Editor: Visual Studio Code ist selbst in TypeScript geschrieben und zeigt Typfehler schon beim Tippen an.

Deinstallieren

1. Übungsprojekt entfernen

Löscht das Projekt samt node_modules. Weil TypeScript nur in diesem Projekt installiert war, ist es damit vollständig entfernt.

rm -rf ~/hallo-ts

2. Optional: Node.js und npm entfernen

Nur ausführen, wenn kein anderes Programm Node.js braucht (siehe Anleitung JavaScript).

sudo apt purge nodejs npm
sudo apt autoremove

Prüfen: Der Projektordner existiert nicht mehr (Datei oder Verzeichnis nicht gefunden).

ls ~/hallo-ts

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Impressum

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Angaben gemäß § 5 DDG (Digitale-Dienste-Gesetz)

  • 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

Haftungsausschluss:

Haftung für Inhalte

Die Inhalte unserer Seiten wurden mit größter Sorgfalt erstellt. Für die Richtigkeit, Vollständigkeit und Aktualität der Inhalte können wir jedoch keine Gewähr übernehmen. Als Diensteanbieter sind wir gemäß § 7 Abs. 1 DDG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 DDG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.

Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.

Urheberrecht und Lizenzierung

Die durch den Betreiber erstellten didaktischen Inhalte, Texte und Projektvorschläge auf diesen Seiten sind lizenziert unter einer Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0).

Ausgenommen von dieser freien Lizenz sind die rechtlichen Pflichtangaben (Impressum, Datenschutzerklärung) sowie etwaige geschützte Marken, Namen oder Komponenten Dritter.

Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.

Datenschutz

Ausführliche Informationen zur Erhebung und zum Schutz personenbezogener Daten finden Sie in unserer separaten Datenschutzerklärung.

Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten Kontaktdaten durch Dritte zur Übersendung von nicht ausdrücklich angeforderter Werbung und Informationsmaterialien wird hiermit ausdrücklich widersprochen. Die Betreiber der Seiten behalten sich ausdrücklich rechtliche Schritte im Falle der unverlangten Zusendung von Werbeinformationen, etwa durch Spam-Mails, vor.


Quelle für die Abschnitte „Haftung für Inhalte“, „Haftung für Links“, den Hinweis auf Urheberrechte Dritter und den Widerspruch gegen Werbung: e-recht24.de

Stand: September 2026

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Datenschutz

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

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

Ihre Betroffenenrechte

Unter den oben angegebenen Kontaktdaten der verantwortlichen Stelle 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 zuständige Aufsichtsbehörde des Bundeslands Ihres Wohnsitzes oder an die für uns als verantwortliche Stelle zuständige Behörde. Für uns ist das Unabhängige Landeszentrum für Datenschutz Schleswig-Holstein (ULD) zuständig.

Eine Liste der Aufsichtsbehörden (für den nichtöffentlichen Bereich) mit Anschrift finden Sie unter: https://www.bfdi.bund.de/DE/Infothek/Anschriften_Links/anschriften_links-node.html.

Hosting bei GitHub Pages

Diese Website wird bei GitHub Pages gehostet. Anbieter ist die GitHub Inc., 88 Colin P. Kelly Jr. Street, San Francisco, CA 94107, USA (nachfolgend „GitHub“); für Nutzer aus der EU/EWR ist GitHub B.V., Prins Bernhardplein 200, 1097 JB Amsterdam, Niederlande, verantwortlich.

Beim Besuch dieser Website erfasst GitHub automatisch Informationen in sogenannten Server-Logfiles, die Ihr Browser übermittelt, u. a. IP-Adresse, Datum und Uhrzeit der Anfrage, Browsertyp und Betriebssystem. Nach eigenen Angaben speichert GitHub die IP-Adresse der Besucher von GitHub-Pages-Seiten zu Sicherheitszwecken. Wir selbst erhalten keinen Zugriff auf diese Logdaten und werten sie nicht aus.

Rechtsgrundlage ist Art. 6 Abs. 1 lit. f DSGVO. Unser berechtigtes Interesse liegt in der sicheren und zuverlässigen Bereitstellung dieses Angebots.

Die Verarbeitung durch GitHub kann auch in den USA erfolgen. GitHub hat sich dem EU-U.S. Data Privacy Framework (DPF) unterworfen, für das die Europäische Kommission am 10. Juli 2023 einen Angemessenheitsbeschluss erlassen hat. Weitere Informationen zum Datenschutz bei GitHub finden Sie unter: https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement.

Diese Seite wird über die eigene Domain installieren.wissen-ahrensburg.de bereitgestellt. Alle Dateien der Website, auch Schriften, Skripte und der Suchindex, werden von GitHub Pages ausgeliefert. Es findet keine Einbindung von Drittanbieter-CDNs, Google Fonts, Analyse- oder Tracking-Diensten statt.

Cookies und Speicherung im Browser

Diese Website setzt keine Cookies. Wenn Sie das Farbschema ändern oder die Seitenleiste ein- oder ausblenden, speichert Ihr Browser diese Einstellung lokal (Local Storage), damit sie beim nächsten Seitenaufruf erhalten bleibt. Diese Angaben verlassen Ihren Rechner nicht und werden nicht an uns oder Dritte übertragen. Die Speicherung ist für die von Ihnen gewünschte Funktion unbedingt erforderlich (§ 25 Abs. 2 Nr. 2 TDDDG). Sie können die gespeicherten Einstellungen jederzeit über die Einstellungen Ihres Browsers löschen.

Kontakt per E-Mail

Wenn Sie uns eine E-Mail schreiben, verwenden wir Ihre Angaben (z. B. E-Mail-Adresse, Name und Inhalt der Nachricht) ausschließlich, um Ihre Anfrage zu beantworten. Rechtsgrundlage ist Art. 6 Abs. 1 lit. f DSGVO; unser berechtigtes Interesse liegt in der Beantwortung Ihrer Anfrage. Die Daten werden gelöscht, sobald sie dafür nicht mehr erforderlich sind und keine gesetzlichen Aufbewahrungspflichten entgegenstehen.

Änderung unserer Datenschutzbestimmungen

Wir behalten uns vor, diese Datenschutzerklärung anzupassen, damit sie stets den aktuellen rechtlichen Anforderungen entspricht oder um Änderungen unserer Leistungen in der Datenschutzerklärung umzusetzen, z.B. bei der Einführung neuer Services. 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 oder wenden Sie sich direkt an die oben genannte verantwortliche Person:

  • E-Mail: thorstenkloehn@gmail.com

Die Datenschutzerklärung wurde in Teilen erstellt mit dem Muster der activeMind AG (Experten für Datenschutz und Informationssicherheit).

Stand: September 2026

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).

Open Knowledge (Freies Wissen): Alle Texte stehen unter der freien Lizenz Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0) und können frei gelesen, geteilt und weiterverarbeitet werden.

Autor: Thorsten · Installationsanleitungen für Ubuntu

Alle Anleitungen ohne Gewähr. Befehle mit sudo verändern das System – vorher lesen, dann ausführen.