Egal ob Softwareentwicklung in einer Firma oder zuhause stattfindet, an einer Softwareversionsverwaltung kommt man mittlerweile nicht mehr vorbei. Gogs, eine flexible und kostengünstige Lösung, ermöglicht es dir, eine eigene Softwareversionsverwaltung einzurichten. Namhafte Anbieter wie GitHub, Bitbucket, GitLab und Co. bieten Unternehmen im Lizenzmodell verschiedene Varianten ihrer Dienste an. Doch gerade, wenn man lokal oder in der eigenen Firma hosten will, wird das Lizenzmodell verdammt teuer oder es wird nichts Passendes angeboten.
In diesem Beitrag möchte ich dir erklären, was eine Softwareversionsverwaltung genau macht, warum sie mittlerweile so wichtig ist und wie du dir mittels Gogs eine eigene Softwareversionsverwaltung einrichten kannst.
Vorab: Docker mit Portainer installieren auf dem Raspberry Pi oder Heimserver
Damit dieser Blogbeitrag funktioniert, braucht es ein System mit Docker und am besten Portainer. Wie du das auf deinem Raspberry Pi oder Heimserver einrichtest, findest du in dieser Anleitung Docker auf dem Raspberry Pi. Gogs selbst kann auch ohne Docker installiert werden, jedoch gibt es bei den Updates einiges zu beachten, was mit Docker dann einfacher zu lösen ist.
Was ist eine (Software-)Versionsverwaltung?
Wenn man das Wort Versionsverwaltung in den Mund nimmt, denken viele (Hobby-)Entwickler direkt an GitHub oder GitLab. Das liegt unter anderem daran, dass die beiden genannten eine starke Präsenz im Internet haben und gerade GitHub bei vielen Projekten die erste Anlaufstelle ist, um Code oder Packages von Programmen zu erhalten. Aber warum braucht es überhaupt eine Versionsverwaltung und was muss man sich darunter vorstellen?
Ich möchte dies mit einem einfachen Beispiel erklären. Denken wir, dass du und dein Freund gerade ein Programm entwickelt. Beide arbeiten am Quellcode und programmieren ihren Teil weiter. Es stellt sich heraus, dass die Software in ihrem Stand von gestern einen Bug aufweist. Du fängst an, entsprechenden Code zu entwickeln, um den Bug zu fixen. Dein Freund weiß aber nichts von deinen Änderungen und fängt ebenfalls an, mit der Softwareversion von gestern zu arbeiten. Am Ende existieren zwei Versionen der Software, bei der entweder aus Unwissenheit ein Teil des Codes überschrieben wird oder alle Änderungen mühsam in den Code integriert werden müssen.
Eine Versionsverwaltung dokumentiert die einzelnen Änderungen, indem der Code erst ausgecheckt und als neue Version für jeden verfügbar gemacht wird. So ist ersichtlich, ob jemand an den Codeabschnitten arbeitet, und Änderungen können durch das Vergleichen von alten und neuen Versionen schneller überblickt werden. Eine Versionsverwaltung hat dabei den Vorteil, Probleme bei Änderungen zu minimieren, auch wenn eine Nachpflege von Code nur teilweise automatisch übernommen werden kann. Dazu gibt es dann meist eine Art Moderator oder Hauptentwickler, der für diese Aufgabe zuständig ist. Jeder kann sehen, sofern alles korrekt eingecheckt wurde, wer was gemacht hat und welche Änderungen sich daraus ergeben haben. Ein Zurückspringen auf frühere Programmstände ist jederzeit möglich, und gerade moderne Versionsverwaltungen bieten den Vorteil, Zweige, die sogenannten Branches, anzulegen und später zusammenzuführen.
In vielen Firmen wird ein Entwicklungszweig angelegt und erst nach Abschluss aller Tests und Freigaben in den Hauptzweig, dem sogenannten Master, übernommen und die Software final gebaut. Viele dieser Versionsverwaltungsprogramme oder -hoster verwenden als Versionsverwaltung Git, welches von Linus Torvalds initiiert wurde. Die grafische Oberfläche oder die Handhabung, wie etwas angezeigt oder umgesetzt wird, ist dann Sache der Entwickler der Programm- bzw. Hosteranbieter.
Der erste Gedanke, der nun aufkommen mag, ist, dass Git und Co. ihre Daten nur über einen Server verfügbar machen und jederzeit eine Verbindung zu diesem bestehen muss, um alles zu sehen. Tatsächlich wird aber auf jedem PC eine lokale Kopie angelegt, die später mit dem eigentlichen Server abgeglichen wird. So kann man unabhängig zur Serververfügbarkeit auf alle bis zum Abgleich getätigten Änderungen einsehen. Das kostet zwar lokalen Speicherplatz, macht das Arbeiten aber durchaus angenehmer.
Was ist Gogs und wofür brauche ich das?
Brauchst du nun einen selbst gehosteten Git-Dienst? Diese Frage kann ich nur schwer beantworten. Im Prinzip kannst du Git auch ohne gehosteten Git-Dienst laufen lassen; dazu kannst du das Repository, also das Projekt, über ein Netzlaufwerk zuhause oder im Büro verfügbar machen. Wenn du aber wie ich öfters mal unterwegs bist und entwickelst, dann ist ein selbst gehosteter Git-Dienst mit Anbindung ans Internet eine feine Sache. Voraussetzung ist, dass du deinen Webserver entsprechend sicher machst, damit du kein Einfallstor für Hacker baust. Du kannst auch direkt auf GitHub zurückgreifen, wo es mittlerweile keine Beschränkung bei den privaten Repositories gibt. Jedoch bist du an einen Anbieter gebunden und teilweise möchte ich einige Änderungen nicht in diesen Repositories sichtbar zeigen.
Ein weiterer Punkt für mich und auch für viele Unternehmen ist der Ort, an dem die eigenen Daten liegen. Ich will meine Daten bei mir wissen und nicht bei jemand anderem. Dies ist ein wichtiger Grund, warum Unternehmen viel Geld in die Hand nehmen, um selbst gehostete Git-Dienste aufzubauen. Sie wollen, dass das geistige Eigentum und auch der Quellcode bei der Firma bleibt und nicht einer Fremdfirma anvertraut wird. Gleichzeitig kann man spezielle Programme nutzen, die mit einem solchen Git-Dienst kommunizieren können. Ob du jedoch einen selbst gehosteten Git-Dienst brauchst, musst du schlussendlich selbst entscheiden.
Gogs mit Docker einrichten
Bevor es losgeht, eine Sache vorweg: Gogs braucht neben Speicher der Repositories auch eine Datenbank. In diesem Blogbeitrag verwende ich SQLite, da diese lokal bei Gogs eingerichtet werden kann. Wenn jedoch mehrere Personen mit Gogs bzw. dem Git-Service arbeiten sollen, wäre z.B. eine MariaDB sinnvoller. In der Dokumentation wird ebenfalls empfohlen, gerade für mehrere Personen, keine SQLite-Datenbank zu nutzen. Bei meinen Tests mit SQLite war Gogs mit 5 Zugriffen gleichzeitig noch zu verwenden, hatte aber durchaus kleinere Probleme.
Für Docker gibt es zwei Wege, Daten aus dem Container auf dem Zielsystem zu speichern, da andernfalls die Daten nach einem Neustart verloren wären. Ich entscheide mich an dieser Stelle für ein Docker-Volume, weswegen unter „Volumes -> Add Volume“ unter Portainer ein neues Volume erstellt wird (siehe Abbildung 1).
Volume erstellen
Abbildung 1: Ein neues Docker-Volume erstellen
Im nachfolgenden Dialog gibst du dem Volume einen Namen, der direkt beschreibt, wofür das Volume eingesetzt wird. Damit vermeidest du, dass du aus Versehen ein Volume eines gestoppten Containers löschst, der möglicherweise doch noch einmal gebraucht wird. Über den Button „Create the Volume“ wird dann das Volume erstellt und ist bereit für die weitere Verwendung (siehe Abbildung 2).
Abbildung 2: Das Volumen anlegen
Nach demselben Prinzip erstellst du ein weiteres Volume, das später für die Backups benötigt wird. Als nächstes wechselst du in den Containers-Bereich und legst über den Button „Add Container“ einen neuen Container an (siehe Abbildung 3).
Container erstellen
Abbildung 3: Container erstellen
Das jetzige Schema unterscheidet sich nicht von den bisherigen Blogbeiträgen. Zunächst braucht der Container einen Namen, damit man später weiß, wofür er gedacht ist. Da bisher das Image noch nicht heruntergeladen wurde, wird bei Image „gogs/gogs:latest“ benötigt. Bei Network Port Configuration werden zwei neue Ports angelegt, wobei der Port 22 und 3000 vom Container auf noch freie Ports vom Host gesetzt werden müssen. In meinem Fall 10022 -> 22 und 3000 -> 3000 (siehe Abbildung 4).
Abbildung 4: Die ersten Einstellungen von Gogs
Danach müssen noch die Volumes mit dem Datenpfad von Gogs gemounted werden. Im Reiter Volumes weiter unten wird der Container-Pfad /data mit dem zuvor erstellten Volume, sowie der Container-Pfad /backup gemappt (siehe Abbildung 5).
Abbildung 5: Die Volumes mappen
Unter dem Reiter Restart Policy kannst du dann noch auf „Unless Stopped“ stellen, damit der Container im Idealfall immer erreichbar ist. Gerade wenn der Host einmal neugestartet wurde, wird so auch der Container direkt wieder gestartet. Sind alle Einstellungen getätigt, wird über den Button „Deploy the Container“ das Image aus dem Internet geladen und der Container gestartet (siehe Abbildung 6).
Abbildung 6: Den Container erstellen und starten
Das kann an dieser Stelle nun etwas dauern, je nach Größe vom Image und dem Hostsystem. Auf einem Raspberry Pi 5 dauert alles ungefähr 30 Sekunden. Danach sollte in der Container-Liste der Gogs-Container erscheinen und mit dem Status „healthy“ den ordentlichen Betrieb zeigen (siehe Abbildung 7).
Abbildung 7: Gestarteter Gogs-Server in der Container-Liste
An dieser Stelle ist Gogs nun heruntergeladen und der Container erfolgreich gestartet.
Über die Adresse http://<IP-Host>:3000
(in meinem Fall die 3000, ansonsten der Port vom Container, der mit dem Host gemappt wurde) wird nun der Einrichtungsassistent von Gogs geöffnet (siehe Abbildung 8).
Einrichtungsassistent von Gogs
Abbildung 8: Installationsseite von Gogs
Hier habe ich schon den Datenbanktyp auf SQLite3 eingestellt, wobei der absolute Pfad der Datenbank nicht verändert werden sollte! Hast du einen MySQL- oder PostgreSQL-Server, kannst du hier die Zugangsdaten zu einer zuvor erstellten Datenbank angeben. Die Struktur der Datenbank wird an dieser Stelle von Gogs dann eingerichtet, es sollte also eine leere Datenbank sein.
Jetzt kommt ein Teil, der bei Gogs etwas Aufmerksamkeit erfordert: die allgemeinen Einstellungen (siehe Abbildung 9).
Abbildung 9: Die allgemeinen Einstellungen von Gogs
Beim Anwendungsnamen kannst du dir aussuchen, wie deine Gogs-Anwendung heißen soll. Dies kann später auch noch im Terminal korrigiert werden. Bei Domain und Anwendungs-URL gibst du am besten die feste IP-Adresse deines Systems ein. Vergewissere dich, dass du im Router entsprechend dem Host eine feste IP vergibst.
Jetzt kommt der Teil, der zumindest bei mir zu Problemen geführt hat. Gogs horcht durch die Einstellungen in Portainer auf den Port 3000 für den HTTP-Port, was auch so gewollt ist. Unter HTTP-Port darf aber der veränderte Port vom Mapping zwischen Host -> Container nicht eingetragen werden. Hier handelt es sich um den vom Container verwendeten Port (siehe Abbildung 9, rote Umrandung). Hast du beim Mappen des Ports in Portainer einen anderen Hostport als 3000 eingetragen, so musst du in der Anwendungs-URL diesen anpassen zu http://<IP-Host>:<gemappter-Port-zu-3000>
. Andernfalls wird beim Erstellen von Gogs dein Container nicht mehr erreichbar sein!
Interessant sind noch die optionalen Einstellungen, wobei die Administratoreinstellungen hierbei am wichtigsten sind (siehe Abbildung 10).
Abbildung 10: Optionale Einstellungen
Zum einen kannst du hier eine E-Mail-Adresse hinterlegen, um z.B. Registrierungsmails oder Passwort-Vergessen-Mails zu verschicken, aber auch das Administratorkonto anlegen. Letzteres ist vor allem wichtig, da du dich sonst nach der Installation von Gogs nicht mehr anmelden kannst. Daher solltest du zumindest einen Benutzernamen und ein Kennwort für das Administratorkonto vergeben. Der E-Mail-Service kann auch später noch konfiguriert werden. Bist du mit deinen Eingaben zufrieden, dann kannst du über den Button „Gogs installieren“ die Installation abschließen.
Die abschließenden Schritte dauern nicht lange und du wirst direkt mit dem Administrationskonto angemeldet (siehe Abbildung 11). Solltest du jedoch nichts sehen oder die Webseite nicht mehr erreichbar sein, so hast du möglicherweise etwas Falsches in den Basiseinstellungen eingetragen.
Abbildung 11: Anmeldung mit Admin-Konto
Letztlich kann ich nicht alles über Gogs zeigen und erklären, jedoch sind die Menüführung und auch die Einstellungen in den meisten Fällen selbsterklärend. Ich gebe aber zu, an einigen Stellen wäre eine umfangreiche Dokumentation hilfreich, die es aber leider so nicht gibt. Wenn es Probleme gibt, findet man vieles in Foren.
Zusammenfassung
Ich nutze für meine Projekte auf meinem Heimserver Gogs und bin bisher komplett zufrieden. Da ich einen Heimserver mit extra Datenbank-Server betreibe, nutze ich die Vorteile eines zentralen Produktiv-Datenbankservers. Gerade für Unternehmen ist dies auch zwingend nötig, da mit SQLite Mehruserverwendung nur bis zu einem gewissen Punkt funktioniert. Da alle gängigen Features wie 2FA oder Anlegen von verschiedenen Branches im Repository so einfach gehen wie z.B. bei GitHub, bin ich voll zufrieden. Nervig ist tatsächlich die Dokumentation von Gogs an vielen Stellen; da hat Gitea einen klaren Vorteil. Als ich den Git-Dienst bei mir eingerichtet habe, war ich aber über die Einfachheit von Gogs fasziniert und es lief stabil auf meinem Raspberry Pi 4, daher bin ich selbst bei Gogs geblieben. Mittlerweile ist der selbst gehostete Git-Service in meinen Homeserver umgezogen und auch über einen Reverse Proxy übers Internet erreichbar. Jeder (Hobby-)Entwickler kennt einen Git-Dienst und ich nutze seit der Einrichtung nur noch meine Versionsverwaltung für meine Softwareprojekte.