·

Unsere Migration zu Forgejo

Forgejo Logo

Für viele Jahre haben wir GitLab zum Hosten unseres Codes eingesetzt. Warum – und wie – wir zu Forgejo gewechselt sind.

Die Vorgeschichte

Wenn ich mich zurückerinnere, dann habe ich meine erste GitLab-Instanz zum 2015 herum installiert, seither habe ich bei Kunden bestimmt ein gutes dutzend Instanzen in Betrieb genommen. Damals war ich noch nebenberuflich als selbstständiger Softwareentwickler unterwegs und brauchte einfach ein zuverlässiges, gut bedienbares Hosting für meine Repositories.

Wichtig war mir damals – wie heute auch – dass die Plattform selbst gehostet werden kann und zumindest nicht schnarch langsam ist. GitLab bot all das, was ich benötigte und noch viel mehr. Obendrein ist die Community-Edition kostenfrei.

Die Gegenwart

Das ist auch heute noch so: GitLab bietet weit mehr, als wir als Firma wirklich benötigen – und das, obwohl unsere Anforderungen heute naturgemäß höher sind, als meine Anforderungen als Solo-Developer es damals waren.

Allerdings hat GitLab mit den Jahren auch massiv an Gewicht zugelegt: Inzwischen ist das Kernpaket unter Ubuntu mehrere Gigabyte groß und selbst das Paket für den Runner hat schon vor einer Weile die Gigabyte-Grenze überschritten. Der Arbeitsspeicherverbrauch war noch nie sonderlich niedrig und kleiner geworden ist er leider auch nicht, ganz im Gegenteil.

Darüber hinaus bin ich ehrlich gesagt kein Freund von übertriebener KI-Integration, wo sie uns keinen Nutzen bringt. GitLab wirbt aber inzwischen mehr mit neuen tollen KI-Features, als mit (für uns) sinnvollen Neuerungen. Dazu kommt die Tatsache, dass überraschend häufig Sicherheitslücken auftreten, gerne auch mit hoher Kritikalität und wir in schöner Regelmäßigkeit zu Wartungsarbeiten außer der Reihe gezwungen wurden.

Ich will aber GitLab keinesfalls schlecht reden: Es ist immer noch ein tolles Produkt. Nur vielleicht nicht mehr für uns.

Alternativen

Beschäftigt man sich mit dem Thema Git-Hosting, kommen natürlich unweigerlich die großen Platzhirsche, also vornehmlich GitHub und eben GitLab zur Sprache. GitHub war für uns wie eine Alternative – und die jüngsten Entwicklungen geben uns da sicher recht. Wer möchte schon seinen Code freiwillig zu Trainingszwecken spenden?

Aber man findet auch einige interessante andere Systeme, die man selbst hosten. Eines davon ist Forgejo, das seinerseits ein Fork von Gitea ist. Forgejo wird dabei von einem gemeinnützigen Verein, Codeberg e.V. mit Sitz in Berlin, verwaltet. Ein Modell, dass mich überzeugt hat.

Bevor es tatsächlich an eine Migration ging, war zunächst zu klären, welche Anforderungen wir eigentlich haben. Konkret sind das:

  • Git-Hosting (klar – darum geht’s ja in erster Linie)
  • SSO-Anbindung mit KeyCloak
  • LFS-Unterstützung
  • Solide CI/CD-Pipeline
  • Integrierte Docker-, NPM-, Maven- und NuGet-Registry
  • Brauchbares Issue-Tracking
    • idealerweise mit Kanban-Boards
  • WebHooks, um Benachrichtigungen an Rocket.Chat schicken zu können

Forgejo bietet alles davon. Gleichzeitig ist es kein Koloss, sondern praktisch ein einziges, relativ schmales Executable mit einem überraschend geringen Ressourcenverbrauch.

Das CI-System, Workflows genannt, arbeitet ähnlich zu dem von GitHub – und damit leider völlig anders, als GitLab. Aber Forgejo deckt unsere Anforderungen vollumfänglich ab.

Die erste Inbetriebnahme

Wir haben uns entschieden, Forgejo zunächst neben unserer GitLab-Instanz in Betrieb zu nehmen. Und das war wirklich erstaunlich einfach, wobei wir uns für den dockerisierten Ansatz entschieden haben.

Es musste zunächst eine neue Datenbank angelegt, dann ein eine Docker-Compose-Datei erstellt werden und anschließend noch der Reverse-Proxy entsprechend eingerichtet werden – wobei der Reverse Proxy, zumindest der offiziellen Dokumentation nach optional ist. Da aber alle unserer Systeme hinter einem RP laufen, war die Entscheidung klar.

