# Anhang: Installation von Sourcehut Da ich im Internet keine vollständige Installationsanleitung für Sourcehut gefunden habe, beschreibe ich hier den vollständigen Installationsvorgang für meine Testinstanz. Ich habe Sourcehut wie vom Entwickler empfohlen auf einer Alpine-Linux-VM installiert. Die Sourcehut-Pakete werden auch für Arch und Debian (Sid) angeboten. Alle aufgelisteten Befehle müssen als Root-User ausgeführt werden, sofern es nicht anders beschrieben ist. ## Sourcehut-Repo Zuerst muss das Sourcehut-Repository zum Paketmanager des Systems hinzugefügt werden. Die URLs für verschiedene Distributionen sind in der Dokumentation des Projekts angegeben. ``` echo "https://mirror.sr.ht/alpine/v3.17/sr.ht" > /etc/apk/repositories wget -q -O /etc/apk/keys/alpine@sr.ht.rsa.pub https://mirror.sr.ht/alpine/alpine@sr.ht.rsa.pub apk update ``` ## Grundlegende Dienste Zu Beginn müssen die grundlegenden Dienste eingerichtet werden: die Postgres-Datenbank, Redis und ein Nginx-Webserver, der als Reverse Proxy zwischen dem Nutzer und den einzelnen Diensten steht. Beim Einrichten der Dienste ist zu beachten, dass Alpine Linux OpenRC anstelle des systemd-Init-Systems verwendet und alle neu installierten Dienste manuell aktiviert und gestartet werden müssen. ``` apk add postgresql redis nginx rc-service postgresql setup rc-update add postgresql rc-service postgresql start rc-update add nginx rc-update add redis rc-service nginx start rc-service redis start ``` Wenn Postgres läuft, kann man die Datenbanken und Nutzer für die einzelnen Dienste erstellen. ``` su postgres psql CREATE USER meta WITH PASSWORD '1234'; CREATE DATABASE "meta.sr.ht"; ALTER DATABASE "meta.sr.ht" OWNER TO meta; GRANT ALL PRIVILEGES ON DATABASE "meta.sr.ht" TO meta; CREATE USER hub WITH PASSWORD '1234'; CREATE DATABASE "hub.sr.ht"; ALTER DATABASE "hub.sr.ht" OWNER TO hub; GRANT ALL PRIVILEGES ON DATABASE "hub.sr.ht" TO hub; CREATE USER git WITH PASSWORD '1234'; CREATE DATABASE "git.sr.ht"; ALTER DATABASE "git.sr.ht" OWNER TO git; GRANT ALL PRIVILEGES ON DATABASE "git.sr.ht" TO git; CREATE USER man WITH PASSWORD '1234'; CREATE DATABASE "man.sr.ht"; ALTER DATABASE "man.sr.ht" OWNER TO man; GRANT ALL PRIVILEGES ON DATABASE "man.sr.ht" TO man; CREATE USER todo WITH PASSWORD '1234'; CREATE DATABASE "todo.sr.ht"; ALTER DATABASE "todo.sr.ht" OWNER TO todo; GRANT ALL PRIVILEGES ON DATABASE "todo.sr.ht" TO todo; CREATE USER lists WITH PASSWORD '1234'; CREATE DATABASE "lists.sr.ht"; ALTER DATABASE "lists.sr.ht" OWNER TO lists; GRANT ALL PRIVILEGES ON DATABASE "lists.sr.ht" TO lists; CREATE USER paste WITH PASSWORD '1234'; CREATE DATABASE "paste.sr.ht"; ALTER DATABASE "paste.sr.ht" OWNER TO paste; GRANT ALL PRIVILEGES ON DATABASE "paste.sr.ht" TO paste; CREATE USER builds WITH PASSWORD '1234'; CREATE DATABASE "builds.sr.ht"; ALTER DATABASE "builds.sr.ht" OWNER TO builds; GRANT ALL PRIVILEGES ON DATABASE "builds.sr.ht" TO builds; ``` Alle Sourcehut-Dienste werden über eine einzige Datei unter `/etc/sr.ht/config.ini` konfiguriert. Sourcehut stellte jedoch keine vollständige Beispielkonfiguration bereit, weswegen ich meine Konfiguration aus den einzelnen Repositories zusammenkopieren musste. - - - - - - - - [Beispielkonfiguration](./assets/sourcehut_setup/config.ini) Folgende Optionen müssen angepasst werden: - Die Domains/URLs der Webseiten (in meiner Beispielkonfiguration `*.codeforge.int`). - Datenbank-URLs/Passwörter (Option: `connection-string`) - GPG-Keys (ein GPG-Schlüsselpaar ohne Passwort erstellen und unter `mail/pgp-privkey`, `mail/pgp-pubkey` und `mail/pgp-key-id` angeben) - `service-key`, `network-key`, `webhooks/private-key` (siehe meta.sr.ht) - OAuth-Client-IDs/Secrets (siehe meta.sr.ht) Anschließend kann man Nginx so konfigurieren, dass Web-Anfragen an die einzelnen Dienste weitergeleitet werden können. Eine Nginx-Beispielkonfiguration findet sich in [diesem Repository](https://git.sr.ht/~sircmpwn/sr.ht-nginx/tree) auf Sourcehut. [Hier](./assets/sourcehut_setup/nginx/nginx_services.conf) befindet sich die angepasste Version (ohne HTTPS), die ich für meine Testinstallation verwendet habe. Noch ein Hinweis für Testinstallationen mit internen Domains: Die konfigurierten Domains/URL müssen auf der Maschine, auf der Sourcehut läuft, erreichbar sein. Eventuell müssen diese Domains also in die /etc/hosts-Datei eingetragen werden. Ansonsten funktioniert die OAuth-Authentifizierung sowie das CI-System nicht. ## Sourcehut-Dienste Jede einzelne Sourcehut-Anwendung (git.sr.ht, builds.sr.ht, todo.sr.ht, etc) besteht aus mehreren Diensten. Dazu zählen das Python-Webfrontend, ein in Go geschriebener API-Server und eventuell noch zusätzliche Dienste wie eine Task Queue. Die Einrichtung einer Sourcehut-Anwendung erfordert folgende Schritte 1. Installation des Pakets 2. Initialisierung der Datenbank mit dem Skript `-initdb` 3. Starten der Dienste Bei einigen Diensten sind noch zusätzliche Konfigurationsanpassungen notwendig. ### meta.sr.ht - Web-UI: Port 5000 - API: Port 5100 meta.sr.ht ist der Dienst zur Nutzerverwaltung und Authentisierung und muss deswegen zuerst installiert werden. ``` # Paket installieren apk add meta.sr.ht # Datenbank initialisieren metasrht-initdb # Schlüssel erzeugen und in die Konfigurationsdatei eintragen # [sr.ht] > service-key srht-keygen service # [sr.ht] > network-key srht-keygen network # [webhooks] > private-key srht-keygen webhook # Dienste starten rc-update add meta.sr.ht rc-update add meta.sr.ht-api rc-update add meta.sr.ht-webhooks rc-service meta.sr.ht start rc-service meta.sr.ht-api start rc-service meta.sr.ht-webhooks start # Admin-Benutzer erstellen metasrht-manageuser -t admin -e thetadev@example.com thetadev # Cronjob hinzufügen crontab -e 0 0 * * * metasrht-daily ``` Die einzelnen Sourcehut-Dienste verwenden OAuth zur Authentifizierung der Nutzer. Jeder Dienst muss hierfür über eine eigene Client-Konfiguration verfügen. Diese lässt sich über das (Legacy) OAuth-Dashboard unter `meta./oauth` erstellen. ![OAuth-Setup](./assets/sourcehut/oauth.png) Als _Base Redirect URI_ trägt man die URL des Dienstes mit dem Pfad `oauth/callback` ein. Beispiel: `https://git.codeforge.int/oauth/callback`. ![OAuth-Registrierung](./assets/sourcehut/oauth_new_client.png) Die Client-ID und das Client-Secret, das auf der nächsten Seite angezeigt wird, können nun in die Konfigurationsdatei unter `[.sr.ht]/oauth-client-id` und `[.sr.ht]/oauth-client-secret` eingetragen werden. Standardmäßig verlangt Sourcehut nach einer manuellen Einwilligung für die Nutzung eines OAuth-Diensts. Um die internen Sourcehut-Dienste als vertrauenswürdig zu markieren und den Einwilligungsbildschirm für neue Nutzer zu deaktivieren, muss man eine manuelle Änderung an der Datenbank vornehmen und das Feld `preauthorized` für die entsprechenden OAuth-Clients auf `true` setzen. ``` su postgres psql \c "meta.sr.ht" UPDATE oauthclient SET preauthorized=true; ``` ### hub.sr.ht hub.sr.ht fungiert als Startseite für Sourcehut. Hier kann man Projekte erstellen, suchen und aufrufen. - Web-UI: Port 5014 - API: Port 5114 ``` # hub.src.ht (Port: 5014, API-Port: 5114) apk add hub.sr.ht hubsrht-initdb rc-update add hub.sr.ht rc-update add hub.sr.ht-api rc-service hub.sr.ht-api start rc-service hub.sr.ht start ``` ### git.sr.ht git.sr.ht ist der eigentliche Git-Hosting-Dienst. Sourcehut bietet auch einen Dienst für das Versionskontrollsystem Mercurial an, diesen habe ich jedoch nicht getestet. - Web-UI: Port 5001 - API: Port 5101 ``` # Abhängigkeiten für git-http server installieren apk add git-sr.ht fcgiwrap git-daemon gitsrht-initdb ``` Diese Zeilen müssen zur `/etc/ssh/sshd_config` hinzugrfügt werden. Dadurch kann der SSH-Server Nutzer anhand der auf Sourcehut hinterlegten SSH-Zugangsdaten authentifizieren. ``` AuthorizedKeysCommand=/usr/bin/gitsrht-dispatch "%u" "%h" "%t" "%k" AuthorizedKeysCommandUser=root PermitUserEnvironment SRHT_* ``` Da SSH den Login von Nutzern mit nicht gesetztem Passwort verbietet, muss der Account `git` mit einem beliebigen Passwort versehen werden. Anschließend muss noch eine Logdatei für das Skript `gitsrht-shell`, dass bei einer SSH-Verbindung aufgerufen wird, erstellt werden. ``` touch /var/log/gitsrht-shell chown git:git /var/log/gitsrht-shell ``` Nachdem alles konfiguriert wurde, kann man den Dienst starten und das Skript `gitsrht-periodic` in den crontab eintragen. ``` rc-update add fcgiwrap rc-update add git.sr.ht rc-update add git.sr.ht-api rc-update add git.sr.ht-webhooks rc-service fcgiwrap start rc-service git.sr.ht-webhooks start rc-service git.sr.ht-api start rc-service git.sr.ht start # Cronjob hinzufügen: */20 * * * * gitsrht-periodic ``` ### man.sr.ht - Web-UI: Port 5004 - API: Port 5104 man.sr.ht ist ein Git-gestütztes Wiki. Der Dienst hängt von git.sr.ht zur Verwaltung der Repositories ab. ``` apk add man.sr.ht mansrht-initdb rc-update add man.sr.ht rc-update add man.sr.ht-api rc-service man.sr.ht-api start rc-service man.sr.ht start ``` ### paste.sr.ht - Web-UI: Port 5011 - API: Port 5111 paste.sr.ht ist ein simpler Pastebin, mit dem man Codeschnipsel speichern und veröffentlichen kann. ``` apk add paste.sr.ht pastesrht-initdb rc-update add paste.sr.ht rc-update add paste.sr.ht-api rc-service paste.sr.ht-api start rc-service paste.sr.ht start ``` ### builds.sr.ht - Web-UI: Port 5002 - API: Port 5102 builds.sr.ht ist der Continuous-Integration-Dienst von Sourcehut. Da der Dienst KVM zur Virtualisierung verwendet, muss auf dem Hostsystem _Nested virtualization_ aktiviert werden, sollte der Dienst selbst in einer KVM-gestützten virtuellen Maschine installiert werden: builds.sr.ht besteht aus zwei Komponenten: dem Master-Server und dem Worker. Der Master-Server verwaltet die Builds, die Worker führen sie aus. Aus Sicherheitsgründen wird empfohlen, die Worker auf einem seperaten System zu installieren. Bei meiner Testinstallation habe ich jedoch beide Komponenten auf dem selben System installiert. Zuerst installiert man die erforderlichen Pakete und initialisiert die Datenbank: ``` # Master-Server apk add builds.sr.ht # Worker-Server builds.sr.ht-worker builds.sr.ht-images buildsrht-initdb ``` Der Nutzer `builds` muss genauso wie der git-Nutzer mit einem beliebigen Password versehen werden, um den SSH-Zugriff auf fehlgeschlagene Builds zu ermöglichen. Anschließend kann man den Master-Server starten ``` rc-update add builds.sr.ht rc-update add builds.sr.ht-api rc-service builds.sr.ht-api start rc-service builds.sr.ht start ``` Der Worker benutzt standardmäßig eine QEMU-Installation in einem Docker-Container, um die Build-VMs zu betreiben. Deswegen muss man zuerst Docker installieren und starten. Zusätzlich sollte man einen neuen Benutzer mit dem Namen `docker` anlegen und der Docker-Gruppe hinzufügen. Dann konfiguriert man sudo so, dass der `builds`-Nutzer das `/var/lib/images/control`-Skript zum Start der Buildmaschinen als `docker`-Nutzer aufrufen kann. Auf diese Weise muss man dem Build-Nutzer keine vollen Root- oder Docker-Rechte geben. ``` apk add docker rc-update add docker rc-service docker start sudo adduser -SDH docker docker visudo # Diese Zeile in die sudoers-Datei eintragen builds ALL=(docker) NOPASSWD: /var/lib/images/control ``` ``` cd /var/lib/images docker build -t qemu qemu/Dockerfile . ``` Als nächstes muss man die VM-Images bauen. Im Ordner `/var/lib/images` befinden sich Skripte für eine Vielzahl von Betriebssystemen und CPU-Architekturen. Ich habe zum Testen das Alpine 3.17-Image in einem Docker-Container gebaut. Dazu musste ich zunächst eine kleine Annpassung am Buildskript vornehmen. Das Skript unter `/var/lib/images/alpine/genimg` enthält den Befehl `modprobe nbd max_part=16`, der in einem Docker-Container nicht ausgeführt werden kann. Dieser Befehl muss deshalb auskommentiert werden und stattdessen vorher auf dem Hostsystem ausgeführt werden. Anschließend kann man das Image bauen: ``` modprobe nbd max_part=16 docker run -it --rm --privileged -v /var/lib/images:/images alpine:3.17 # Im Docker-Container cd /images/alpine/3.17 apk add qemu-img sfdisk syslinux e2fsprogs ./genimg ``` Mit der Datei `/etc/image-control.conf` kann der Worker konfiguriert werden (zugewiesener Arbeitsspeicher, Methode der Virtualisierung). ``` MEMORY=4096 default_means=docker ``` Nachdem der Worker konfiguriert wurde, kann man ihn mit dem Skript `/var/lib/images/control` testen. Hinweis: wenn der Container nicht startet, sollte man prüfen, ob das System genug RAM zum Start der VM zur Verfügung hat. ``` ./control alpine/latest boot x86_64 12345 docker ps # Prüfen, ob der Container gestartet wurde # Über die SSH-Verbindung kann man nun Befehle auf der Build-VM ausführen ssh -p 12345 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no build@localhost ./control alpine/latest cleanup 12345 ``` Jetzt kann der Worker gestartet werden: ``` # Start worker rc-update add builds.sr.ht-worker rc-service builds.sr.ht-worker start ``` ### todo.sr.ht - Web-UI: Port 5003 - API: Port 5103 ``` apk add todo.sr.ht ``` Im Gegensatz zu den anderen Diensten konnte ich die Datenbank für den todo-Dienst nicht mit `todosrht-initdb` erfolgreich initialisieren. Offenbar fehlten in diesem Skript bestimmte Datenbankobjekte, sodass die Anwendung Fehler lieferte. Stattdessen habe ich die `schema.sql`-Datei aus dem sourcehut-Repository verwendet. ``` wget "https://git.sr.ht/~sircmpwn/todo.sr.ht/blob/master/schema.sql" psql -U todo -d todo.sr.ht -f schema.sql todo-migrate stamp head ``` Anschließend können die Dienste gestartet werden. Hinweis: Der LMTP-Dienst ist dafür da, E-Mails zu empfangen, sodass man auf Issues per Mail antworten kann. Hierfür ist ein Mailserver nötig, weswegen ich diesen Dienst in meiner Testinstallation nicht vollständig konfigurieren konnte. ``` rc-update add todo.sr.ht rc-update add todo.sr.ht-api rc-update add todo.sr.ht-lmtp rc-update add todo.sr.ht-webhooks rc-service todo.sr.ht-webhooks start rc-service todo.sr.ht-lmtp start rc-service todo.sr.ht-api start rc-service todo.sr.ht start ``` ### lists.sr.ht - Web-UI: Port 5006 - API: Port 5106 lists.sr.ht ist der Mailingslisten-Dienst für Sourcehut. Mangels eines eigenen Mailservers konnte ich diesen Dienst in meiner Test-VM nicht einrichten. Eine Anleitung für die Mail-Konfiguration findet sich hier: ``` listssrht-initdb rc-update add lists.sr.ht rc-update add lists.sr.ht-api rc-update add lists.sr.ht-lmtp rc-update add lists.sr.ht-process rc-update add lists.sr.ht-webhooks rc-service lists.sr.ht-webhooks start rc-service lists.sr.ht-process start rc-service lists.sr.ht-lmtp start rc-service lists.sr.ht-api start rc-service lists.sr.ht start ```