Seit Jahren verwende ich jetzt schon subversion als Versions-Verwaltung bin damit auch absolut zufrieden. Nie kam ich in eine Situation, dass ich an die Grenzen von subversion gestoßen wäre. Von daher hatte ich bisher auch nicht den Bedarf und den Ergeiz, daran irgendwas zu ändern. Auch die ewigen Diskussionen, dass git doch viel besser wäre als subversion, finde ich nicht wirklich zielführend. Bisher gab es einfach noch kein brauchbares Argument, das mich zu einem Umzug überzeugt hätte. Immerhin ist so ein Umzug auch mit Aufwand verbunden und das muss sich dann ja auch auszahlen.
Allerdings kam jetzt ein wirklich schlagkräftiges Argument auf, dem ich mich nur schwerlich entziehen kann. Und was noch dazu kommt… Ich bin neugierig und möchte auch in diesem Technologie-Zweig ein bisschen mitreden können. Aber erst einmal zum erwähnten Argument:

Die meisten modernen Frameworks und IDEs unterstützen git by default, indem zum Beispiel automatisch .gitignore Dateien angelegt werden oder ähnliches.

Das ist natürlich wahr und dem kann ich mich nicht entziehen.
Wenn man zum Beispiel ein angular-Projekt anlegt und dieses einfach in subversion einchecken will, muss man sich erst mühsam die ganzen Ignores zusammensuchen und eintragen. Ja, das muss man in der Regel nur einmal machen, aber bei git muss man das gar nicht machen, da .gitignore von Haus aus angelegt wird.
Daher will ich mir jetzt erst einmal einen brauchbaren git-Server aufsetzen und dann in einem späteren Schritt mal versuchen, dass ich meine bestehenden Repositories umziehe.

Anforderungen an einen git-Server

Da ich jetzt schon lange Zeit einige subversion-Server administriere, haben sich einige Anforderungen für mich heraus kristallisiert, die auf jeden Fall auch weiterhin beibehalten werden müssen:

  • Zugriff nur per ssh mit entsprechenden RSA-Keys
  • Bestehende RSA-Keys von früheren subversion-Installationen sollen wiederverwendet werden können
  • Rechteverwaltung mit verschiedenen Gruppen

Das ist eigentlich nicht viel, aber mit einer Standard-Installation kann man diese Voraussetzungen leider schon nicht erfüllen. Git ermöglich per default den Zugriff per ssh und auch mit einem RSA-Key. Das sogar einfacher als es bei subversion der Fall ist. Aber verschiedene Rechte und Gruppen sind standardmäßig nicht sonderlich schön gelöst. Man müsste zum Beispiel für jeden git-Benutzer einen Benutzer auf dem Server anlegen. Das geht in meinen Augen gar nicht. Der administrative Aufwand wäre zu hoch und ich bin einfach der Meinung, dass jeder zusätzliche Benutzer eine Sicherheitslücke darstellt.
Nach einiger Suche bin ich dann aber auf gitolite gestoßen. Gitolite ist ein Addin oder Subsystem für git, mit dem man eine gut funktionierende Accountverwaltung hinzufügen kann und auch noch viel mehr. Daher will ich mir jetzt die Installation mit diesem System einmal genauer anschauen.

Installation von git und gitolite auf dem Server

Anlegen eines git-Benutzers

Git wird in dieser Installation als ein eigenständiger Benutzer laufen. Der Benutzer soll dabei allerdings kein Password haben, so dass man sich nicht direkt damit anmelden kann. Lediglich Zugriffe über ssh sollen bei diesem Benutzer möglich sein.

Den Benutzer legt man mit folgendem Kommando an:

sudo adduser --system --shell /bin/bash -gecos 'git version control' --group --disabled-password --home /home/git git

Wichtig ist hier auf jeden Fall der Parameter disabled-password, damit man sich nicht direkt mit diesem Benutzer anmelden kann.

Erzeugen eines RSA-Keys für die administrativen Tätigkeiten

Damit man sich dann aber anmelden kann, muss man gleich mal einen RSA-Key erzeugen, mit dem man sich dann anmelden kann. Einen RSA-Key erzeugt man mit folgendem Kommando. Idealerweise macht man das auf seinem Client-PC, da man auf dem Server nur den entsprechenden Public-Key haben sollte. Den Private-Key muss man gut aufbewahren, weil man den künftig auch noch zum administrieren des git-Servers benötigt.

ssh-keygen -t rsa -f gitadmin

Im aktuellen Verzeichnis findet man dann zwei Dateien:

  • gitadmin
  • gitadmin.pub

gitadmin.pub überträgt man dann auf den Server:

scp gitadmin.pub <server-ip>:/tmp

Jetzt meldet man sich wieder am Server an und verschiebt den Key in das Verzeichnis des git-Users:

sudo mv /tmp/gitadmin.pub /home/git
sudo chown git:git /home/git/gitadmin.pub

Installation von git und gitolite

Jetzt ist endlich das Vorgeplänkel vorbei und es geht an die Installation von git und gitolite.
Falls noch nicht geschehen, installieren wir erst einmal git mit folgendem Kommando:

sudo apt-get install git

Ich glaub, einfacher kann man kein Programm installieren.
Um jetzt gitolite zu installieren, müssen wir uns als der zuvor angelegt Benutzer git anmelden. Da der Benutzer kein Passwort hat, geht das nur über folgendes Kommando:

sudo su - git

So. Und jetzt kann man sich gitolite besorgen. Eigentlich kann man gitolite auch über die Paketquellen installieren, aber ich hab die Erfahrung gemacht, dass die darin enthaltene Version ziemlich alt ist und ich hab es bei meinen Tests auch nicht geschafft, das System zum Laufen zu bekommen. Daher hab ich beschlossen, dass man den Empfehlungen der gitolite-Webseite folgen sollte und gitolite direkt von github holen sollte:

