diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 59e5de7..2335fd5 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -7,3 +7,12 @@ - [Aufgabe 3](./aufgaben/aufgabe_3.md) - [Aufgabe 4](./aufgaben/aufgabe_4.md) - [Aufgabe 5](./aufgaben/aufgabe_5.md) + +# Selfhosting von Open-Source-Entwicklertools + +- [Einleitung](./studienarbeit/1_einleitung.md) +- [GitLab](./studienarbeit/2_gitlab.md) +- [Gitea](./studienarbeit/3_gitea.md) +- [Sourcehut](./studienarbeit/4_sourcehut.md) +- [OneDev](./studienarbeit/5_onedev.md) +- [Anhang: Sourcehut-Setup](./studienarbeit/sourcehut_setup.md) diff --git a/src/studienarbeit/1_einleitung.md b/src/studienarbeit/1_einleitung.md new file mode 100644 index 0000000..93b1d53 --- /dev/null +++ b/src/studienarbeit/1_einleitung.md @@ -0,0 +1,161 @@ +# Selfhosting von Open-Source-Entwicklertools + +Um effizient mit anderen Entwicklern an Open-Source-Projekten arbeiten zu können, muss +man den Quellcode seines Projekts veröffentlichen, Aufgaben koordinieren und neue +Codebeiträge entgegen nehmen. + +Hierbei kommt fast immer eine Git-Hosting-Plattform zum Einsatz. Diese erlaubt es einem, +sein Repository zu veröffentlichen und mit anderen Personen über das Internet +zusammenzuarbeiten. Andere Nutzer und Entwickler können Softwarefehler melden, +Vorschläge für neue Features machen und neuen Code zum Projekt beitragen. + +Der meistgenutzte Git-Hosting-Anbieter ist GitHub. Die Plattform wurde von Tom +Preston-Werner, Chris Wanstrath, P. J. Hyett and Scott Chacon gegründet und ging 2008 +ans Netz. 2018 wurde die Firma von Microsoft übernommen. + +Der große Vorteil von GitHub ist, dass der Dienst für öffentliche Projekte vollkommen +kostenlos ist. Zudem hat der Dienst mit 100 Millionen Nutzern die mit Abstand größte +Community an potenziellen Beitragenden. + +GitHub bietet auch einen Continuous-Integration-Dienst namens GitHub Actions an, mit dem +man sein Projekt automatisch testen und veröffentlichen lassen kann. Im Gegensatz zu +vielen Konkurrenzanbietern setzt GitHub hierbei kein Nutzungslimit bei öffentlichen +Repositories. + +Allerdings hat die Nutzung von GitHub auch seine Nachteile. Zum einen ist man bei der +Nutzung eines fremden Webdiensts, insbesondere wenn dieser kostenlos ist und man +deswegen keinen Vertrag mit dem Anbieter abgeschlossen hat, komplett von dessen +Entscheidungen und Nutzungsbedingungen abhängig. Der Anbieter kann den Dienst +einstellen, kostenpflichtig machen, Features entfernen oder bestimmte Nutzer +ausschließen. + +Beispielsweise wurde der russische Webentwickler Nikolay Kuchumov wegen eines einzigen +beleidigenden Issues +[2020 auf GitHub gesperrt](https://medium.com/@catamphetamine/how-github-blocked-me-and-all-my-libraries-c32c61f061d3). +Dabei wurden alle seine Repositories von der Plattform entfernt. Noch absurder: GitHub +verlangte eine Kopie seines Personalausweis um die Sperre wieder aufzuheben. + +Es gibt auch einige Fälle von Open Source-Projekten, die von GitHub wegen angeblichen +Verstößen gegen das amerikanische Urheberrecht (DMCA) gesperrt wurden. Das prominenteste +Beispiel hierfür ist der Video-Downloader +[youtube-dl](github.blog/2020-11-16-standing-up-for-developers-youtube-dl-is-back/). +Auch das Repository der alternativen Smartwatch-App +[Gadgetbridge](https://www.heise.de/news/Pebble-Gadgetbridge-unter-Beschuss-3740625.html) +wurde zeitweise von GitHub gesperrt. Eine selbstgehostete Plattform ist dagegen viel +schwieriger zu sperren. + +Ein weiterer Grund für einige Entwickler, die GitHub-Plattform zu verlassen, ist die +Einführung von GitHub Copilot. Hierbei handelt es sich um ein künstliche Intelligenz, +die einem Programmierer automatisch Code-Vorschläge geben kann. Dessen Sprachmodell +wurde mit dem Code aus öffentlichen GitHub-Repositories trainiert. Kritiker sehen +hierbei eine Urheberrechtsverletzung, da der AI-generierte Code Schnipsel aus den +Trainingsdaten enthalten kann, die dann ohne Erwähnung des Urhebers in andere Projekte +eingefügt werden. + +Insbesondere bei privaten oder firmeninternen Projekten kann auch der Datenschutz ein +Grund sein, auf Webanwendungen von Fremdanbietern zu verzichten und die Daten auf +eigenen Servern zu speichern. Da GitHub nicht quelloffen ist und nur mit einer +kostspieligen Enterprise-Lizenz selbst gehostet werden kann, ist is für solche Fälle +attraktiv, eine Open-Source-Anwendung einzusetzen. + +Mittlerweile gibt es mehrere Open-Source-Projekte, die Alternativen zu GitHub entwickelt +hat. Im Gegensatz zu proprietären Webdiensten lassen sich diese Anwendungen auf eigenen +Servern installieren, sodass man die volle Autonomie über sein System behält. + +In dieser Arbeit werde ich vier von ihnen testen und vergleichen. + +## Testkriterien + +Ich habe jede Plattform auf meinem Rechner installiert und nach folgenden Kritierien +getestet: + +### 0\. Über das Projekt + +Zuerst werde ich einige grundlegende Informationen über die entsprechende Anwendung +präsentieren. + +- In welcher Programmiersprache ist die Anwendung geschrieben? +- Wie lange existiert das Projekt bereits? Ist es eine Abspaltung eines anderen + Projekts? +- Wie viele Beitragende hat das Projekt? +- Wie sieht die Architektur der Anwendung aus? Welche Dienste werden benötigt? + +### 1\. Installation und Einrichtung + +Hier gebe ich eine kurze Anleitung zur Installation und Einrichtung der Anwendung. Ich +werde hierbei bewerten, wie einfach die Installation vonstatten geht. + +Monolithisch (d.h. aus einem Dienst) aufgebaute Anwendungen sind in der Regel einfacher +einzurichten, bieten aber weniger Flexibilität bei der Skalierung für viele User. + +### 2\. Systemanforderungen + +Hierbei geht es nicht nur um die unterstützten Betriebssysteme und CPU-Architekturen, +sondern auch um den Bedarf an Rechenleistung und Arbeitsspeicher. Im Idealfall soll die +Software auch auf preisgünstigen Single Board-Computern und virtualisierten Servern +lauffähig sein, sodass sich jeder ein selbst gehostetes Setup leisten kann und nicht aus +Kostengründen auf proprietäre Anbieter angewiesen ist. + +Getestet wurden CPU-Auslastung und Arbeitsspeicherverbrauch auf einem Rechner mit einem +Ryzen 5700G-Prozessor (16 Threads) und 32GB RAM. Die angegebene CPU-Auslastung bezieht +sich auf die ausgelasteten Threads (wie in htop angezeigt), d.h. 100% entspricht einem +voll ausgelastetem Thread, 16.000% einem voll ausgelasteten Prozessor. + +Neben dem Ressourcenverbrauch im Leerlauf habe ich auch die CPU-Auslastung unter Last +gemessen. Hierfür habe ich das Repository des Linux-Kernels importiert und mir die +Versionsgeschichte und die Blame-Ansicht der Makefile im Stammverzeichnis anzeigen +lassen. + +### 3\. Bedienung + +Wie einfach ist die Weboberfläche zu bedienen? Ist es möglich, schnell durch +Repositories zu navigieren? Gibt es eine Suchfunktion, um beispielsweise eine bestimmte +Funktion im Code zu finden? + +Zudem habe ich dir Unterstützung für verschiedene Dateiformate getestet. Alle +Plattformen können Code, Markdown und Textdateien darstellen. Binärdateien können auf +diese Weise natürlich nicht dargestellt werden, weswegen einige Plattformen spezielle +Viewer für bestimmte Dateitypen mitbringen. Um dies zu testen, habe ich ein Repository +mit Dateien in folgenden Formaten angelegt. + +- Bilder (\*.jpg, \*.svg) +- Tabellen (\*.csv, \*.xlsx, \*.ods) +- Text (\*.rst, \*.tex, \*.docx, \*.odt) +- PDF-Dokumente +- 3D-Modelle (\*.stl) +- Jupyter-Notebooks (\*.ipynb) + +Zum Vergleich: GitHub unterstützt alle diese Dateitypen mit Ausnahme von LaTEX- und +MS/Open Office-Dokumenten. + +### 4\. Import bestehender Projekte + +Eine gute GitHub-Alternative sollte es dem Entwickler ermöglichen, bestehende Projekte +von anderen Providern zu importieren. Hierbei soll nicht nur das Repository, sondern +auch z.B. Issues übertragen werden können. + +### 5\. Zusatzfeatures + +Bietet die Anwendung zusätzlich zu Git-Repositories, Issues und Pull-Requests noch +weitere Features an? + +Beispiele hierfür wären das Hosting von statischen Websites direkt aus Repositories +heraus, ein Repository für Softwarepakete verschiedener Programmiersprachen oder +Projektmanagement-Tools. + +### 6\. Continuous Integration + +Continuous Integration (CI), also das automatische Testen von neuem Code ist ein fester +Teil des Worflows vieler Entwickler. Hat die Plattform einen CI-Dienst eingebaut oder +lässt sie sich mit anderen CI-Diensten integrieren? + +### 7\. Öffentliche Instanzen + +Nicht jeder möchte den Aufwand betreiben, seine Git-Hosting-Plattform selbst zu hosten. +Deswegen ist es vom Vorteil, wenn es die Möglichkeit gibt, anstelle dessen einer +öffentlichen Instanz beizutreten. + +## Quellen + +- [Software Freedom Conservancy](https://sfconservancy.org/GiveUpGitHub/): Give up + GitHub diff --git a/src/studienarbeit/2_gitlab.md b/src/studienarbeit/2_gitlab.md new file mode 100644 index 0000000..a25ccd9 --- /dev/null +++ b/src/studienarbeit/2_gitlab.md @@ -0,0 +1,278 @@ +# GitLab + +2011, drei Jahre nach dem Start von GitHub veröffentlichten Dmytro Zaporozhets und Sytse +Sijbrandij die erste Version von GitLab. Damit ist GitLab die erste und bekannteste +Open-Source-Alternative zu GitHub. + +GitLab Community Edition ist unter der MIT-Lizenz veröffentlicht. Die Firma hinter +GitLab verfolgt ein "Open Core"-Geschäftsmodell, d.h. einige fortgeschrittene Features +sind nicht in der Community Edition enthalten und erfordern die proprietären Versionen +"Premium" bzw. "Ultimate". Diese sind nur in Form eines Abonnements zum Preis von 29 +(Premium) bzw. 99USD (Ultimate) pro Nutzer und Monat erhältlich. Open-Source-Projekte +und Bildungseinrichtungen können die Ultimate-Version kostenfrei nutzen. + +Im Kern ist GitLab eine Ruby-on-Rails-Webanwendung. Allerdings sind einige Funktionen +der Plattform (bspw. SSH oder Git-Operationen) an zusätzliche Services ausgelagert. Die +meisten dieser Services sind in Go implementiert. Das Webfrontend wurde mit Vue.js +implementiert. + +GitLab Architektur + +- **Workhorse** Reverse Proxy, der HTTP-Anfragen an Git oder die Hauptanwendung + weiterleitet +- **Gitaly** Microservice zur Speicherung der Git-Repositories und Verarbeitung von + Git-Anfragen +- **GitLab Shell** SSH-Server +- **Sidekiq** Task Queue zur Ausführung von Aufgaben im Hintergrund + +GitLab verwendet eine PostgreSQL-Datenbank zur Speicherung seiner Daten. Zudem kommt +eine Redis-Instanz als Cache und Event Queue zum Einsatz. + +Getestet wurde GitLab in der Version 16.1.1. + +## Installation + +Um die Installation der Anwendung trotz ihres Aufbaus aus verschiedenen Services zu +vereinfachen, stellt GitLab ein Omnibus-Paket zur verfügung. Hierbei handelt es sich um +ein Linux-Softwarepaket, das die gesamte GitLab-Anwendung mit allen Services (inklusive +NGINX, Redis und Postgres) beinhalten. Die Pakete sind für die meisten +Linux-Distributionen (Ubuntu, Debian, Alma Linux, CentOS, OpenSUSE, Raspberry Pi OS) +verfügbar. + +Um Gitlab als Omnibus-Paket zu installieren, muss man zuerst das Gitlab-Repository zu +seinem System hinzufügen. Hierfür kann man dieses Skript verwenden: +. + +Danach kann man GitLab mit diesem Befehl installieren und starten: + +``` +GITLAB_ROOT_PASSWORD="" EXTERNAL_URL="http://gitlab.example.com" apt install gitlab-ce +``` + +Der Konfigurationsprozess dauert mehrere Minuten. Wenn der Webserver gestartet ist, kann +man die Weboberfläche aufrufen und sich anmelden (Benutzername: `root`). + +GitLab stellt auch ein Docker-Image (`gitlab/gitlab-ce`) zur Verfügung, welches das +Omnibus-Paket beinhaltet. Der Einrichtungsprozess ist der gleiche wie bei einer bare +metal-Installation, mit dem Unterschied dass die Konfiguration durch die +Umgebungsvariable `GITLAB_OMNIBUS_CONFIG` erfolgt. + +[Hier](./assets/gitlab/docker-compose.yml) ist die Docker-Compose-Datei, die ich für +meine Testinstallation verwendet habe. + +Für Unternehmen und große Organisationen mit Tausenden Nutzern bietet GitLab in ihrer +Dokumentation auch Referenzarchitekturen für hochverfügbare Systemen mit mehreren +Servern. + +## Systemanforderungen + +GitLab bietet Pakete für eine +[Vielzahl von Linux-Distributionen](https://docs.gitlab.com/ee/administration/package_information/supported_os.html), +sowohl für Intel/AMD als auch für ARM-Prozessoren. Das offizielle Docker-Image ist +jedoch nur für die arm64-Architektur verfügbar. + +GitLab hat unter allen getesteten Plattformen den höchsten Ressourcenverbrauch. + +Im Leerlauf bewegt sich die CPU-Last auf meinem Testsystem zwischen 3 und 30 Prozent. +Der Arbeitsspeicherverbrauch beträgt ganze 6GB. + +Aufwändige Git-Operationen können Lastspitzen über 100% für eine Dauer von bis zu 5 +Sekunden pro Anfrage verursachen. + +GitLab erwähnt in ihrer Dokumentation, dass man die Konfiguration anpassen kann, um den +Ressourcenverbrauch etwas zu senken. Nachdem ich diese Zeilen zur Konfigurationsdatei +hinzugefügt habe, sank der Speicherbedarf auf 2.8GB und die CPU-Auslastung auf 1-12%. + +``` +# Reduce the number of running workers to the minimum in order to reduce memory usage +puma['worker_processes'] = 2 +sidekiq['max_concurrency'] = 9 +# Turn off monitoring to reduce idle cpu and disk usage +prometheus_monitoring['enable'] = false +``` + +Für eine Installation auf Single Board-Computern und kleinen V-Servern ist der +Speicherverbrauch jedoch weiterhin zu hoch. GitLab gibt als Mindestanforderung 4 +CPU-Kerne und 4GB RAM an. + +## Bedienung + +Gitlab's Weboberfläche wurde mit dem VueJS-Framework realisiert. Die gesamte +Weboberfläche wird somit clientseitig mittels JavaScript gerendert. Dies erlaubt eine +äußerst flüssige Navigation durch die Webseite, da die Seite nicht bei jedem +Navigationsschritt neu geladen wird. Der Nachteil dieser Lösung: Javascript ist für die +Darstellung der Webseite zwingend erforderlich. + +GitLab bietet die Möglichkeit, den Code eines Repositories zu durchsuchen. Die +Verwendung einer externen Elasticsearch-Instanz für die Suche und die Möglichkeit, die +gesamte Gitlab-Instanz zu durchsuchen, ist allerdings den kostenpflichtigen Versionen +vorbehalten. + +GitLab unterstützt in der Standardkonfiguration die meisten Dateiformate unter den +getesteten Plattformen. Auf der Weboberfläche können Bilder, CSV-Tabellen, PDF-Dokumente +und stl-Modelle betrachtet werden, alternative Markupsprachen wie Restructured Text +werden ebenfalls unterstützt. Es gibt sogar die Möglichkeit, GeoJSON-Dateien (Listen von +GPS-Standorten) auf einer OpenStreetMap-Karte darzustellen. + +Eine Besonderheit der Gitea-Weboberfläche stellt die Web-IDE dar. GitLab verfügt über +eine modifizierte Version von Visual Studio Code, mit der man direkt im Browser an +seinen Projekten arbeiten kann. + +![GitLab-Web-IDE](./assets/gitlab/web_ide.png) + +## Import bestehender Projekte + +GitLab erlaubt den Projektimport von GitHub, Bitbucket, FogBugz, Gitea sowie von anderen +GitLab-Instanzen. + +Die Importfunktion ist standardmäßig deaktiviert und muss erst in der _Admin Area_ +aktiviert werden (_Settings_ \> _General_ \> _Visibility and access controls_ \> _Import +sources_). + +Für den Import von GitHub-Projekten muss man sich mit einem Access Token anmelden und +bekommt anschließend eine Übersicht aller Repositories angezeigt. Hier kann man +auswählen, welche Repositories übertragen werden sollten. Der Import umfasst auch +Issues, Pull Requests und Releases. + +![GitLab-Import](./assets/gitlab/import.png) + +Als einzige Plattform im Test bietet GitLab die Möglichkeit, ein Repository mit +sämtlichen gespeicherten Daten als zip-Datei zu exportieren. Dies erlaubt nicht nur den +Import auf anderen Instanzen sondern bietet dem Nutzer auch eine Backup-Option. + +## Zusatzfeatures + +GitLab hat von allen getesteten Plattformen die meisten Features. Einige Features sind +jedoch der proprietären Premium/Ultimate Edition vorbehalten, die ich nicht getestet +habe. + +Die Projektmanagement-Features von GitLab sind die besten im Test. GitLab erlaubt das +Erstellen von Issues mit Labels, Verantwortlichen, Fälligkeitsterminen und geleisteter +Arbeitszeit. Zudem können Issues zu Meilensteinen hinzugefügt werden. + +Issue Boards erlauben einen schnellen Überblick über den alle gerade bearbeiteten +Issues. Es lassen sich Spalten erstellen, die Issues mit einem bestimmten Tag auflisten. +Erstellt man also z.B. zwei Tags: "Implementierung" und "Review" und legt in seinem +Board zwei Spalten hierfür an, erhält man eine Übersicht über den Fortschritt aller +Issues. Issues lassen sich zwischen Spalten verschieben, wodurch sich auch die Tags des +Issues ändern. + +![GitLab Kanban](./assets/gitlab/kanban.png) + +Ein interessantes Feature ist die Möglichkeit, zu einem Issue mehrere Tasks +hinzuzufügen. Tasks sind Sub-Issues, die ihre eigene Beschreibung und Diskussion haben, +aber unter einem Issue zusammengefasst sind. Auf diese Weise lassen sich große Features +in kleinere Arbeitsschritte aufteilen, die von verschiedenen Teammitgliedern erledigt +werden können. + +![GitLab Issue mit Task](./assets/gitlab/issue.png) + +Viele fortgeschrittene Projektmanagement-Features sind allerdings der Enterprise Edition +vorbehalten. Hierzu gehört z.B. das Anlegen von Boards mit Filtern (z.B. für einen +bestimmten Meilenstein) oder Aufwandsschätzungen. + +Um Projekte zu dokumentieren bietet GitLab ein auf Git und Markdown basierendes Wiki. +Zudem gibt es mit "Snippets" einen Pastebin, der ebenfalls Git zur Speicherung der +Codeschnipsel verwendet. + +Es gibt auch die Möglichkeit, mit GitLab statische Webseiten zu hosten. Die Seiten +können mit GitLab CI gebaut und unter einer persönlichen Subdomain veröffentlicht +werden. + +GitLab bietet auch eine Paketregistry für Bibliotheken verschiedener Programmiersprachen +(z.B. Maven, npm, Python) an. Die Unterstützung für einige Programmiersprachen wie Ruby +ist allerdings noch experimentell. \*.deb-Pakete sowie Docker-Images können ebenfalls +mit GitLab gehostet werden. + +Zur einfachen Bedienung mit der Kommandozeile bietet GitLab das Tool `glab` an. Damit +lassen sich beispielsweise Issues und Pull Requests erstellen und bearbeiten, Snippets +hochladen und CI-Build starten. Es gibt auch ein offizielles VS-Code-Plugin, das +Pull-Requests, Issues und CI-Builds in den Texteditor integriert. + +## Continous Integration + +Gitlab verfügt über ein eingebautes CI-System, um Software automatisiert zu testen und +zu veröffentlichen. Das System kann Builds in Docker-Containern, auf einem +Kubernetes-Cluster, in einer VirtualBox-Maschine oder ohne Virtualisierung ausführen. +Hierfür verwendet Gitlab ein verteiltes System aus Runnern. Die Runner kommunizieren +über das Internet mit der Gitlab-Instanz und können so neue Buildaufträge +entgegennehmen. + +Um einen Runner einzurichten, muss man zuerst die erforderliche Konfigurationsdatei +erstellen. Hierfür startet man den Runner mit dem Befehl `register`: + +``` +docker run --rm -it -v $(pwd)/runner-config:/etc/gitlab-runner gitlab/gitlab-runner register +``` + +Daraufhin fragt der Runner nach der URL der Gitlab-Instanz und einem +Registrierungstoken. Den Token kann man sich entweder in den Repository-Einstellungen +oder in der Admin-Oberfläche generieren lassen (je nachdem, ob man den Runner nur zu +einem Projekt oder der gesamten Instanz hinzufügen möchte). Anschließend muss man +festlegen, wie der Runner die Builds ausführen sollte. In meinem Test habe ich den +`docker`-Executor gewählt. + +Wenn die Konfiguration abgeschlossen ist, kann man den Runner mit diesem Befehl starten + +``` +docker run --rm -it -v $(pwd)/runner-config:/etc/gitlab-runner gitlab/gitlab-runner +``` + +![Runner](./assets/gitlab/runners.png) + +Anschließend kann man für sein Repository einen Build definieren. Hierfür muss man eine +Datei mit dem Namen `.gitlab-ci.yml` im Wurzelverzeichnes des Repositories erstellen, in +der die einzelnen Schritte des Builds beschrieben werden. GitLab stellt ein Repository +mit Beispielen für verschiedene Programmiersprachen und Frameworks zur Verfügung, um den +Einstieg zu erleichtern. + +```yml +image: "rust:latest" + +test:cargo: + script: + - rustc --version && cargo --version # Print version info for debugging + - rustup component add rustfmt clippy + - cargo fmt --all --check + - cargo clippy --all --features=rss -- -D warnings + - cargo test --features=rss --workspace +``` + +## Öffentliche Instanzen + +Gitlab betreibt selbst eine öffentliche Instanz der proprietären Ultimate-Version unter +[gitlab.com](https://gitlab.com/explore/). + +Daneben gibt es eine Vielzahl von communitybetriebenen GitLab-Instanzen, die die freie +Community Edition verwenden. Viele große Open-Source-Projekte und Organisationen hosten +eine eigene GitLab-Instanz, wie zum Beispiel [Debian](https://salsa.debian.org), +[Framasoft](https://framagit.org/public/projects/) oder [KDE](https://invent.kde.org). + +## Fazit + +GitLab ist zu Recht seit mehr als zehn Jahren die führende quelloffene +GitHub-Alternative. Mittlerweile bietet GitLab mehr Features als die Konkurrenz von +Microsoft. + +Trotz seiner komplexen Architektur lässt sich GitLab relativ einfach und schnell +installieren, da das Omnibus-Paket die einzelnen Dienste automatisch konfiguriert. + +Insbesondere Unternehmen und große Organisationen werden die professionellen Features +und den kommerziellen Support zu schätzen wissen. + +Darüber hinaus bietet Gitlab selbst in der Open-Source-Version die besten +Projektmanagement-Features im Test. Wer also keine separate Projektmanagement-Anwendung +einsetzen möchte, ist mit Gitlab ebenfalls gut beraten. + +Wer seine Plattform allerdings auf einem kleinen Single Board Computer oder V-Server +betreiben möchte, sollte sich dagegen nach einer leichtgewichtigeren Alternative +umsehen. + +## Quellen + +- Dokumentation +- Repository +- Architekturübersicht + +- Liste von öffentlichen GitLab-Instanzen + diff --git a/src/studienarbeit/3_gitea.md b/src/studienarbeit/3_gitea.md new file mode 100644 index 0000000..bffb94b --- /dev/null +++ b/src/studienarbeit/3_gitea.md @@ -0,0 +1,327 @@ +# Gitea + +Das Gitea-Projekt begann 2016 als Fork der Git-Hosting-Plattform Gogs. Lunny Xiao, einer +der Beitragenden von Gogs, war damit unzufrieden, dass der Gründer des Projekts, Joe +Chen, das Projekt alleine betreuen und keine weiteren Maintainer ernennen wollte. + +2022 gründete Lunny Xiao die Firma Gitea Limited. Die Firma bietet Unternehmen Hosting- +und Supportdienstleistungen für Gitea an. Da einige Mitglieder der Community einem +kommerziell geleiteten Open-Source-Projekt misstrauen, entstand ein neuer Fork names +Forgejo. Forgejo steht unter der Leitung von Codeberg, einem Berliner Verein, der seit +2018 eine öffentliche Gitea-Instanz betreibt. Abgesehen von Design- und Namensänderungen +unterscheidet sich Forgejo von Gitea momentan kaum. + +Gitea ist in Go geschrieben und besteht aus einer einzigen ausführbaren Datei. +Standardmäßig verwendet Gitea eine interne SQLite-Datenbank, alternativ werden auch +externe Datenbanken (MySQL, MariaDB, Postgres, MS SQL) unterstützt. + +Die Weboberfläche wied serverseitig mit Templates gerendert. Einige Websitekomponenten +wie z.B. Drop-Down-Menüs erfordern JavaScript. + +Getestet wurde die Version 1.20.0-rc2. + +## Installation + +Gitea stellt kompilierte Binaries für alle gängigen Betriebssysteme unter + zur Verfügung. Von dort aus lässt sich die Anwendung +einfach herunterladen und starten. + +Alternativ gibt es auch [offizielle](https://pkgs.org/download/gitea) und +[inoffizielle](https://gitea.com/gitea/awesome-gitea/src/branch/main/README.md#user-content-packages) +Pakete für die meisten Linux-Distributionen. + +Darüber hinaus stellt Gitea auch ein Docker-Image (`gitea/gitea`) zur Verfügung. + +Die Einrichtung ist extrem simpel. Beim ersten Start wird diese Konfigurationsseite +angezeigt, auf der man die grundlegenden Einstellungen (z.B. Datenbank-URL, +Admin-Passwort) vornehmen kann. Nach der Bestätigung ist Gitea in wenigen Sekunden +bereit zur Verwendung. + +![Gitea-Konfiguration](./assets/gitea/setup.png) + +Dieser Konfigurationsassistent wird jedoch nur beim ersten Start angezeigt. Alle +weiteren Konfigurationsänderungen müssen durch die +`app.ini`-[Konfigurationsdatei](https://docs.gitea.com/1.20/administration/config-cheat-sheet) +erfolgen. Gitea verfügt zwar über eine Admin-Oberfläche, diese dient allerdings +hauptsächlich der Nutzerverwaltung und erlaubt keine Konfigurationsänderungen. + +## Systemanforderungen + +Gitea ist auf jedem Betriebssystem und jeder CPU-Architektur lauffähig, die von der +Programmiersprache Go unterstützt wird. Binaries für MacOS (amd64/aarch64), FreeBSD +(amd64), Windows (i386/amd64) und Linux (i386/amd64/arm5/arm6/aarch64) werden offiziell +zum Download angeboten. Das offizielle Docker-Image ist für die amd64- und +aarch64-Architektur verfügbar. + +Im Leerlauf benötigt der Server ca. 150MB Arbeitsspeicher und verursacht unter 0.1% +CPU-Auslastung. Damit ist Gitea die mit Abstand leichtgewichtigste Plattform in Test und +eignet sich perfekt für den Einsatz auf schwächerer Hardware. + +## Bedienung + +Die Weboberfläche von Gitea wird serverseitig mit Hilfe von Templates gerendert +(klassische Multi-Page-Anwendung). Dies hat den Vorteil, dass die Seite auch ohne +JavaScript dargestellt werden kann (wenn auch mit eingeschränkter Bedienbarkeit). + +Obwohl bei jedem Navigationsschritt durch ein Repository die gesamte Seite neu geladen +wird, läuft die Navigation durch Ordner sehr flüssig. + +Optisch und funktional ist die Benutzerschnittstelle stark an GitHub angelehnt. Wer also +vorher GitHub verwendet hat, findet sich auf Gitea schnell zurecht + +Der Code in Gitea-Repositories kann durchsucht werden, allerdings ist diese Funktion +standardmäßig deaktiviert. Um sie zu aktivieren, müssen diese Zeilen zur +Konfigurationsdatei hinzugefügt werden: + +``` +[indexer] +REPO_INDEXER_ENABLED=true +``` + +Standardmäßig verwendet Gitea die Bibliothek [Bleve](https://blevesearch.com/) für die +Suche, es kann jedoch auch eine externe Elasticsearch-Instanz verwendet werden. + +![Gitea-Suche](./assets/gitea/search.png) + +Gitea kann standardmäßig Bilder, CSV-Dateien, PDFs und Markdown-Dateien auf der +Weboberfläche darstellen. Andere Markupsprachen wie ReStructured Text werden +standardmäßig nicht unterstützt. Allerdings bietet Gitea als einzige getestete Plattform +die Möglichkeit, zusätzliche Renderer in der Konfigurationsdatei zu definieren. +Beispielsweise kann Gitea Pandoc verwenden, um RST, LaTEX oder Word-Dokumente in HTML zu +konvertieren und anzuzigen. Es ist auch möglich, mit etwas Bastelei einen Viewer für STL +oder Excel-Dateien zu installieren. + +## Import bestehender Projekte + +Gitea bietet die Möglichkeit, Projekte von GitHub, Gitlab, Gogs, OneDev, GitBucket und +Codebase zu importieren. Neben den Repositories können auch Issues, Pull-Requests und +Releases importiert werden. + +Der Versuch, zwei meiner GitHub-Projekte mit Issues und Pull-Requests zu übertragen, +scheiterte jedoch mit einer Fehlermeldung. + +## Zusatzfeatures + +Gitea bietet grundlegende Features zum Projektmanagement. Issues können erstellt, mit +Labels versehen und bestimmten Entwicklern zugewiesen werden. Es können +Fälligkeitstermine für Issues festgelegt und die Arbeitszeit hinterlegt werden. + +Dazu kommt die Möglichkeit, Issues zu Meilensteinen hinzuzufügen und somit +beispielsweise den Arbeitsfortschritt für eine neue Version zu verfolgen. + +Darüber hinaus können in Gitea Kanbanboards erstellt werden. Allerdings sind diese +Boards nicht in das restliche Issue-System integriert und deswegen umständlich zu +nutzen. Issues müssen beispielsweise manuell den Boards hinzugefügt werden. Während +GitLab Labels verwendet, um die Issues den Spalten zuzuordnen ist in Gitea außerhalb des +Boards nicht ersichtlich, welchen Status ein Issue hat. Ein Issue, das in die +Done-Spalte verschoben wird, wird nicht automatisch geschlossen. Umgekehrt führt das +Schließen eines Issues nicht zu einer Platzierung in der Done-Spalte. + +Dokumentation für Gitea-Repositories kann in einem simplen, auf Markdown basierenden +Wiki veröffentlicht werden. + +Das Hosting statischer Webseiten unterstützt Gitea nicht, weswegen das Team von Codeberg +hierfür eine [eigene Lösung](https://codeberg.org/Codeberg/pages-server) entwickelt hat. + +Gitea bietet eine integrierte Registry für Pakete aller gängigen Programiersprachen +(z.B. Python, npm, Rust). Wer eine Softwarebibliothek entwickelt, kann diese auf seiner +Gitea-Instanz veröffentlichen, sodass andere Entwickler sie nutzen können. Zudem +unterstützt die Gitea-Registry Linux-Pakete (.deb und .rpm) sowie Docker-Images. + +Gitea unterstützt als einzige getestete Plattform agit. Dies ist ein alternativer +Git-Workflow, der von Alibaba entwickelt wurde. Agit erlaubt es Entwicklern, Pull +Requests zu erstellen ohne zuvor einen Fork des Projekts anzulegen. Hierbei wird die +Änderung mit diesem Befehl in einen versteckten Branch des Reposiories gepusht, worauf +Gitea automatisch eine PR erstellt. + +Dieser Befehl erfordert im Gegensatz zum normalen push keine Schreibrechte im +entsprechenden Repository. + +``` +git push origin HEAD:refs/for/main -o topic="feat/user-search" -o title="Add user search" +``` + +Es existiert auch ein Git-Plugin für agit namens +[`git-repo`](https://git-repo.info/en/2020/03/agit-flow-and-git-repo/), damit man nicht +jedes Mal diesen langen Befehl eintippen muss, sondern den Beschreibungstext direkt in +die Kommandozeile tippen kann. + +Gitea lässt sich auch mit dem Tool [`tea`](https://gitea.com/gitea/tea) auf der +Kommandozeile bedienen. Auf diese Weise lassen sich Issues erstellen und lesen oder Pull +Requests erstellen und abrufen. + +Gitea bietet dem Administrator vollen Zugriff auf seinen Webserver und das +Templatesystem. Dadurch kann man Templates und Stylesheets durch eigens angepasste +Versionen ersetzen und die Weboberfläche nach seinen Bedürfnissen anpassen. Dies ist +insbesondere für große Organisationen und Firmen interessant, die ihre +Git-Hosting-Plattform nach ihrem Corporate Design gestalten möchten. + +Ein Beispiel für eine stark angepasste Gitea-Oberfläche ist die Instanz des +[Blender-Projekts](https://projects.blender.org/), die sich nahtlos in die restliche +Projektseite einfügt. + +## Continous Integration + +### Woodpecker + +Gitea verfügte lange nicht über einen eingebauten CI-Server. Allerdings gibt es eine +Schnittstelle, um externe CI-Systeme anzubinden. + +Ich habe einige CI-Systeme getestet, die mit Gitea kompatibel sind. +[Woodpecker](https://woodpecker-ci.org/) ist meiner Meinung nach eines der besten +Systeme. Bei Woodpecker handelt es sich um einen Fork des Drone CI-Projekts nach deren +Wechsel von der Apache License zu einer nichtkommerziellen Lizent. + +Woodpecker erlaubt den Login mit seinem Gitea-Account und zeigt dem Entwickler auf der +Startseite eine Liste aller Repositories an. Von dort aus lässt sich die CI für +bestimmte Repositories aktivieren. Daraufhin konfiguriert Woodpecker die Webhooks des +Repositories, sodass die Builds automatisch bei Aktualisierungen gestartet werden. + +Woodpecker verwendet sogenannte Agents, die mittels GRPC mit dem zentralen Server +kommunizieren und Buildaufträge empfangen. Die Agents verwenden Docker, um die Builds in +Containern auszuführen. + +![Woodpecker CI](./assets/gitea/woodpecker.png) + +Die Builds werden in einer yml-Datei mit dem Namen `.woodpecker.yml` im +Wurzelverzeichnes des Repositories definiert. Jeder Buildschritt wird in einem eigenen +Docker-Container ausgeführt. + +```yaml +pipeline: + test: + image: rust:latest + commands: + - rustup component add rustfmt clippy + - cargo fmt --all --check + - cargo clippy --all --features=rss -- -D warnings + - cargo test --features=rss --workspace +``` + +Die Installation von Woodpecker ist etwas komplizierter, da Woodpecker sowohl einen +HTTP-Server als auch einen GRPC-Server bereitstellt. Möchte man Agents auf anderen +Servern betreiben, sollte auch der GRPC-Server mit TLS gesichert sein. Hierfür kann man +einen Reverse Proxy (z.B Traefik) verwenden. Allerdings beinhaltet die offizielle +Dokumentation keine Anleitung hierfür. + +[Hier](./assets/woodpecker/docker-compose.yml) ist die Docker-Compose-Datei, die ich für +meine Setup (mit Traefik) verwendet habe. Vor der Verwendung müssen noch die folgenden +Konfigurationsvariablen bearbeitet werden: + +- `WOODPECKER_HOST` URL der Woodpecker-Instanz +- `WOODPECKER_GITEA_URL` URL der Gitea-Instanz +- `WOODPECKER_GITEA_CLIENT` / `WOODPECKER_GITEA_SECRET` OAuth-Zugangsdaten (in Gitea das + Einstellungsmenü aufrufen und unter _Create a new OAuth2 Application_ einen neuen + Client erstellen. Redirect URI: `/authorize`) +- `WOODPECKER_AGENT_SECRET` ist das Passwort für alle mit der Instanz verbundenen + Agents. Hierfür sollte man sich einfach einen langen Zufallsstring erzeugen, + beispielsweise mit `openssl rand -hex 32`. + +### Gitea Actions + +Mit dem vorletzten Release 1.19 bekam Gitea jedoch ein eigenes CI-System: Gitea Actions. +Hierbei wurde nicht nur der Name an die Konkurrenz von Microsoft angelehnt. Das System +basiert auf [act](https://github.com/nektos/act), einer freien Implementation von GitHub +Actions. Ursprünglich wurde act zum lokalen Testen von GitHub Actions entwickelt. Gitea +hat die Anwendung stattdessen als Basis für ihr CI-System verwendet. + +Standardmäßig sind Gitea Actions in den Einstellungen deaktiviert. Um sie verwenden zu +können, muss man diese Zeilen zur Konfigurationsdatei hinzufügen: + +``` +[actions] +ENABLED=true +``` + +Anschließend muss man wie bei Gitlab und Woodpecker einen Runner einrichten, der die +Builds mittels Docker ausführt. Der Runner kann als Binary von der +[Gitea-Download-Seite](https://dl.gitea.com/act_runner/) heruntergeladen werden. Es ist +auch möglich, den Runner in einem Docker-Container zu betreiben. + +Nachdem man den Runner heruntergeladen hat, muss man ihn konfigurieren. Dafür führt man +den Befehl `act-runner register` auf. Anschließend muss man die Adresse der Instanz und +einen Registrierungstoken, den man in der Admin-Oberfläche unter _Actions / Runners_ +erzeugen kann. + +Anschließend muss man noch die Actions im gewünschten Repository aktivieren, in dem man +in den Einstellungen den Haken bei _Enable Repository Actions_ setzt. + +Die Builds werden als yaml-Dateien im Verzeichnis `.gitea/workflows` definiert. Obwohl +Gitea die gleiche Syntax wie Github Actions verwendet, sind die Workflows nicht 1:1 +kompatibel. Beispielsweise lädt Gitea vordefinierte Actions wie `actions/checkout` nicht +von [github.com/actions](https://github.com/actions) sondern von +[gitea.com/actions](https://gitea.com/actions) herunter, sodass einige Actions nicht +verfügbar sind. + +Außerdem führt GitHub seine Builds in einer virtuellen Maschine mit einer Vielzahl an +vorinstallierten Programmiersprachen und Entwicklertools aus. Da das Image dieser +Maschine sehr groß ist, benutzt Gitea stattdessen standardmäßig den +Debian+NodeJS-Container `node:16-bullseye`. Das Image enthält neben Node.js auch Python, +gcc, make und curl. Wer andere Programmiersprachen benutzt, muss jedoch Anwendungen +nachinstallieren (wie beispielsweise Rust im unteren Beispiel). Es ist jedoch möglich, +andere Docker-Images zu verwenden. + +```yaml +name: Test +on: [push] + +jobs: + Test: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Setup Rust + run: | + curl https://sh.rustup.rs -sSf | sh -s -- -y + source "$HOME/.cargo/env" + - name: Test + run: | + cargo clippy + cargo test +``` + +![Gitea Actions](./assets/gitea/actions.png) + +Ein wichtiges Feature, das Gitea Actions momentan noch fehlt ist die Möglichkeit, +Workflows manuell zu starten. Da Gitea Actions noch relativ neu ist, gehe ich jedoch +davon aus, dass dieses Feature in Zukunft implementiert wird. + +## Öffentliche Instanzen + +Die von den Maintainern des Projekts betriebene Instanz unter +[gitea.com](https://gitea.com/explore/repos) verfügt über 5600 Repositories. + +Eine noch größere Instanz betreibt der Berliner Verein Codeberg e.V. Auf +[codeberg.org](https://codeberg.org) werden 30900 öffentliche Repositories gehostet. +Zusätzlich zu ihrer Gitea-Instanz bietet Codeberg auch einen Webhosting-Dienst unter +[\*.codeberg.page](codeberg.page) an. Codeberg betreibt auch einen Woodpecker-CI-Server, +für dessen Verwendung die Nutzer allerdings manuell freigeschaltet werden müssen. + +Da Gitea sehr einfach und günstig zu hosten ist, wird es von einigen Open +Source-Projekten auch als sekundäre Plattform zusätzlich zu GitHub verwendet. +Beispielsweise betreibt das Team hinter dem alternativen YouTube-Frontend Invidious eine +[Gitea-Instanz](https://gitea.invidious.io/iv-org), um vor eventuellen Takedowns des +Repositories auf GitHub sicher zu sein + +## Fazit + +Während GitLab meiner Meinung nach die beste Lösung für große Organisationen und +Unternehmen darstellt, ist Gitea das perfekte System für einzelne Entwickler, kleine +Teams und Hobbybastler. Durch seinen sparsamen Ressourcenverbrauch ist Gitea auf fast +jeder Hardware lauffähig und die Einrichtung funktioniert einfach und schnell. + +Darüber hinaus lässt sich Gitea mit eigenen Themes und Templates individuell anpassen +und zu seiner persönlichen Website machen. + +Die Projektmanagement-Features von Gitea sind allerdings eher rudimentär. Wer +Kanbanboards benötigt, sollte Gitlab oder OneDev in Betracht ziehen oder hierfür eine +externe Software verwenden. + +## Quellen + +- Projektseite +- Repository +- Start von Codeberg (damals TeaHub) + , + diff --git a/src/studienarbeit/4_sourcehut.md b/src/studienarbeit/4_sourcehut.md new file mode 100644 index 0000000..026ec8e --- /dev/null +++ b/src/studienarbeit/4_sourcehut.md @@ -0,0 +1,292 @@ +# Sourcehut + +Eine Git-Hosting-Plattform ohne Pull-Requests, einer spartanischen Weboberfläche und +einem mächtigen Buildsystem - so lässt sich Sourcehut am besten zusammenfassen. + +![SourceHut homepage](./assets/sourcehut/homepage.png) + +SourceHut begann im +[Oktober 2016](https://git.sr.ht/~sircmpwn/meta.sr.ht/commit/40dcb38349af3f67845857c4ac9003911a653624) +als Hobbyprojekt von Drew DeVault. Drew wollte eine alternative zu den etablierten +Git-Hosting-Diensten entwickeln, die den klassischen E-Mail-basierten Git-Workflow +unterstützt anstatt das Funktionsprinzip von GitHub zu kopieren. + +[2018](https://drewdevault.com/2018/11/15/sr.ht-general-availability.html) war die +Alpha-Version der Software öffentlich unter verfügbar. + +Die Plattform besteht aus einzelnen Komponenten für die verschiedenen Features: + +- meta.sr.ht (Login und Benutzerverwaltung) +- hub.sr.ht (Projektverwaltung) +- git.sr.ht / hg.sr.ht (Git/Mercurial Hosting) +- todo.sr.ht (Issues) +- lists.sr.ht (Mailinglisten) +- man.sr.ht (Wiki) +- paste.sr.ht (Pastebin) +- builds.sr.ht (Continuous Integration) +- pages.sr.ht (Statisches Webhosting) + +Jede dieser Komponentent besteht wiederum aus 2-3 Diensten: dem in Python/Flask +implementierten Webfrontend, einem in Go geschriebenen API-Server und eventuell noch +zusätzliche Dienste wie eine Task Queue. + +Jede Komponente legt ihre Daten in einer eigenen PostgreSQL-Datenbank ab. Zusätzlich +wird noch eine gemeinsame Redis-Instanz als Cache und Event Queue verwendet. + +Hier ist eine Übersicht über die einzelnen Dienste: + +![SourceHut architecture](./assets/sourcehut/sourcehut_arch.svg) + +## Installation + +Da Sourcehut aus mehreren Services für die einzelnen Features besteht, ist die +Einrichtung mit deutlich mehr Aufwand verbunden. Die Anleitung zur Installation findet +sich auf der [Dokumentationsseite](https://man.sr.ht/installation.md) des Projekts. +Allerdings ist diese Anleitung nicht vollständig und ich musste an einigen Stellen im +Quellcode der Software nachschlagen, wie bestimmte Features zu konfigurieren sind. + +Erschwerend kommt hinzu, dass Sourcehut an vielen Stellen keine aussagekräftigen +Fehlermeldungen liefert. Beispielsweise hatte ich das Problem, dass builds.sr.ht keine +VMs starten konnte, da diese standardmäßig mit 4GB RAM konfiguriert sind - zu viel für +meine Test-VM. Der einzige Fehler, der in diesem Fall auf der Webseite angezeigt wird, +ist der, dass das Build-System innerhalb einer bestimmten Zeit keine Verbindung zur VM +aufbauen konnte. Der OOM-Fehler beim Start wurde weder geloggt noch an den Nutzer +weitergegeben. + +Auf der Dokumentationsseite wird erwähnt, dass sich das Projekt noch im Alpha-Stadium +befindet, es ist also zu hoffen, dass die Dokumentation in Zukunft verbessert wird. + +Ich habe sämtliche Schritte, die zur Installation meiner Testinstanz erforderlich waren, +im [Anhang](sourcehut_setup.md) aufgelistet. + +## Systemanforderungen + +Sourcehut ist auf jedem System lauffähig, das Python 3.10 und Go unterstützt. Allerdings +sind die Pakete momentan nur für die amd64-Architektur verfügbar. Wer Sourcehut also auf +einem Raspberry Pi oder ARM-Server installieren will, muss die Pakete selbst +kompilieren. + +Die CPU-Auslastung im Leerlauf ist gering (ca. 1%). Bei aufwändigen Git-Operationen +sieht die Sache jedoch anders aus. Wenn man sich z.B. die Änderungshistorie der Makefile +des Linux-Kernels anzeigen lässt, läuft git.sr.ht 30 Sekunden lang mit 100% +CPU-Auslastung, bis Nginx die Anfrage wegen Zeitüberschreitung abbricht. Dieses Problem +lässt sich auch auf der offiziellen Instanz reproduzieren +([Link zum Testen](https://git.sr.ht/~gregkh/linux-stable/log/master/item/Makefile)). + +Zum Vergleich: Die Ausführung des Befehls `git --no-pager log Makefile | head -n 1000` +benötigte auf meinem Testsystem nur 100ms. + +Beim Arbeitsspeicherverbrauch macht sich die Microservice-Architektur negativ bemerkbar: +jeder Python-Dienst reserviert 90-100MB, die in Go geschriebenen API-Server kommen mit +20-30MB RAM aus. Da die gesamte Sourcehut-Installation aus 14 Python- und 8 Go-Services +besteht, summiert sich der Arbeitsspeicherbedarf auf ca. 1,5GB. + +## Bedienung + +Sourcehut's Weboberfläche ist spartanisch designt und kommt fast ohne JavaScript aus. +Dadurch ist die Webseite ohne Probleme in alten Geräten und Browsern benutzbar. + +Die Repository-Ansicht ist klar an GitWeb angelehnt und zeigt die Dateien ähnlich wie +der `ls -l`-Befehl zusammen mit Größe und Berechtigungen an. + +Genau wie GitWeb (und ls) platziert Sourcehut Ordner nicht vor Dateien, was das +Auffinden bestimmter Ordner unter vielen Dateien erschwert. + +Eine Suchfunktion gibt es nicht, dadurch ist es schwierig, auf der Webseite durch große +Projekte zu navigieren. + +Hinzu kommt, dass die Webseite nur Code und Markdown-Dokumente darstellen kann. Bilder, +PDF-Dokumente oder andere Markupsprachen wie RST werden nicht unterstützt. + +![Repository](./assets/sourcehut/repo.png) + +Die einzelnen Komponenten von Sourcehut sind eigenständige Webanwendungen. Dies hat den +Vorteil, dass man nur einen Teil von Sourcehut installieren kann, wenn man +beispielsweise den Build-Service oder die Mailinglisten nicht benötigt. Allerdings macht +diese Aufteilung die Bedienung an vielen Stellen hakelig. Es gibt zwar eine zentrale +Projektverwaltung (hub.sr.ht), die Repositories, Issue-Tracker und Mailinglisten zu +bestimmten Projekten zuordnet. Allerdings ist diese Verlinkung eine Einbahnstraße: von +der Projekseite auf dem Hub kann man alle zugehörigen Repositories, Issue-Tracker und +Mailinglisten aufrufen, befindet man sich aber bspw. in einem Repository, kann man das +zugehörige Projekt nicht ohne weiteres ermitteln. + +![SourceHut Hub](./assets/sourcehut/hub.png) Projektansicht im SourceHut Hub + +Sourcehut unterscheidet sich von GitHub und anderen Code-Hosting-Plattformen vor allem +dadurch, dass es zur Kollaboration zwischen Entwicklern keine Pull-Requests verwendet. +Stattdessen basiert das System auf den "klassischen" Git-Workflow, also dem Austausch +von Patches via E-Mail. Projekteigentümer können Mailinglisten einrichten und darüber +Patches empfangen. + +Dies hat den Vorteil, dass außenstehende Entwickler sich nicht auf der Plattform +registrieren müssen und ausschließlich via E-Mail mit den Maintainern des Projekts +kommunizieren können. + +Sourcehut bietet Entwicklern auch die Möglichkeit, über die Weboberfläche Patches zu +erstellen und zu versenden. Dazu muss man das Repository zuerst auf der Plattform +klonen, die eigenen Commits hochladen und diese anschießend in der Weboberfläche +auswählen. + +![Send patchset](./assets/sourcehut/send_patchset.png) + +Auch wenn dieser Workflow sicherlich Vorteile mit sich bringt, muss man feststellen, +dass dies für die meisten Entwickler ungewohnt und umständlich ist. Entwickler, die +bisher nur mit GitHub und ähnlichen Plattformen gearbeitet haben, werden beim Versuch, +zu einem Projekt beizutragen, eventuell auf Hindernisse stoßen. + +Es gibt auch ein CLI-Tool namens [hut](https://git.sr.ht/~emersion/hut), um die +verschiedenen Sourcehut-Dienste mit der Kommandozeile zu bedienen. Das Tool erlaubt das +Erstellen von Issues, Hochladen von Releases, Starten von Builds, Veröffentlichen von +Webseiten, Hinzufügen von SSH-Keys und einiges mehr. + +## Import bestehender Projekte + +Die Sourcehut-Weboberfläche erlaubt auf lediglich den Import von öffentlichen +Git-Repositories per clone. Es gibt keine Möglichkeit zum Import von Issues und +Pull-Requests werden wie oben erwähnt nicht unterstützt. + +## Zusatzfeatures + +Wie bereits beschrieben besteht Sourcehut aus einer Vielzahl von Diensten, den +Entwicklern neben Git-Hosting und Issue Tracking diverse Zusatzfeatures bieten. + +man.sr.ht ist ein auf Git basierendes Wiki, das in Markdown geschriebene +Dokumentationstexte darstellen kann. Allerdings bietet es kaum Features: der einzige +Unterschied zum Betrachten von Markdown-Dateien in git.sr.ht ist das +Seiteninhaltsverzeichnis, das man.sr.ht oben anfügt. Es gibt kein Inhaltsverzeichnis +über die gesamte Dokumentation, genauso wenig wie eine Suchfunktion. + +paste.sr.ht ist ein Pastebin zum Speichern und Veröffentlichen von kleineren Texten, +Skripten und Codeausschnitten. Man kann Pastes öffentlich oder privat speichern und es +gibt auch die Möglichkeit, Textdateien mit dem `hut`-CLI-Tool hochzuladen. + +pages.sr.ht ist ein Webhosting-Dienst, der es einem erlaubt, statische Webseiten unter +einer persönlichen Subdomain zu veröffentlichen. Hierfür muss man sämtliche Dateien als +`tar.gz`-Archiv komprimieren und anschließend mit dem `hut`-Tool hochladen. + +Das Issue-System von Sourcehut (todo.sr.ht) ist jedoch sehr rudimentär. Es gibt außer +Labels und der Möglichkeit, verantwortliche Personen zuzuweisen keine Zusatzfunktionen, +die das Projektmanagement erleichtern. Für größere Projekte ist daher die Verwendung +einer zusätzlichen Projektmanagement-Software wie Redmine nötig. + +## Continous Integration + +builds.sr.ht ist ein sehr leistungsfähiges und einfach zu verwendender CI-System. + +Builds können über die Weboberfläche, eine API oder durch Git-Pushes und auf der +Mailigliste eingegangene Patches initiiert werden. Zum Ausführen der Builds werden +virtuelle Maschinen (mit QEMU/KVM) gestartet, wodurch die Build-Umgebung vom Server +isoliert ist. + +QEMU erlaubt es auch, andere CPU-Architekturen zu emulieren und so beispielsweise +Embedded Linux-Anwendungen zu testen. + +![Erfolgreicher Build](./assets/sourcehut/successful_build.png) + +Sourcehut Builds werden durch +[yaml-Manifests](https://man.sr.ht/builds.sr.ht/manifest.md) beschrieben. Die Syntax ist +sehr simpel gehalten. Manifests bestehen aus dem Namen des VM-Images, den benötigten +Paketen und Repositories und einem oder mehreren Shell-Skripten. + +```yaml +image: alpine/latest +packages: + - cargo +sources: + - https://code.thetadev.de/ThetaDev/short-uuid.git +tasks: + - test: | + cd short-uuid + cargo test +``` + +Es gibt auch die Möglichkeit, für den Build benötige Secrets wie API-Keys und +SSH-Schlüssel zu hinterlegen. Die Secrets werden auf der Build-VM in Dateien abgelegt, +von wo aus sie in Buildskripten verwendet werden können (z.B. +`cargo publish --token "$(<~/.cargo-token)"`). Zudem gibt es die Möglichkeit, SSH- und +GPG-Schlüssel automatisch zu importieren. + +Ein besonderes Feature von builds.sr.ht ist die Möglichkeit, fehlgeschlagene Builds zu +analysieren. Schlägt ein Build fehl, läuft die entsprechende VM noch 10 Minuten weiter. +In dieser Zeit kann man sich per SSH mit dem Build-Server verbinden und kann Befehle in +der entsprechenden Build-VM ausführen. Auf diese Weise kann man Logdateien inspizieren +oder den Build mit Konfigurationsänderungen neu starten, ohne jedes Mal das +Buildmanifest zu ändern und neu zu übermitteln. + +![Fehlgeschlagener Build](./assets/sourcehut/failed_build.png) + +Allerdings bietet Sourcehut Builds nicht die Möglichkeit, zu spezifizieren, wann ein +Build ausgeführt werden soll. Builds werden immer dann gestartet, wenn ein Branch in +einem Repository aktualisiert wird, in dem sich eine `.builds.yml`-Datei befindet. +Eingehende Patches in der Mailingliste können ebenfalls einen Build startet. + +Es gibt jedoch keine Möglichkeit, Builds nur dann zu starten, wenn ein bestimmter Branch +oder bestimmte Dateien aktualisiert wurden. Dies kann beispielsweise in Monorepos +(Repositories mit mehreren Projekten) zu unnötig lange dauernden Builds führen. + +## Öffentliche Instanzen + +Die öffentliche Sourcehut-Instanz, die von Drew DeVault und seiner Firma betrieben wird, +befindet sich unter . + +sr.ht ist der einige mir bekannte Git-Hosting-Anbieter, der ein kostenpflichtiges +Abonnement für das Erstellen eigener Projekte erfordert. Solange sich Sourcehut im +Alpha-Stadium befindet, ist das Abo allerdings optional (außer für die Nutzung des +Build-Service). Das Abonnement kostet 20€ im Jahr, man kann auch auf freiwilliger Basis +bis zum 100€ bezahlen, um das Projekt zu unterstützen. + +Die kostenpflichtigen Mitgliedschaften erlauben Sourcehut, finanziell unabhängig zu sein +und nicht den Entscheidungen von Investoren unterworfen zu sein. Sourcehut +veröffentlicht seine jährlichen Einnahmen und Ausgaben auf ihrem Blog und gibt an, seit +2019 Profit zu erwirtschaften. + +Bekannte Projekte, die auf sr.ht gehostet werden sind das alternative Instagram-Frontend +[Bibliogram](https://sr.ht/~cadence/bibliogram/), +[microblog.pub](https://sr.ht/~tsileo/microblog.pub/), eine persönliche +Microblogging-Anwendung mit ActivityPub-Unterstützung und natürlich +[Sourcehut](https://sr.ht/~sircmpwn/sourcehut/) selbst. Insgesamt hostet sr.ht ca. 7100 +Projekte. + +Es gibt auch Open-Source-Projekte, die ihren Code auf anderen Plattformen hosten und nur +das Build-System von Sourcehut nutzen. Beispielsweise benutzt die Linux-Distribution +postmarketOS [Sourcehut Builds](https://build.postmarketos.org/) zum Bau ihrer Pakete. + +Wichtig ist noch zu erwähnen, dass die offizielle Sourcehut-Instanz keine Projekte +erlaubt, die mit +[Blockchain oder Kryptowährungen](https://sourcehut.org/blog/2022-10-31-tos-update-cryptocurrency/) +zu tun haben. Sourcehut begründet dies damit, dass Kryptowährungen häufig für Betrug und +andere Verbrechen eingesetzt werden und große Mengen an Ressourcen verschwenden. + +Abgesehen von der offiziellen Instanz gibt es sehr wenige weiterem öffentlichen +Sourcehut-Instanzen, was wohl auch dem komplizierten Einrichtungsprozess geschuldet ist. + +Es existiert eine Instanz unter [gnu.org](https://sourcehut.gnu.org), die sich +allerdings im Entwicklermodus befindet und über keine öffentlichen Projekte verfügt. Die +größte alternative Sourcehut-Instanz, die ich gefunden habe, ist +. Die Instanz wird von einer Webentwicklungsfirma +betrieben, beherbergt 9 öffentliche Projekte und erlaubt keine Registrierung von +Außenstehenden. + +## Fazit + +Das Highlight von sr.ht ist meiner Meinung nach der CI-Dienst. Während die meisten +anderen CI-Dienste an Repositories gekoppelt sind, erlaubt es Sourcehut, einfach ein +Build-Manifest mit dem CLI-Tool oder dem Formular auf der Website abzuschicken und +ausführen zu lassen. Die Möglichkeit fehlgeschlagene Builds zu analysieren ist ebenfalls +einzigartig. + +Allerdings ist die Einrichtung von Sourcehut sehr aufwändig und einige grundlegende +Features wie eine Suchfunktion fehlen weswegen ich das System in seinem momentanen +Zustand nicht empfehlen kann. + +Hinzu kommt, dass Sourcehut trotz seiner spartanischen Weboberfläche und seinem +reduziertem Funktionsumfang das System mit dem zweithöchsten Ressourcenverbrauch im Test +war. + +Da sich Sourcehut wie gesagt noch im Alpha-Stadium befindet, lohnt es sich jedoch das +Projekt weiter zu verfolgen. + +## Quellen + +- Projektseite +- Sourcehut Blog diff --git a/src/studienarbeit/5_onedev.md b/src/studienarbeit/5_onedev.md new file mode 100644 index 0000000..8394d68 --- /dev/null +++ b/src/studienarbeit/5_onedev.md @@ -0,0 +1,232 @@ +# OneDev + +Abschließen möchte ich meinen Test mit einer weitgehend unbekannten Plattform, die erst +2019 als Hobbyprojekt von zwei Entwicklern veröffentlicht wurde, sich aber in Sachen +Funktionalität nicht vor den anderen Plattformen verstecken muss: OneDev. + +![OneDev homepage](./assets/onedev/homepage.png) + +OneDev ist in Java geschrieben und verwendet das Webframework Apache Wicket. Das Projekt +wird hauptächlich von Robin Shen und Steve Luo entwickelt, insgesamt gibt es ca. 30 +Beitragende. Das Projekt ist unter der MIT-Lizenz veröffentlicht. + +Der +[erste Commit](https://code.onedev.io/onedev/server/~commits/6be8e3f97c97e44cf6b5a9b8360c299cc55388f6) +erfolgte im April 2012, die erste in Git getaggte Version (2.0.0) wurde 2019 +veröffentlicht. Rechnet man mit dem Datum des ersten Release, ist OneDev die jüngste der +vier Plattformen, die ich getestet habe. + +OneDev besteht aus einer einzigen Java-Anwendung und erfordert bei Verwendung der +eingebetteten HSQL-Datenbank keine zusätzlichen Dienste zum Betrieb. Es werden auch +externe Datenbanken (MySQL, MariaDB, Postgres, MS SQL, Oracle) unterstützt. + +Getestet wurde die Version 8.5.2. + +## Installation + +Die OneDev-Entwickler stellen Container-Images für OneDev zur Verfügung +(`docker.io/1dev/server`), mit denen sich OneDev einfach mittels Docker installieren +lässt. Alternativ gibt es auch die Möglichkeit, die Java-Anwendung direkt auf seinem +System zu installieren oder OneDev in einem Kubernetes-Cluster zu betreiben. + +Für den Installationsprozess gibt es eine Schritt-für-Schritt-Anleitung auf der +Dokumentationsseite des Projekts. Allerdings bin ich hiervon abgewichen, da in der +Installationsanleitung empfohlen wird, den Docker-Socket (`/var/run/docker.sock`) im +OneDev-Container als Volume einzubinden. + +Dies ist nur dann erforderlich, wenn der eingebaute _Server Docker Executor_ anstelle +eines externen Agents für CI-Jobs verwendet wird. + +Da Container mit Docker-Zugriff effektiv über Root-Rechte auf dem Hostsystem verfügen, +ist dies jedoch mit einem Sicherheitsrisiko verbunden. Deswegen empfehle ich, den +eingebauten Agent nicht zu nutzen und stattdessen den seperaten Agent-Container +(`docker.io/1dev/agent`) zu verwenden. Der CI-Agent sollte bei einem Produktionssetup +auf einem anderen Server bzw. einer anderen VM laufen, auf der sich keine wertvollen +oder sensiblen Daten befinden - insbesondere wenn nicht vertrauenswürdige Nutzer Zugriff +auf das CI-System haben. + +[Hier](./assets/onedev/docker-compose.yml) ist die Docker-Compose-Datei, die ich für +meine Testinstallation verwendet habe. + +Nach dem Start des Servers kann man auf der Weboberfläche den ersten Benutzeraccount +anlegen und die URL des Servers konfigurieren. + +Anschließend muss noch das CI-System eingerichtet werden. Hierzu öffnet man den +Menüpunkt _Administration_ \> _Agents_, klickt auf _Tokens_ und generiert sich einen +neuen Agent Token. Dieser Token muss dem Agent als Umgebungsvariable übergeben werden +(also z.B. in die Docker-Compose-Datei eintragen). Nach dem Start des Agents muss dieser +in der Tabelle sichtbar sein. + +![Agent setup](./assets/onedev/add_agent.png) + +Danach öffnet man den Menüpunkt _Job Executors_ und erstellt einen _Remote Docker +Executor_. Damit ist die Einrichtung des CI-Systems abgeschlossen und man kann den +ersten Build starten (siehe im Abschnitt +[Continuous Integration](#continous-integration)). + +Standardmäßig erlaubt OneDev nur angemeldeten Benutzern den Zugriff auf die Instanz. Um +seine Projekte öffentlich verfügbar zu machen, muss noch die Option _Security Settings_ +\> _Enable Anonymous Access_ aktiviert werden. + +## Systemanforderungen + +OneDev ist auf jedem System mit Java-Unterstützung lauffähig. Das offizielle +Docker-Image wird für die 64bit Interl/AMD und ARM-Architektur angeboten. + +Der Server benötigte auf meinem System ca. 1.2GB Arbeitsspeicher, der CI-Agent ca. +180MB. Die CPU-Auslastung im Leerlauf beträgt auf meinem System (AMD Ryzen 5700G) ca. +1%, mit gelegentlichen Spitzen auf 5-10%. + +Aufwändige Git-Operationen (History/Blame in großen Repositories) können Lastspitzen von +bis zu 100% mit einer Dauer von max. 2 Sekunden verursachen. Bei Nutzung der +Suchfunktion habe ich bis zu 50% Auslastung gemessen. + +## Bedienung + +OneDev verfügt über eine modern gestaltete Weboberfläche, die mit dem Webframework +Apache Wicket realisiert wurde. Das Framework lädt beim Navigieren nur die Teile der +Website vom Server, die sich durch den entsprechenden Navigationsschritt geändert haben +(also z.B. die Dateiliste). + +Dadurch geht das Navigieren durch die Repositories sehr flüssig vonstatten, ohne dass +die gesamte Seite neu geladen werden muss. + +Ein Alleinstellungsmerkmal von OneDev ist die Suchfunktion. OneDev verwendet nicht nur +eine Textsuchmaschine, sondern analysiert den Code im Repository und bietet so die +Möglichkeit, nach Klassen und Funktionen zu suchen. Die Suchergebnisse werden während +dem Tippen angezeigt. Auf diese Weise kann man schnell durch komplexe Softwareprojekte +navigieren. + +![Suche](./assets/onedev/search.png) + +Die Suche kann auch über ein Kontextmenü in der Code-Ansicht aufgrufen werden. Auf diese +Weise kann man nach Definitionen oder Verwendungen von Funktionen suchen. Es gibt auch +eine Übersicht aller Klassen und Funktionen einer Datei auf der rechten Seite. + +Die Code-Analyse ist für die Sprachen Java, JavaScript, C, C++, CSharp, Go, PHP, Python, +CSS, SCSS, LESS und R verfügbar. Rust wird leider nicht unterstützt. + +![Code-Navigation](./assets/onedev/code_navigation.png) + +OneDev kann auf der Weboberfläche Code, Markdown-Dokumente und Bilder darstellen. Es +gibt keine Unterstützung für alternative Markupsprachen wie RST. + +## Import bestehender Projekte + +OneDev bietet einen Import-Assistenten mit Unterstützung für GitHub, Gitlab, BitBucket, +und Gitea. Neben dem Git-Repository werden auch Metadaten und Issues übertragen. + +Der Importer erlaubt es auch, nach einer Authentifizierung per API-Key sämtliche +Projekte eines Nutzers oder einer Organisation zu übertragen, was beim Umstieg viel Zeit +sparen kann. + +Es gibt jedoch nicht die Möglichkeit, Projekte aus anderen OneDev-Instanzen zu +übertragen. + +## Zusatzfeatures + +OneDev verfügt über umfangreiche Tools zum Projektmanagement. Es gibt die Möglichkeit, +Issues zu Meilensteinen zuzuordnen (z.B. _Sprint 14_ oder _Version 2.0_). Zudem verfügt +OneDev über Issue Boards, um Issues je nach Status in mehreren Spalten anzuzeigen. + +![OneDev Issue Board](./assets/onedev/kanban.png) + +Issues können bestimmten Entwicklern zugewiesen werden und es gibt die Möglichkeit, +Abhängigkeiten zwischen Issues zu definieren (z.B. Issue A muss vor Issue B erledigt +werden). Was allerdings fehlt ist die Möglichkeit, einem Issue mehrere Labels +zuzuordnen. + +OneDev bietet auch die Möglichkeit, statische Webseiten zu hosten. Hierfür ist im +Gegensatz zu Gitlab Pages keine separate Domain nötig. Stattdessen wird die Webseite im +Unterverzeichnis `~site` des Repositorys (z.B. `https://example.com/user/repo/~site`) +veröffentlicht. + +Als einzige getestete Plattform verfügt OneDev über ein Plugin-System. Auf diese Weise +lassen sich neue Features implementieren, ohne die Software verändern zu müssen. +Beispielsweise gibt es ein Plugin zum +[Import von Issues](https://github.com/DevCharly/onedev-plugin-import-redmine/) aus der +Projektmanagement-Anwendung Redmine. + +Weitere Zusatzfeatures wie Paketmanagement bietet OneDev nicht. Darüber hinaus fehlt die +Möglichkeit, Releases seiner Software hochzuladen und mit Git-Tags zu verknüpfen. Dieses +Feature beherrschen ansonsten alle getesteten Plattformen. + +## Continous Integration + +OneDev bietet ein eingebautes CI-System um Projekte zu kompilieren und zu testen. Die +Jobs können in Docker-Containern, Kubernetes-Pods oder bare metal ausgeführt werden. + +Jobs werden in einer yml-Datei definiert, die als `.onedev-buildspec.yml` im +Wurzelverzeichnis des Repositories abgelegt werden muss. + +OneDev bietet jedoch auch eine Weboberfläche, um Builds zu erstellen und zu bearbeiten. +Auf diese Weise muss man nicht zuerst die yaml-Syntax erlernen, um das CI-System zu +nutzen. Über die Weboberfläche lassen sich bestimmte Aktionen (z.B. "Befehle ausführen", +"Docker Image bauen", "Webseite veröffentlichen") auswählen und konfigurieren. + +![CI-Editor](./assets/onedev/ci_editor.png) + +```yml +version: 23 +jobs: + - name: test + steps: + - !CheckoutStep + name: checkout + cloneCredential: !DefaultCredential {} + withLfs: false + withSubmodules: false + condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL + - !CommandStep + name: build + runInContainer: true + image: rust:latest + interpreter: !DefaultInterpreter + commands: + - rustup component add rustfmt clippy + - cargo fmt --all --check + - cargo clippy --all --features=rss -- -D warnings + - cargo test --features=rss --workspace + useTTY: false + condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL + triggers: + - !BranchUpdateTrigger {} + - !PullRequestUpdateTrigger {} + retryCondition: never + maxRetries: 3 + retryDelay: 30 + timeout: 3600 +``` + +Die Builds können durch Branch Updates oder neue Pull Requests ausgelöst werden. Es gibt +auch die Möglichkeit, Builds zeitgesteuert oder manuell zu starten. + +## Öffentliche Instanzen + +Das OneDev-Team betreibt ihre eigene Instanz unter +[code.onedev.io](https://code.onedev.io). Allerdings verbietet diese Instanz das +erstellen eigener Projekte und dient nur der Entwicklung und Demonstration der +Plattform. + +Darüber hinaus habe ich außer einer kleinen privaten Instanz names +["Winux Projects"](https://projects.winux.it/) keine öffentlichen Instanzen gefunden, +was sicher auch daran liegt, dass das Projekt momentan noch relativ unbekannt ist. + +## Fazit + +Obwohl OneDev noch relativ jung und weitgehend unbekannt ist, kann es funktional +durchaus mit den Konkurrenten mithalten. Insbesondere die intelligente Suchfunktion und +das einfach zu bedienende CI-System haben mir im Test sehr gut gefallen. + +Allerdings ist OneDev immer noch ein Hobbyprojekt von 2 Entwicklern und hat keine Firma +oder größere Organisation hinter sich. Wer OneDev beispielsweise in einem Unternehmen +einsetzen möchte, muss die Einrichtung und den Support selbst übernehmen, da es im +Gegensatz zu GitLab und Gitea keine öffentlichen Instanzen oder SaaS-Angebote gibt. + +Wer sich hieran nicht stört, erhält mit OneDev eine leichtgewichtige, einfach zu +installierende und moderne Git-Hosting-Plattform. + +## Quellen + +- Projektseite +- Repository diff --git a/src/studienarbeit/assets/gitea/actions.png b/src/studienarbeit/assets/gitea/actions.png new file mode 100644 index 0000000..3a6d89c Binary files /dev/null and b/src/studienarbeit/assets/gitea/actions.png differ diff --git a/src/studienarbeit/assets/gitea/homepage.png b/src/studienarbeit/assets/gitea/homepage.png new file mode 100644 index 0000000..27cf819 Binary files /dev/null and b/src/studienarbeit/assets/gitea/homepage.png differ diff --git a/src/studienarbeit/assets/gitea/search.png b/src/studienarbeit/assets/gitea/search.png new file mode 100644 index 0000000..bccbde9 Binary files /dev/null and b/src/studienarbeit/assets/gitea/search.png differ diff --git a/src/studienarbeit/assets/gitea/setup.png b/src/studienarbeit/assets/gitea/setup.png new file mode 100644 index 0000000..b259dc3 Binary files /dev/null and b/src/studienarbeit/assets/gitea/setup.png differ diff --git a/src/studienarbeit/assets/gitea/woodpecker.png b/src/studienarbeit/assets/gitea/woodpecker.png new file mode 100644 index 0000000..cc72833 Binary files /dev/null and b/src/studienarbeit/assets/gitea/woodpecker.png differ diff --git a/src/studienarbeit/assets/gitlab/architecture.png b/src/studienarbeit/assets/gitlab/architecture.png new file mode 100644 index 0000000..dcdb9d7 Binary files /dev/null and b/src/studienarbeit/assets/gitlab/architecture.png differ diff --git a/src/studienarbeit/assets/gitlab/docker-compose.yml b/src/studienarbeit/assets/gitlab/docker-compose.yml new file mode 100644 index 0000000..10c3fb3 --- /dev/null +++ b/src/studienarbeit/assets/gitlab/docker-compose.yml @@ -0,0 +1,21 @@ +version: "3.6" +services: + web: + image: "gitlab/gitlab-ce:latest" + restart: unless-stopped + environment: + GITLAB_OMNIBUS_CONFIG: | + external_url 'http://localhost:8001' + nginx['listen_https'] = false + nginx['listen_port'] = 80 + nginx['redirect_http_to_https'] = false + letsencrypt['enable'] = false + GITLAB_ROOT_PASSWORD: secret1234 + ports: + - "8001:80" + - "2222:22" + volumes: + - "./config:/etc/gitlab" + - "./logs:/var/log/gitlab" + - "./data:/var/opt/gitlab" + shm_size: "256m" diff --git a/src/studienarbeit/assets/gitlab/import.png b/src/studienarbeit/assets/gitlab/import.png new file mode 100644 index 0000000..91318ff Binary files /dev/null and b/src/studienarbeit/assets/gitlab/import.png differ diff --git a/src/studienarbeit/assets/gitlab/issue.png b/src/studienarbeit/assets/gitlab/issue.png new file mode 100644 index 0000000..3fb10e8 Binary files /dev/null and b/src/studienarbeit/assets/gitlab/issue.png differ diff --git a/src/studienarbeit/assets/gitlab/kanban.png b/src/studienarbeit/assets/gitlab/kanban.png new file mode 100644 index 0000000..ba830d6 Binary files /dev/null and b/src/studienarbeit/assets/gitlab/kanban.png differ diff --git a/src/studienarbeit/assets/gitlab/runners.png b/src/studienarbeit/assets/gitlab/runners.png new file mode 100644 index 0000000..7af0ac4 Binary files /dev/null and b/src/studienarbeit/assets/gitlab/runners.png differ diff --git a/src/studienarbeit/assets/gitlab/web_ide.png b/src/studienarbeit/assets/gitlab/web_ide.png new file mode 100644 index 0000000..315d302 Binary files /dev/null and b/src/studienarbeit/assets/gitlab/web_ide.png differ diff --git a/src/studienarbeit/assets/onedev/add_agent.png b/src/studienarbeit/assets/onedev/add_agent.png new file mode 100644 index 0000000..de4ef57 Binary files /dev/null and b/src/studienarbeit/assets/onedev/add_agent.png differ diff --git a/src/studienarbeit/assets/onedev/build.png b/src/studienarbeit/assets/onedev/build.png new file mode 100644 index 0000000..5edff29 Binary files /dev/null and b/src/studienarbeit/assets/onedev/build.png differ diff --git a/src/studienarbeit/assets/onedev/ci_editor.png b/src/studienarbeit/assets/onedev/ci_editor.png new file mode 100644 index 0000000..215d921 Binary files /dev/null and b/src/studienarbeit/assets/onedev/ci_editor.png differ diff --git a/src/studienarbeit/assets/onedev/code_navigation.png b/src/studienarbeit/assets/onedev/code_navigation.png new file mode 100644 index 0000000..b4d6315 Binary files /dev/null and b/src/studienarbeit/assets/onedev/code_navigation.png differ diff --git a/src/studienarbeit/assets/onedev/docker-compose.yml b/src/studienarbeit/assets/onedev/docker-compose.yml new file mode 100644 index 0000000..c35eabe --- /dev/null +++ b/src/studienarbeit/assets/onedev/docker-compose.yml @@ -0,0 +1,19 @@ +version: "3" +services: + onedev: + image: 1dev/server:latest + ports: + - 6610:6610 + - 6611:6611 + volumes: + - ./data:/opt/onedev + agent: + image: 1dev/agent:latest + environment: + - "serverUrl=http://onedev:6610" + - "agentToken=3922e711-8a7f-4dd0-8b68-fd3ca891ffff" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./work:/agent/work + depends_on: + - onedev diff --git a/src/studienarbeit/assets/onedev/homepage.png b/src/studienarbeit/assets/onedev/homepage.png new file mode 100644 index 0000000..e577248 Binary files /dev/null and b/src/studienarbeit/assets/onedev/homepage.png differ diff --git a/src/studienarbeit/assets/onedev/kanban.png b/src/studienarbeit/assets/onedev/kanban.png new file mode 100644 index 0000000..027163e Binary files /dev/null and b/src/studienarbeit/assets/onedev/kanban.png differ diff --git a/src/studienarbeit/assets/onedev/search.png b/src/studienarbeit/assets/onedev/search.png new file mode 100644 index 0000000..1df4329 Binary files /dev/null and b/src/studienarbeit/assets/onedev/search.png differ diff --git a/src/studienarbeit/assets/sourcehut/failed_build.png b/src/studienarbeit/assets/sourcehut/failed_build.png new file mode 100644 index 0000000..71e8dd2 Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/failed_build.png differ diff --git a/src/studienarbeit/assets/sourcehut/homepage.png b/src/studienarbeit/assets/sourcehut/homepage.png new file mode 100644 index 0000000..10d0d46 Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/homepage.png differ diff --git a/src/studienarbeit/assets/sourcehut/hub.png b/src/studienarbeit/assets/sourcehut/hub.png new file mode 100644 index 0000000..faabd0e Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/hub.png differ diff --git a/src/studienarbeit/assets/sourcehut/oauth.png b/src/studienarbeit/assets/sourcehut/oauth.png new file mode 100644 index 0000000..3ae6499 Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/oauth.png differ diff --git a/src/studienarbeit/assets/sourcehut/oauth_new_client.png b/src/studienarbeit/assets/sourcehut/oauth_new_client.png new file mode 100644 index 0000000..efdbdc7 Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/oauth_new_client.png differ diff --git a/src/studienarbeit/assets/sourcehut/repo.png b/src/studienarbeit/assets/sourcehut/repo.png new file mode 100644 index 0000000..1f7629c Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/repo.png differ diff --git a/src/studienarbeit/assets/sourcehut/send_patchset.png b/src/studienarbeit/assets/sourcehut/send_patchset.png new file mode 100644 index 0000000..43ca636 Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/send_patchset.png differ diff --git a/src/studienarbeit/assets/sourcehut/sourcehut.dio b/src/studienarbeit/assets/sourcehut/sourcehut.dio new file mode 100644 index 0000000..df756ce --- /dev/null +++ b/src/studienarbeit/assets/sourcehut/sourcehut.dio @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/studienarbeit/assets/sourcehut/sourcehut.png b/src/studienarbeit/assets/sourcehut/sourcehut.png new file mode 100644 index 0000000..8d7c4e7 Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/sourcehut.png differ diff --git a/src/studienarbeit/assets/sourcehut/sourcehut_arch.svg b/src/studienarbeit/assets/sourcehut/sourcehut_arch.svg new file mode 100644 index 0000000..eb31e5c --- /dev/null +++ b/src/studienarbeit/assets/sourcehut/sourcehut_arch.svg @@ -0,0 +1 @@ +
Frontend
:5000
Frontend...
API
:5100
API...
meta.sr.ht
(Nutzerverwaltung)
meta.sr.ht...
Webhooks
(Queue)
Webhooks...
Frontend
:5014
Frontend...
API
:5114
API...
hub.sr.ht
(Startseite)
hub.sr.ht...
Frontend
:5001
Frontend...
API
:5101
API...
git.sr.ht
(Nutzerverwaltung)
git.sr.ht...
Webhooks
(Queue)
Webhooks...
Frontend
:5004
Frontend...
API
:5104
API...
man.sr.ht
(Wiki)
man.sr.ht...
Frontend
:5002
Frontend...
API
:5102
API...
builds.sr.ht
(CI)
builds.sr....
Worker
Worker
Worker
Worker
Frontend
:5011
Frontend...
API
:5111
API...
paste.sr.ht
(Wiki)
paste.sr.h...
Frontend
:5006
Frontend...
API
:5106
API...
lists.sr.ht
(Mailinglisten)
lists.sr.h...
Process
(Queue)
Process...
LMTP
LMTP
Frontend
:5003
Frontend...
API
:5103
API...
todo.sr.ht
(Issues)
todo.sr.ht...
Webhooks
(Queue)
Webhooks...
LMTP
LMTP
Webhooks
(Queue)
Webhooks...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/src/studienarbeit/assets/sourcehut/successful_build.png b/src/studienarbeit/assets/sourcehut/successful_build.png new file mode 100644 index 0000000..edceae8 Binary files /dev/null and b/src/studienarbeit/assets/sourcehut/successful_build.png differ diff --git a/src/studienarbeit/assets/sourcehut_setup/config.ini b/src/studienarbeit/assets/sourcehut_setup/config.ini new file mode 100644 index 0000000..09f1155 --- /dev/null +++ b/src/studienarbeit/assets/sourcehut_setup/config.ini @@ -0,0 +1,523 @@ +[sr.ht] +# The name of your network of sr.ht-based sites +site-name=sourcehut +# +# The top-level info page for your site +site-info=https://sourcehut.org +# +# {{ site-name }}, {{ site-blurb }} +site-blurb=the hacker's forge +# +# If this != production, we add a banner to each page +environment=production +# +# Contact information for the site owners +owner-name=Drew DeVault +owner-email=sir@cmpwn.com +# +# The source code for your fork of sr.ht +source-url=https://git.sr.ht/~sircmpwn/srht +# +# Link to your instance's privacy policy. Uses the sr.ht privacy policy as the +# default, which describes the information collected by the upstream SourceHut +# code. +privacy-policy= +# +# A key used for encrypting session cookies. Use `srht-keygen service` to +# generate the service key. This must be shared between each node of the same +# service (e.g. git1.sr.ht and git2.sr.ht), but different services may use +# different keys. If you configure all of your services with the same +# config.ini, you may use the same service-key for all of them. +service-key=9654c9ec7bedab6321a7f29f8b1b607ba023ddb9e248a67e10c49122e59a335f +# +# A secret key to encrypt internal messages with. Use `srht-keygen network` to +# generate this key. It must be consistent between all services and nodes. +network-key=iZnfEOgNVuCw6uGPQx1LE6eKVd20GXnd9IgCD3wxKJA= +# +# The redis host URL. This is used for caching and temporary storage, and must +# be shared between nodes (e.g. git1.sr.ht and git2.sr.ht), but need not be +# shared between services. It may be shared between services, however, with no +# ill effect, if this better suits your infrastructure. +redis-host=redis://localhost:6379 +# +# Optional email address for reporting security-related issues. +security-address= +# +# The global domain of the site. If unset, the global domain will be determined +# from the service URL: each service is assumed to be a sub-domain of the global +# domain, i.e. of the form `meta.globaldomain.com`. +global-domain=codeforge.int + +[mail] +# Outgoing SMTP settings +smtp-host= +smtp-port= +smtp-from=user@example.org +# +# Default: starttls +# Options: starttls, tls, insecure +smtp-encryption=tls +# +# Default: plain +# Options: plain, none +smtp-auth=plain +# user / password are required if smtp-auth is plain +smtp-user=user@example.org +smtp-password=pass + +pgp-privkey=/etc/sr.ht/gpg/privkey.gpg +pgp-pubkey=/etc/sr.ht/gpg/pubkey.gpg +pgp-key-id=E77640E3C9BA474C9C0791547298D360EE7DB9B4 + +[webhooks] +# +# base64-encoded Ed25519 key for signing webhook payloads. This should be +# consistent between all services. +# +# Use the `srht-keygen webhook` command to generate this key. Put the private +# key here and distribute the public key to anyone who would want to verify +# webhook payloads from your service. +private-key=FMCFMBL9HX3OHkYFoDUetJzxNfHw0vwWgLFKACXdoCY= + +[meta.sr.ht] +# +# URL meta.sr.ht is being served at (protocol://domain) +origin=http://meta.codeforge.int +# Address and port to bind the debug server to +# debug-host=127.0.0.1 +# debug-port=5000 +# +# Configures the SQLAlchemy connection string for the database. +connection-string=postgresql://meta:1234@localhost/meta.sr.ht?sslmode=disable +# +# Set to "yes" to automatically run migrations on package upgrade. +migrate-on-upgrade=yes +# +# The redis connection used for the webhooks worker +webhooks=redis://localhost:6379/1 +# +# If "yes", the user will be sent the stock sourcehut welcome emails after +# signup (requires cron to be configured properly). These are specific to the +# sr.ht instance so you probably want to patch these before enabling this. +welcome-emails=no + +# +# Origin URL for the API +# By default, the API port is 100 more than the web port +api-origin=http://localhost:5100 + +[meta.sr.ht::api] +# +# Maximum complexity of GraphQL queries. The higher this number, the more work +# that API clients can burden the API backend with. Complexity is equal to the +# number of discrete fields which would be returned to the user. 200 is a good +# default. +max-complexity=200 + +# +# The maximum time the API backend will spend processing a single API request. +# +# See https://golang.org/pkg/time/#ParseDuration +max-duration=3s + +# +# Set of IP subnets which are permitted to utilize internal API +# authentication. This should be limited to the subnets from which your +# *.sr.ht services are running. +# +# Comma-separated, CIDR notation. +internal-ipnet=127.0.0.0/8,::1/128,192.168.0.0/16,10.0.0.0/8 + +[meta.sr.ht::settings] +# +# If "no", public registration will not be permitted. +registration=yes +# +# Where to redirect new users upon registration +onboarding-redirect=http://codeforge.int + +[meta.sr.ht::aliases] +# +# You can add aliases for the client IDs of commonly used OAuth clients here. +# +# Example: +# git.sr.ht=12345 + +[meta.sr.ht::billing] +# +# "yes" to enable the billing system +enabled=no +# +# Get your keys at https://dashboard.stripe.com/account/apikeys +stripe-public-key= +stripe-secret-key= + +[meta.sr.ht::auth] +# +# What authentication method to use. +# builtin: use sr.ht builtin authentication +# unix-pam: use Unix PAM authentication +auth-method=builtin + +[hub.sr.ht] +# +# URL hub.sr.ht is being served at (protocol://domain) +origin=http://codeforge.int +# +# Address and port to bind the debug server to +# debug-host=127.0.0.1 +# debug-port=5014 +# +# Configures the SQLAlchemy connection string for the database. +connection-string=postgresql://hub:1234@localhost/hub.sr.ht?sslmode=disable +# +# Set to "yes" to automatically run migrations on package upgrade. +migrate-on-upgrade=yes +# +# hub.sr.ht's OAuth client ID and secret for meta.sr.ht +# Register your client at meta.example.org/oauth +oauth-client-id=712f709b315e4441 +oauth-client-secret=a186072ee9900662841188857777f44f + +[git.sr.ht] +# +# URL git.sr.ht is being served at (protocol://domain) +origin=http://git.codeforge.int +# +# Address and port to bind the debug server to +#debug-host=0.0.0.0 +#debug-port=5001 +# +# Configures the SQLAlchemy connection string for the database. +connection-string=postgresql://git:1234@localhost/git.sr.ht?sslmode=disable +# +# Set to "yes" to automatically run migrations on package upgrade. +migrate-on-upgrade=yes +# +# The redis connection used for the webhooks worker +webhooks=redis://localhost:6379/1 +# +# A post-update script which is installed in every git repo. +post-update-script=/usr/bin/gitsrht-update-hook +# +# git.sr.ht's OAuth client ID and secret for meta.sr.ht +# Register your client at meta.example.org/oauth +oauth-client-id=33e27e614a5a6c99 +oauth-client-secret=e128d76adb42d64290381facab1a9db1 +# +# Path to git repositories on disk +repos=/var/lib/git/ +# +# Configure the S3 bucket and prefix for object storage. Leave empty to disable +# object storage. Bucket is required to enable object storage; prefix is +# optional. +#s3-bucket= +#s3-prefix= +# +# Required for preparing and sending patchsets from git.sr.ht +outgoing-domain= + +# +# Origin URL for the API +# Only needed if not run behind a reverse proxy, e.g. for local development. +# By default, the API port is 100 more than the web port +#api-origin=http://localhost:5101 + +[git.sr.ht::api] +# +# Maximum complexity of GraphQL queries. The higher this number, the more work +# that API clients can burden the API backend with. Complexity is equal to the +# number of discrete fields which would be returned to the user. 200 is a good +# default. +max-complexity=200 + +# +# The maximum time the API backend will spend processing a single API request. +# +# See https://golang.org/pkg/time/#ParseDuration +max-duration=3s + +# +# Set of IP subnets which are permitted to utilize internal API +# authentication. This should be limited to the subnets from which your +# *.sr.ht services are running. +# +# Comma-separated, CIDR notation. +internal-ipnet=127.0.0.0/8,::1/128,192.168.0.0/16,10.0.0.0/8 + +[git.sr.ht::dispatch] +# +# The authorized keys hook uses this to dispatch to various handlers +# The format is a program to exec into as the key, and the user to match as the +# value. When someone tries to log in as this user, this program is executed +# and is expected to omit an AuthorizedKeys file. +# +# Uncomment the relevant lines to enable the various sr.ht dispatchers. +/usr/bin/gitsrht-keys=git:git +/usr/bin/buildsrht-keys=builds:builds + +[todo.sr.ht] +# +# URL todo.sr.ht is being served at (protocol://domain) +origin=http://todo.codeforge.int +# +# Address and port to bind the debug server to +#debug-host=0.0.0.0 +#debug-port=5003 +# +# Configures the SQLAlchemy connection string for the database. +connection-string=postgresql://todo:1234@localhost/todo.sr.ht?sslmode=disable +# +# Set to "yes" to automatically run migrations on package upgrade. +migrate-on-upgrade=yes +# +# todo.sr.ht's OAuth client ID and secret for meta.sr.ht +# Register your client at meta.example.org/oauth +oauth-client-id=215b592aa1e401b6 +oauth-client-secret=05f0d7ba973c6e4f2e0b5c95f00510f4 +# +# Outgoing email for notifications generated by users +notify-from=user@example.org +# +# The redis connection used for the webhooks worker +webhooks=redis://localhost:6379/1 +# +# Origin URL for the API +# Only needed if not run behind a reverse proxy, e.g. for local development. +# By default, the API port is 100 more than the web port +#api-origin=http://localhost:5103 + +[todo.sr.ht::mail] +# +# Path for the lmtp daemon's unix socket. Direct incoming mail to this socket. +# Alternatively, specify IP:PORT and an SMTP server will be run instead. +sock=/tmp/todo.sr.ht-lmtp.sock +# +# The lmtp daemon will make the unix socket group-read/write for users in this +# group. +sock-group=postfix +# +# Fill this in with the name of the domain to which emails should be sent. +# Leave blank to disable email submission. +posting-domain= + +[lists.sr.ht] +# +# URL lists.sr.ht is being served at (protocol://domain) +origin=http://lists.codeforge.int +# +# Address and port to bind the debug server to +#debug-host=0.0.0.0 +#debug-port=5006 +# +# Configures the SQLAlchemy connection string for the database. +connection-string=postgresql://lists:1234@localhost/lists.sr.ht?sslmode=disable +# +# Set to "yes" to automatically run migrations on package upgrade. +migrate-on-upgrade=yes +# +# The redis connection used for the webhooks worker +webhooks=redis://localhost:6379/1 +# +# The redis connection used for the Celery worker (configure this on both the +# master and workers) +redis=redis://localhost:6379/0 +# +# The domain that incoming email should be sent to. Forward mail sent here to +# the LTMP socket. +posting-domain=lists.codeforge.int +# +# lists.sr.ht's OAuth client ID and secret for meta.sr.ht +# Register your client at meta.example.org/oauth +oauth-client-id=95b6e656251e01f9 +oauth-client-secret=c6a53f7ac6e242dcbae198b738ce9c9a +# +# Trusted upstream SMTP server generating Authentication-Results header fields +msgauth-server=mail.sr.ht.local +# +# If "no", prevents non-admins from creating new lists +allow-new-lists=yes +# +# Origin URL for the API +# Only needed if not run behind a reverse proxy, e.g. for local development. +# By default, the API port is 100 more than the web port +#api-origin=http://localhost:5106 + +[lists.sr.ht::worker] +# Protocol used by the daemon. Either lmtp or smtp. By default ltmp if using +# unix socket and smtp if using tcp socket. +protocol=lmtp +# +# Path for the lmtp daemon's unix socket. Direct incoming mail to this socket. +# Alternatively, specify IP:PORT will run the server using tcp. +sock=/tmp/lists.sr.ht-lmtp.sock +# +# The lmtp daemon will make the unix socket group-read/write for users in this +# group. +sock-group=postfix +# +# Comma-delimited list of Content-Types to reject. Messages with Content-Types +# included in this list are rejected. Multipart messages are always supported, +# and each part is checked against this list. +# +# Uses fnmatch for wildcard expansion. +reject-mimetypes= +# +# Link to include in the rejection message where senders can get help +# correcting their email. +reject-url=https://man.sr.ht/lists.sr.ht/etiquette.md + +[lists.sr.ht::api] +# +# Maximum complexity of GraphQL queries. The higher this number, the more work +# that API clients can burden the API backend with. Complexity is equal to the +# number of discrete fields which would be returned to the user. 200 is a good +# default. +max-complexity=200 + +# +# The maximum time the API backend will spend processing a single API request. +# +# See https://golang.org/pkg/time/#ParseDuration +max-duration=90s + +# +# Set of IP subnets which are permitted to utilize internal API +# authentication. This should be limited to the subnets from which your +# *.sr.ht services are running. +# +# Comma-separated, CIDR notation. +internal-ipnet=127.0.0.0/8,::1/128,192.168.0.0/16,10.0.0.0/8 + +[lists.sr.ht::redirects] +# +# Redirects for migrating old mailing lists to new ones. This just sets up the +# redirect for incoming emails. +# +# old-address=~example/new-name + +[man.sr.ht] +# +# URL man.sr.ht is being served at (protocol://domain) +origin=http://man.codeforge.int +# +# Address and port to bind the debug server to +#debug-host=0.0.0.0 +#debug-port=5004 +# +# Configures the SQLAlchemy connection string for the database. +connection-string=postgresql://man:1234@localhost/man.sr.ht?sslmode=disable +# +# Set to "yes" to automatically run migrations on package upgrade. +migrate-on-upgrade=yes +# +# man.sr.ht's OAuth client ID and secret for meta.sr.ht +# Register your client at meta.example.org/oauth +oauth-client-id=96319d48a50cdfe5 +oauth-client-secret=e405e716b052402c88035c6ab429e6d3 + +[builds.sr.ht] +# +# URL builds.sr.ht is being served at (protocol://domain) +origin=http://builds.codeforge.int +# +# Address and port to bind the debug server to +#debug-host=0.0.0.0 +#debug-port=5002 +# +# Configures the SQLAlchemy connection string for the database. +connection-string=postgresql://builds:1234@localhost/builds.sr.ht?sslmode=disable +# +# Set to "yes" to automatically run migrations on package upgrade. +migrate-on-upgrade=yes +# +# The redis connection used for the Celery worker (configure this on both the +# master and workers) +redis=redis://localhost:6379/0 +# +# builds.sr.ht's OAuth client ID and secret for meta.sr.ht +# Register your client at meta.example.org/oauth +oauth-client-id=ecfda530d17ae5c3 +oauth-client-secret=68176355b4de8865163748e0a1ec1551 +# +# Script used to launch on ssh connnection. /usr/bin/master-shell on master, +# /usr/bin/runner-shell for workers. +# If master and worker are on the same system set to /usr/bin/runner-shell +shell=/usr/bin/runner-shell +# +# Set to "yes" to allow nonpaying users to submit builds +allow-free=yes +# +# Origin URL for the API +# Only needed if not run behind a reverse proxy, e.g. for local development. +# By default, the API port is 100 more than the web port +#api-origin=http://localhost:5102 + +# +# These config options are only necessary for systems running a build runner +[builds.sr.ht::worker] +# +# Name of this build runner (with HTTP port if not 80) +name=runner.codeforge.int +# +# Path to write build logs +buildlogs=/var/log/builds +# +# Path to the build images +images=/var/lib/images +# +# In production you should NOT put the build user in the docker group. Instead, +# make a scratch user who is and write a sudoers or doas.conf file that allows +# them to execute just the control command, then update this config option. For +# example: +# +# doas -u docker /var/lib/images/control +# +# Assuming doas.conf looks something like this: +# +# permit nopass builds as docker cmd /var/lib/images/control +# +# For more information about the security model of builds.sr.ht, visit the wiki: +# +# https://man.sr.ht/builds.sr.ht/installation.md +controlcmd=sudo -u docker /var/lib/images/control +# +# Max build duration. See https://golang.org/pkg/time/#ParseDuration +timeout=45m +# +# Http bind address for serving local build information/monitoring +bind-address=127.0.0.1:8080 +# +# Build trigger email +trigger-from=user@example.org +# +# Configure the S3 bucket and prefix for object storage. Leave empty to disable +# object storage. Bucket is required to enable object storage; prefix is +# optional. +s3-bucket= +s3-prefix= + +[paste.sr.ht] +# +# URL paste.sr.ht is being served at (protocol://domain) +origin=http://paste.codeforge.int +# +# Address and port to bind the debug server to +#debug-host=0.0.0.0 +#debug-port=5011 +# +# Configures the SQLAlchemy connection string for the database. +connection-string=postgresql://paste:1234@localhost/paste.sr.ht?sslmode=disable +# +# Set to "yes" to automatically run migrations on package upgrade. +migrate-on-upgrade=yes +# +# paste.sr.ht's OAuth client ID and secret for meta.sr.ht +# Register your client at meta.example.org/oauth +oauth-client-id=b930097f0d5666fb +oauth-client-secret=ee749b58b1ff808f3bc095a7e5ea4f9a +# +# Origin URL for the API +# Only needed if not run behind a reverse proxy, e.g. for local development. +# By default, the API port is 100 more than the web port +#api-origin=http://localhost:5111 diff --git a/src/studienarbeit/assets/sourcehut_setup/nginx/graphql.conf b/src/studienarbeit/assets/sourcehut_setup/nginx/graphql.conf new file mode 100644 index 0000000..cc990ca --- /dev/null +++ b/src/studienarbeit/assets/sourcehut_setup/nginx/graphql.conf @@ -0,0 +1,20 @@ +real_ip_header X-Forwarded-For; +real_ip_recursive on; +proxy_set_header Host $host; +proxy_set_header X-Forwarded-Proto https; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + +if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; +} + +add_header 'Access-Control-Allow-Origin' '*'; +add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; +add_header 'Access-Control-Allow-Headers' 'User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; +add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; diff --git a/src/studienarbeit/assets/sourcehut_setup/nginx/nginx_services.conf b/src/studienarbeit/assets/sourcehut_setup/nginx/nginx_services.conf new file mode 100644 index 0000000..0ac98c6 --- /dev/null +++ b/src/studienarbeit/assets/sourcehut_setup/nginx/nginx_services.conf @@ -0,0 +1,223 @@ +# Meta +server { + include sourcehut.conf; + include port80.conf; + server_name meta.codeforge.int; + + location / { + proxy_pass http://127.0.0.1:5000; + include web.conf; + } + + location /.well-known/oauth-authorization-server { + proxy_pass http://127.0.0.1:5000; + } + + location /query { + proxy_pass http://127.0.0.1:5100; + include graphql.conf; + } + + location /static { + root /usr/lib/$python/site-packages/metasrht; + expires 30d; + } +} + +# Hub +server { + include sourcehut.conf; + include port80.conf; + server_name codeforge.int; + + location / { + proxy_pass http://127.0.0.1:5014; + include web.conf; + } + + location /query { + proxy_pass http://127.0.0.1:5114; + include graphql.conf; + } + + location /static { + root /usr/lib/$python/site-packages/hubsrht; + expires 30d; + } +} + +# Git +server { + include sourcehut.conf; + include port80.conf; + server_name git.codeforge.int; + + location / { + proxy_pass http://127.0.0.1:5001; + include web.conf; + } + + location /query { + proxy_pass http://127.0.0.1:5101; + include graphql.conf; + } + + location /static { + root /usr/lib/$python/site-packages/gitsrht; + expires 30d; + } + + location = /authorize { + proxy_pass http://127.0.0.1:5001; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header X-Original-URI $request_uri; + } + + location ~ ^/([^/]+)/([^/]+)/(HEAD|info/refs|objects/info/.*|git-upload-pack).*$ { + auth_request /authorize; + root /var/lib/git; + fastcgi_pass unix:/run/fcgiwrap/fcgiwrap.sock; + fastcgi_param SCRIPT_FILENAME /usr/libexec/git-core/git-http-backend; + fastcgi_param PATH_INFO $uri; + fastcgi_param GIT_PROJECT_ROOT $document_root; + fastcgi_read_timeout 500s; + include fastcgi_params; + gzip off; + } +} + +# Man +server { + include sourcehut.conf; + include port80.conf; + server_name man.codeforge.int; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:5004; + include web.conf; + } + + location /query { + proxy_pass http://127.0.0.1:5104; + include graphql.conf; + } + + location /static { + root /usr/lib/$python/site-packages/mansrht; + expires 30d; + } +} + +# Todo +server { + include sourcehut.conf; + include port80.conf; + server_name todo.codeforge.int; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:5003; + include web.conf; + } + + location /query { + proxy_pass http://127.0.0.1:5103; + include graphql.conf; + } + + location /static { + root /usr/lib/$python/site-packages/todosrht; + expires 30d; + } +} + +# Lists +server { + include sourcehut.conf; + include port80.conf; + server_name lists.codeforge.int; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:5006; + include web.conf; + } + + location /query { + proxy_pass http://127.0.0.1:5106; + include graphql.conf; + } + + location /static { + root /usr/lib/$python/site-packages/listssrht; + expires 30d; + } +} + +# Paste +server { + include sourcehut.conf; + include port80.conf; + server_name paste.codeforge.int; + + client_max_body_size 10M; + + location / { + proxy_pass http://127.0.0.1:5011; + include web.conf; + } + + location /query { + proxy_pass http://127.0.0.1:5111; + include graphql.conf; + } + + location /static { + root /usr/lib/$python/site-packages/pastesrht; + expires 30d; + } +} + +# Builds +server { + include sourcehut.conf; + include port80.conf; + server_name builds.codeforge.int; + + client_max_body_size 100M; + + location / { + proxy_pass http://127.0.0.1:5002; + include web.conf; + } + + location /query { + proxy_pass http://127.0.0.1:5102; + include graphql.conf; + } + + location /static { + root /usr/lib/$python/site-packages/buildsrht; + expires 30d; + } +} + +# Runner (proxy only local requests) +server { + include sourcehut.conf; + include port80.conf; + server_name runner.codeforge.int; + + location / { + proxy_pass http://127.0.0.1:8080; + include web.conf; + + allow 127.0.0.1; + deny all; + } +} diff --git a/src/studienarbeit/assets/sourcehut_setup/nginx/port80.conf b/src/studienarbeit/assets/sourcehut_setup/nginx/port80.conf new file mode 100644 index 0000000..4e2f720 --- /dev/null +++ b/src/studienarbeit/assets/sourcehut_setup/nginx/port80.conf @@ -0,0 +1,10 @@ +listen 80; +listen [::]:80; + +location ^~ /.well-known { + root /var/www; +} + +location = /robots.txt { + root /var/www; +} diff --git a/src/studienarbeit/assets/sourcehut_setup/nginx/sourcehut.conf b/src/studienarbeit/assets/sourcehut_setup/nginx/sourcehut.conf new file mode 100644 index 0000000..dec2564 --- /dev/null +++ b/src/studienarbeit/assets/sourcehut_setup/nginx/sourcehut.conf @@ -0,0 +1,3 @@ +set $python "python3.10"; +set_real_ip_from 127.0.0.0/16; +set_real_ip_from 173.195.146.128/25; diff --git a/src/studienarbeit/assets/sourcehut_setup/nginx/web.conf b/src/studienarbeit/assets/sourcehut_setup/nginx/web.conf new file mode 100644 index 0000000..cee7b79 --- /dev/null +++ b/src/studienarbeit/assets/sourcehut_setup/nginx/web.conf @@ -0,0 +1,5 @@ +real_ip_header X-Forwarded-For; +real_ip_recursive on; +proxy_set_header Host $http_host; +proxy_set_header X-Forwarded-Proto https; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/src/studienarbeit/assets/woodpecker/docker-compose.yml b/src/studienarbeit/assets/woodpecker/docker-compose.yml new file mode 100644 index 0000000..add0cd6 --- /dev/null +++ b/src/studienarbeit/assets/woodpecker/docker-compose.yml @@ -0,0 +1,48 @@ +version: "3" +services: + woodpecker-server: + image: woodpeckerci/woodpecker-server:next + restart: unless-stopped + networks: + - proxy + environment: + - WOODPECKER_OPEN=true + - WOODPECKER_HOST=https://ci.thetadev.de + - WOODPECKER_GITEA=true + - WOODPECKER_GITEA_URL=https://code.thetadev.de + - WOODPECKER_GITEA_CLIENT=48060801-dc04-4361-b0a9-eefbfc6f29d0 + - WOODPECKER_GITEA_SECRET=gto_wefjljwg4ouio34goi4ui34ui34uighjrfvnerrejrekwhgui34g4 + - WOODPECKER_AGENT_SECRET=f81909f8e70371af65a6e1c6e77d35d4677c3ed242dcadde032fb27a9c5f9c35 + labels: + - "traefik.enable=true" + - "traefik.docker.network=proxy" + - "traefik.http.routers.woodpecker.entrypoints=websecure" + - "traefik.http.routers.woodpecker.rule=Host(`ci.thetadev.de`)" + - "traefik.http.routers.woodpecker.service=woodpecker" + - "traefik.http.services.woodpecker.loadbalancer.server.port=8000" + + # gRPC service + - "traefik.http.routers.woodpecker-grpc.entrypoints=websecure" + - "traefik.http.routers.woodpecker-grpc.rule=Host(`ci-grpc.thetadev.de`)" + - "traefik.http.routers.woodpecker-grpc.service=woodpecker-grpc" + - "traefik.http.services.woodpecker-grpc.loadbalancer.server.port=9000" + - "traefik.http.services.woodpecker-grpc.loadbalancer.server.scheme=h2c" + + woodpecker-agent: + image: woodpeckerci/woodpecker-agent:next + command: agent + restart: unless-stopped + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /etc/localtime:/etc/localtime:ro + environment: + - "WOODPECKER_SERVER=ci-grpc.thetadev.de:443" + - "WOODPECKER_AGENT_SECRET=f81909f8e70371af65a6e1c6e77d35d4677c3ed242dcadde032fb27a9c5f9c35" + - "WOODPECKER_MAX_PROCS=2" + - "WOODPECKER_HOSTNAME=ocloud" + - WOODPECKER_GRPC_SECURE=true + - WOODPECKER_GRPC_VERIFY=true + +networks: + proxy: + external: true diff --git a/src/studienarbeit/sourcehut_setup.md b/src/studienarbeit/sourcehut_setup.md new file mode 100644 index 0000000..113dbd8 --- /dev/null +++ b/src/studienarbeit/sourcehut_setup.md @@ -0,0 +1,512 @@ +# 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 +```