Die erste „Herausforderung“ war dann, die app.ini-Datei entsprechend unseren Wünschen zu konfigurieren. Das war allerdings schnell gemacht, auch wenn es am Ende, nach den Erfahrungen im Betrieb, noch hier und da ein paar Fine-Tunings gab.

Alles in allem stand eine lauffähige Instanz nach weniger als 30 Minuten.

Die Migration

Die Migration gliederte sich in 3 Phasen:

  • Migration der Repository und der damit verbundenen Issues
  • Migration der CI für gemeinsam genutzte Pakete
  • Migration der CI für „normale“ Builds

Die Migration der Repositories erwies sich als geradezu kinderleicht – denn Forgejo bietet einen Migrations-Assistenten dafür an. Damit waren die Repos im Handumdrehen zu Forgejo migriert. Freundlicherweise übernimmt Forgejo dabei auch gleich die Issues, wenn man das wünscht.

Was aber leider auf der Strecke bleibt, sind die Boards. Forgejo bietet hierfür Projekte an. Leider muss man die Zuordnung dann aber händisch erledigen, was aber relativ einfach mit einem Batch-Edit funktioniert. Nur die Lane muss danach händisch eingestellt werden – und das ist tatsächlich eine Arbeit für Blöde…

Für den Bau unserer Produkte verwenden wir in aller Regel eigene Pakete – und eigene Docker-Images, in denen der Bau abläuft. Daher mussten diese im nächsten Schritt umgestellt werden.

Vorher mussten auf den relevanten Systemen noch Build-Runner installiert werden. Das ließ sich aber ganz einfach mit Ansible erledigen.

Wie bereits erwähnt ist das CI-System zu dem von GitLab völlig inkompatibel und folgt einer anderen Logik. Immerhin kann man in der Regel auf GitHub Actions zurückgreifen. Das setzt allerdings voraus, dass in dem jeweiligen Build-Container node.js installiert ist.

Während das in den Containern kein großes Problem ist, gefiel uns dieser Ansatz für Host-basierte Runner nicht unbedingt. Node.js ist eine große Abhängigkeit und auf Basis der Erfahrungen in den letzten Monaten und Jahren – Stichwort Supply Chain Attacks – eine Sache für sich.

Wir haben daher einige Actions selbst entwickelt, so dass sie nur auf Shell-Kommandos zurückgreifen, was dieses Problem effektiv löst und obendrein auch noch die Geschwindigkeit des Durchlaufs verbessert.

Die Lernkurve war durchaus steil, aber nach etwa 6h harter Arbeit war dann die Umstellung für die Pakete und Docker-Images gelungen.

Interessanterweise gibt es im übrigen keinen vorgefertigten Runner für macOS, was uns dann im nächsten Schritt, bei der Umstellung der Anwendungs-Builds auffiel. Wir fanden einige Posts, dass man auf den act_runner von Gitea zurückgreifen könnte, der auch über Homebrew schnell zu installieren ist, allerdings unterstützt der einige wichtige Dinge (etwa den forgejo-Kontext) nicht.

Bis dato hatte niemand von uns mit der Programmiersprache Go gearbeitet. Aber wir sind nicht umsonst Softwareentwickler und Go ist schnell installiert. Und zu unserer völligen Verblüffung ließ sich der Code des Forgejo-Runners völlig problemlos mit einem einzelnen Kommando compilieren. Fehlerfrei und in unter einer Minute.

Sollten auch andere Entwickler diesen Runner vermissen, bieten wir im übrigen gern an, den Build zu automatisieren und öffentliche Builds bereitzustellen. Dazu gern einfach ein Mail an mich.

Nachdem auch dieses Problem nun aus der Welt geschafft war, konnten wir auf die gesammelten Erfahrungen zurückgreifen und die Umstellung der Anwendungen dauerte nur noch wenige Minuten pro Anwendung.

Fazit

Forgejo hält, was es verspricht. Es ist schnell, es ist klein und es ist einfach zu nutzen.

Vorher brauchten wir Gigabyte-weise RAM für das Git-Hosting (vom Plattenplatz ganz zu schweigen), jetzt sind es keine 100 Megabyte mehr. Ein Update geht in Sekunden vonstatten.

Das System läuft nun seit etwa einem Monat stabil und wir sind so zufrieden, dass wir unsere GitLab-Instanz gestern abgeschaltet haben.

Vielen Dank für die schöne Zeit, GitLab. Du wirst mir immer in guter Erinnerung bleiben. Aber es war Zeit für etwas leichgewichtigeres.