git clone git://github.com/sitaramc/gitolite

Installiert werden soll das Ganze in das bin-Verzeichnis des Users, das man auch erst anlegen muss. Da man sich nur im Home-Verzeichnis des git-Users bewegt, kann man alles ohne Adminrechte machen.

mkdir bin
gitolite/install -to /home/git/bin

Schließlich muss man nur noch das System konfigurieren, damit man darauf zugreifen kann. Damit stoßen wir das setup von gitolite an und übergeben diesem den zuvor erzeugten RSA-Key gitadmin.pub

bin/gitolite setup -pk gitadmin.pub

Das war’s und man kann sich jetzt vom System wieder abmelden. Alles weitere kann man vom Client aus durchführen.

Administration einrichten

So. Wir befinden jetzt also wieder am Client und wollen auf den neuen git-Server zugreifen.
In den Dokumentationen findet man immer folgenden Befehl, um auf die Konfiguration zuzugreifen:

git clone git@<server-ip>:gitolite-admin

Das probieren wir gleich mal… Hmpf… Passwort eingeben. Wir haben aber kein Passwort für den git-Benutzer und wollen auch keines haben. Wir haben vorhin extra einen neuen RSA-Key erzeugt. War das ein Fehler, da ich ja meine bisherigen RSA-Keys wieder verwenden will?
Nein. In meinen Augen nicht, da ich ein Freund davon bin, dass man die Administration von den normalen Tätigkeiten abgrenzt. Wir müssen also git bzw. ssh irgendwie erklären, dass der neu erstellte RSA-Key verwendet werden soll.
Zum Glück kann man ssh sehr gut konfigurieren und kann auch festlegen, wann welcher Key verwendet werden soll. Dazu öffnet man die Datei ~/.ssh/config oder legt sie an, falls sie noch nicht existiert und schreibt folgende Konfiguration hinein:

Host gitadmin
   User git
   Hostname <server-ip>
   Port 22
   IdentityFile ~/.ssh/gitadmin

Wenn man jetzt mit dem folgenden Kommando das Repository cloned, sollte es problemlos funktionieren:

git clone git@gitadmin:gitolite-admin

Was hat man hier gemacht?
Man erzeugt in der config einen Pseudo-Host mit dem Namen gitadmin. Wenn man auf diesen Host zugreifen will, soll der User git auf dem Server verwendet werden und außerdem soll dazu das Key-File (IdentityFile) *gitadmin* verwendet werden. Den Host *gitadmin* muss man dazu nicht im Nameserver oder sonst irgendwo bekannt machen. Er wird nur von ssh beim aktuellen Benutzer so verwendet.

Die Konfiguration von gitolite

Man hat jetzt also das Konfigurations-Repository ausgecheckt und kann mit der Konfiguration loslegen.
Die Konfiguration ist folgenderweise aufgebaut:

  • conf
  • keydir

Im Ordner conf findet man die Datei gitolite.conf in der die einzelnen Repositories verwaltet werden. Man kann hier Benutzer in Gruppen zusammenfassen und einem Benutzer oder einer Gruppe Rechte auf unterschiedliche Repositories zuweisen.
IM Ordner keydir findet man dagegen die RSA-Keys der einzelnen Benutzer, die mit diesem git-Server arbeiten dürfen.

Legen wir mal als Beispiel einen neuen Benutzer an (verwenden wir dazu unseren bisherigen RSA-Key, den wir bei subversion schon verwendet haben) und legen auch gleich ein neues Repository an, das wir dann diesem Benutzer zuweisen.

Zuerst kopieren wir unseren RSA-Key in das entsprechende Verzeichnis:

cp ~/.ssh/id_rsa-pub ~/gitolite-admin/keydir/mykey.pub

Man beachte dabei jetzt, dass der Benutzer in gitolite jetzt den Namen mykey hat. Also vielleicht sollte man einen sprechenden Namen verwenden wie zum Beispiel jon_dow.pub.

Dann öffnen wir die gitolite.conf und ändern die Datei so, dass sie folgendermaßen aussieht:

repo gitolite-admin
    RW+     =   gitadmin

repo testing
    RW+     =   @all

repo sample
    RW+     =   jon_dow

Anschließend commiten und pushen wir die Konfgiguration zum Server:

git add --all
git commit -m 'new user and new sample repository'
git push

Beim push kommen jetzt ein paar Meldungen. Die interessante Meldung dabei ist folgende:

remote: Initialized empty Git repository in /home/git/repositories/sample.git/

Man erkennt also, dass ein neues Repository angelegt wurde. Dieses Repository checken wir dann auch gleich mal aus.

git clone git@<server>:sample

Und jetzt hat man das Repository bei sich lokal.
Legen wir gleich mal eine Datei an und checken diese ein:

touch README
git add --all
git commit -m 'sample file'
git push

Um jetzt noch zu testen, ob das mit den Rechten auch wirklich funktioniert, löschen wir das lokale Repository wieder und entfernen die Rechte aus der Konfguration. Da wir aktuell keine anderen Benutzer haben, sagen wir einfach, dass der Benutzer gitadmin der andere Benutzer ist, das jetzt eben auf das Projekt sample die Rechte bekommt. Die Konfiguration des Repositories sieht dann so aus:

repo sample
    RW+     =   gitadmin

Jetzt probieren wir nochmal, dass wir das Repository auschecken und siehe da:

Klone nach 'sample' ...
FATAL: R any sample mossi_extensa DENIED by fallthru
(or you mis-spelled the reponame)
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Und man sieht, dass alles funktioniert.