WPF-OpenSource/src/studienarbeit/sourcehut_setup.md
2023-06-30 12:36:05 +02:00

15 KiB

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.

https://man.sr.ht/packages.md

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

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 auf Sourcehut.

Hier 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 <service>-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.<Sourcehut-Domain>/oauth erstellen.

OAuth-Setup

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

Die Client-ID und das Client-Secret, das auf der nächsten Seite angezeigt wird, können nun in die Konfigurationsdatei unter [<service>.sr.ht]/oauth-client-id und [<service>.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: https://docs.fedoraproject.org/en-US/quick-docs/using-nested-virtualization-in-kvm/

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: https://man.sr.ht/lists.sr.ht/configuration.md

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