Hosting von Git-Repositories mit Gitosis

Schon wieder Git. Nach den Artikeln zu Git, iDisk und so und GitNub hat mich in den letzten Tagen beschäftigt, wie man Git-Repositories auf einem Server hosten kann, beispielsweise um diese der Allgemeinheit zur Verfügung zu stellen (man kann natürlich auch einfach github verwenden). Dabei stieß ich auf Gitosis und es entstand die nachfolgende kurze Anleitung.

Ausgangsbasis

Um beim Lesen nicht durcheinander zu kommen, sind Befehle, die auf dem Server einzugeben sind, mit dunklem Hintergrund und heller Schrift formatiert. Beispiel:

uname

Befehle, die auf dem Client einzugeben sind, haben entsprechend einen hellen Hintergrund und dunkle Schrift. Beispiel:

uname

Für alle nachfolgenden Schritte wird davon ausgegangen, dass auf dem Server schon Git und Python (inkl. dem Paket Setuptools) installiert sind sowie ein Benutzer mit root- oder sudo-Rechten verfügbar ist. In meinem Fall lief auf dem Server Ubuntu Linux, die Anleitung sollte sich aber leicht auf andere Linux-Varianten anpassen lassen (sofern überhaupt Änderungen notwendig sind). Auf dem Client verwende ich Mac OS X 10.5, die Installation von Git kann man in einem älteren Beitrag nachlesen.

Installation & Konfiguration

  1. Git-Repository von Gitosis klonen:
    cd ~
    mkdir sources
    cd sources
    git clone git://eagain.net/gitosis.git
  2. Gitosis installieren:
    cd gitosis/
    sudo python setup.py install
  3. Benutzer "git" anlegen:
    sudo adduser --system --shell /bin/sh --gecos 'git version control' --group --disabled-password --home /home/git git
    Mit den letzten beiden Parametern wird ein Login per Passwort deaktiviert und das Heimatverzeichnis des Benutzers auf /home/git gesetzt.

  4. Im nächsten Schritt muss der eigene öffentliche SSH-Schlüssel auf den Server kopiert werden. Zunächst ist zu prüfen, ob ein solcher schon existiert:
    ls ~/.ssh/id_rsa.pub
    Falls ja, direkt weiter mit dem nächsten Schritt. Falls nein, einen neuen Schlüssel erzeugen:
    ssh-keygen -t rsa
  5. Den Öffentlichen SSH-Schlüssel auf den Server kopieren:
    scp -P 10022 ~/.ssh/id_rsa.pub USER@SERVER:/tmp
    USER ist dabei durch den Benutzernamen auf dem Server, SERVER durch den Servernamen zu ersetzen.

  6. Zurück auf dem Server wird nun Gitosis initialisiert und dabei der eigene SSH-Schlüssel in die Liste der autorisierten Benutzer aufgenommen:
    sudo -H -u git gitosis-init < /tmp/id_rsa.pub
  7. Je nach Debian-Version kann es notwendig sein, noch folgende Rechte zu setzen (siehe Kommentare von Wir und MacLovin):
    chmod 750 /home/git/repositories/gitosis-admin.git/hooks/post-update
  8. Zum Schluss kann der gitdaemon gestartet werden, sofern ein öffentlicher Zugriff auf eines der Repositories gewünscht ist (Konfiguration der Rechte wird weiter unten beschrieben):
    sudo -u git git-daemon --base-path=/home/git/repositories/
    Der Daemon läuft auf Port 9418, je nach Konfiguration des Servers müssen möglicherweise die Regeln einer vorhandenen Firewall angepasst werden.

Verwalten von Repositories

Die Verwaltung von Repositories und (wie wir später sehen werden) von Benutzern geschieht bei Gitosis über ein eigens dafür vorgesehenes Git-Repository, welches bei der Installation auf dem Server erzeugt wurde. Es lässt sich wie folgt auf dem Client klonen:

cd ~/Projects
git clone git@SERVER:gitosis-admin.git

SERVER ist wiederum durch den Namen des Servers zu ersetzen. Da wir vorhin den eigenen öffentlichen SSH-Schlüssel auf den Server kopiert haben, ist kein Passwort notwendig.

Das Repository besteht grundsätzlich aus der Datei gitosis.conf zur Verwaltung der Repositories und Benutzer sowie dem Verzeichnis keydir, in dem die SSH-Schlüssel ablegt sind:

$ cd gitosis-admin/
$ ls -ln
total 8
-rw-r--r--  1 501  20  167  3 Jan 19:57 gitosis.conf
drwxr-xr-x  4 501  20  136  3 Jan 19:57 keydir

Die Datei gitosis.conf enthält im initialen Zustand folgende Zeilen:

[gitosis]

[group gitosis-admin]
writable = gitosis-admin
members = tom@mymac

Der Abschnitt "group gitosis-admin" definiert eine neue Benutzergruppe mit dem Namen "gitosis-admin", die Schreibzugriff auf das Repository "gitosis-admin" hat und derzeit nur aus einem Mitglied "tom@mymac" besteht. "tom" ist hierbei mein lokaler Benutzername, "mymac" der Name meines Client-Rechners. Entsprechend enthält das Verzeichnis keydir eine Datei mit dem Namen tom@mymac.pub.

Ein neues Repository kann nun erzeugt werden, in dem folgende Zeilen der Datei gitosis.conf hinzufügt werden:

[group developers]
writable = test
members = tom@mymac

Das Repository hat hier den Namen "test", gehört zur Gruppe "developers" und nur mein eigener Benutzer "tom@mymac" hat darauf Schreibrechte. Im Prinzip hätte es auch ausgereicht, den Bezeichner "test" an die obige Zeile "writable = gitosis-admin" mit Leerzeichen getrennt anzuhängen. Es ist aber aus meiner Sicht sinnvoll, gleich von Anfang an die Repositories für Projekte vom Repository für die administrativen Aufgaben zu unterscheiden.

Nach Speichern der Datei gitosis.conf wird nun gitosis-admin eingecheckt und auf den Server geschoben ("push"):

git commit -a -m "Created repository test." 
git push

Damit hat "tom@mymac" Zugriff auf das Repository "git@SERVER:test.git", das Repository selbst existiert aber noch nicht und muss entsprechend angelegt werden:

cd ~/Projects
mkdir test
cd test
git init
git remote add origin git@SERVER:test.git

Hat man bereits ein Projektverzeichnis (egal ob mit oder ohne Dateien), kann der Aufruf von "mkdir test" entfallen. Anschließend können Dateien dem Projekt hinzugefügt und eingecheckt werden. Beispiel:

echo "This is a test file." > README
git add README
git commit -m "Initial revision." 

Beim "push" auf den Server wird schlussendlich das Repository erzeugt:

git push origin master:refs/heads/master

Verwalten von Benutzern

Bisher hat auf das erzeugte Test-Repository lediglich der Benutzer "tom@mymac" Lese- und Schreibzugriff. Weitere Benutzer mit denselben Rechten können erstellt werden, indem diese dem Admin ihren öffentlichen SSL-Schlüssel zur Verfügung stellen. Angenommen, der Benutzer "joey@hismac" schickt seinen Schlüssel, dann sind folgende Schritte durchzuführen:

cd ~/Project/gitosis-admin
cp ~/Download/joey@hismac keydir

In der Datei gitosis.conf ist der Benutzer der Gruppe "developers" hinzuzufügen:

[group developers]
writable = test
members = tom@mymac joey@hismac

Dann weiter im Terminal:

git add .
git commit -m "Added joey to project test." 
git push

Will man das Repository hingegen für die Allgemeinheit mit Leserechten veröffentlichen (also ohne Abfrage von Benutzername und Passwort), muss auf dem Server die Datei git-daemon-export-ok innerhalb des Repositories erzeugt werden,

sudo touch /home/git/repositories/test.git/git-daemon-export-ok

und ist dann wie folgt klonbar:

git clone git://SERVER/test.git

Damit endet dieser Artikel über Gitosis. Für weitere Dokumentation sei auf die README-Datei von gitosis verwiesen.

Kommentare, Fragen und Kritik sind wie immer herzlich willkommen.

Schlüsselwörter: git, server, versionskontrolle

Von Thomas Dohmke vor 607 Tagen hinzugefügt


Kommentare

Von rubyphunk vor 427 Tagen hinzugefügt

Geniales System. Schade dass ich das nicht früher schon kannte.
Danke für die Erleuchtung!

Von Nils und Gecko vor 416 Tagen hinzugefügt

Lieber Thomas
vielen Dank für dieses wundervolle Howto; wir benutzen es gerade auf einem FreeBSD server.
eine kleine Anmerkung:

Schritt 6 sollte nicht:

sudo -H -u git gitosis-init < /tmp/id_rsa.pub

lauten sondern:

sudo -H -u gitosis-init < /tmp/id_rsa.pub

Beste Grüße aus Bonn

Von Thomas Dohmke vor 416 Tagen hinzugefügt

@Nils und Gecko: Ich habe gerade kein FreeBSD zur Hand, aber unter Linux folgt nach sudo -u der Benutzername, auf den man sudo'en will:

$ sudo
usage: sudo -h | -K | -k | -L | -l | -V | -v
usage: sudo [-bEHPS] [-p prompt] [-u username|#uid] [VAR=value]
            {-i | -s | <command>}
usage: sudo -e [-S] [-p prompt] [-u username|#uid] file ...

Insofern ist Schritt 6 im Tutorial korrekt.

Von Nils und Gecko vor 416 Tagen hinzugefügt

hi thomas
du hast völlig recht, das war unser fehler.
inzwischen haben wir das ganze eigentlich am laufen, das einizige problem ist noch dass wir leider trotz erfolgreichem schritt 6 nicht ohne passwort eingabe das admin repo clonen können...
hast du da evtl. einen heißen tip?

lg gecko & nils

Von Thomas Dohmke vor 416 Tagen hinzugefügt

Aus der Ferne ist das eine gute Frage. Folgende Ideen:
  • PubkeyAuthentication beim sshd aktiviert?
  • Ist euer Key auf dem Server in /home/git/.ssh/authorized_keys enthalten?
  • Liegt der Key auf dem Client in .ssh?
  • Hat der Key eine Passphrase? Falls ja, muss diese zwar bei git clone eingegeben werden, das ist aber nicht das Passwort des Servers.

Von Nils vor 415 Tagen hinzugefügt

hi thomas,

1. jawohl denn mit dem root user klappt das ohne passwort auf den server zukommen (also aufgrund des keys, nicht etwa weil der kein passwort hat :))
2. ja ist drinne, hat er alles schön reingelegt
3. jup
4. nein ...

ich habe so ein bisschen das gefühl dass das irgendwie an dem git user liegt und an der art und weise wie wir den angelegt haben. ich werde dazu nochmal unseren server admin konsultieren und dich wissen lassen was es war, wenn du möchtest.

gruß nils

Von Rudolf vor 408 Tagen hinzugefügt

Hi Thomas,

vielen Dank für diese tolle (deutsch) Anleitung, ich währe sicher nicht so weit ohne diese Anleitung gekommen.

Bei dieser Zeile hänge ich aber fest:
sudo -u git git-daemon --base-path=/home/git/repositories/

Bei mir meldet das System das git-daemon unbekannt ist.

Ich setze Debian 4.0 ein, habe die aller neuste Version von git runtergeladen (mit ./configure) konfiguriert, (mit make) gebaut und (mit make install) installiert. Dann bin ich Schritt für schritt diese Anleitung durchgegangen.

Der Port 9418 (der sowiel ich weiß von gitosis benutzt wird, oder?) ist bei mir von "Git Version Control System" belegt, folgendes hat der Befehl

grep 9418 /etc/services
ausgegeben:

git             9418/tcp                        # Git Version Control System

Wenn ich aber über den Packet-Manager git-daemon-run nachinstalliere bekomme ich es nicht auf den "Standard"-Port gesetzt. Es kommt eine Meldung das er den Port nicht benutzen kann.

Weiß jemand Rat?

Von Thomas Dohmke vor 408 Tagen hinzugefügt

Hi Rudolf,

wo liegt denn bei dir das Binary von git, das du durch make install installiert hast? Bei uns liegt es in /usr/bin:

$ which git
/usr/bin/git

Im selben Verzeichnis ist auch der git-daemon:

$ which git-daemon
/usr/bin/git-daemon

Vielleicht liegt das Binary bei dir in /usr/local/bin und dieses Verzeichnis ist nicht im PATH?

Die Fehlermeldung beim Port klingt danach, als ob der git-daemon schon läuft. Eventuell musst du für diesen bloß noch die Config anpassen, so dass er auf das richtige Verzeichnis zeigt (/home/git/repositories/).

Thomas

Von Rudolf vor 408 Tagen hinzugefügt

Hi Thomas,

vielen Dank für die so schnelle Antwort.

$ which git
gibt mir, wie du vermutet hast folgendes aus:
/usr/local/bin/git

Wenn ich aber das

which git-daemon
probiere kommt keine Ausgabe und in dem Verzeichnis von git (siehe oben) es auch kein git-daemon.
Das Verzeichnis /usr/local/bin/git beinhaltet nur folgende Dateien:
git            
git-receive-pack 
git-upload-archive 
gitk
git-cvsserver
git-shell
git-upload-pack

Also nichts vom git-daemon zu sehen. Kann es sein, ich habe dazu leider nichts gefunden, das im Git-Source kein Daemon mitgeliefert wird? (das wurde auch in keiner englischen anleitung erwähnt!)

Ich hoffe du kannst mir helfen ich weiß einfach nicht mehr weiter...

Gruß
Rudolf

Von Thomas Dohmke vor 408 Tagen hinzugefügt

Hi Rudolf,

probier das ganze mal ohne das Minus zwischen git und daemon, also

sudo -u git git daemon --base-path=/home/git/repositories/

Außerdem solltest du gucken, ob der Daemon eventuell schon läuft, z.B. mit:

ps ax | grep git

Gruß

Thomas

Von Wir vor 374 Tagen hinzugefügt

Unter Gentoo musste ich noch ein "chmod /home/git/repositories/gitosis-admin.git/hooks/post-update" machen, damit ich in's admin-repo pushen konnte. Hat mich nur ca. einen Tag gekostet das herauszufinden. ;-)

Von hexa vor 275 Tagen hinzugefügt

Ist es nicht so, dass die Keys (siehe "Verwalten von Benutzerkonten") als user@host*.pub* in das Verzeichnis kopiert werden müssen?

Zum Beispiel:
cp ~/Download/joey@hismac keydir/joey\@hismac.pub

Von Thomas Dohmke vor 275 Tagen hinzugefügt

Nein, der Dateiname des Public-Keys ist egal, wichtig ist nur, dass er mit der Angabe in der gitosis.conf übereinstimmt.

Von MacLovin vor 208 Tagen hinzugefügt

Vielen Dank für diese großartige Anleitung!

Dem Kommentar von "Wir" kann ich mich nur anschließen. Ich habe es mit Ubuntu 9.10 getestet und mir fehlte nach der Initialisierung auch das
chmod 750 /home/git/repositories/gitosis-admin.git/hooks/post-update

Vielleicht könntest du es in die Anleitung aufnehmen...

Von Tobias vor 193 Tagen hinzugefügt

Vielen Dank für die Super Anleitung. Läuft hier unter einem Debian Lenny auch ganz prima. - Aber ein kleines Problem habe ich noch mit dem daomen ... der daemon läuft nur wenn man "sudo -u git git-daemon --base-path=/home/git/repositories/" eingibt und das Putty Fenster offen lässt.

Natürlich kann ich den Daomen in den Background jagen, aber lieder wäre es mir wenn er beim booten mit gestartet wird. Habe mir auch schon das Paket "git-daomen-run" angesehen, finde aber keine Konfig Datei um mein Repositorie unter /home/git anzugeben (das Paket nutzt standardmäßig wohl /var/git/cache ...)

Von Thomas Dohmke vor 193 Tagen hinzugefügt

Bei der Installation von git-daemon-run wird u.A. die Datei /etc/sv/git-daemon/run angelegt. Diese als Superuser editieren und den Parameter --base-path auf /home/git/repositories setzen, dann sollte es klappen.

Von Tobias vor 193 Tagen hinzugefügt

Danke Thomas, wollte gerade schreiben das ich mittels "find" doch noch eine Konfig Datei gefunden habe - warst nur schneller. ;-)

Von surtic vor 191 Tagen hinzugefügt

@Wir und MacLovin

Wie habt ihr denn nun das post-update erstellt? ich bin gerade beim selben problem, nur das ich es über sudo apt-get instll gitosis unter ubuntu 9.04 admin repo konnte ich clonen und alles aber ein neues erstellen geht nicht.

Von Marc vor 65 Tagen hinzugefügt

Danke für die ausführliche Anleitung.

Ich habe allerdings wohl noch ein letztes Problem. Beim clonen vom Client aus bekomme ich diverse Python-Fehler entgegengeschmissen.

Traceback (most recent call last):
File "/opt/bin/gitosis-serve", line 8, in <module>
load_entry_point('gitosis==0.2', 'console_scripts', 'gitosis-serve')()
File "/opt/lib/python2.5/site-packages/gitosis/app.py", line 24, in run
return app.main()
File "/opt/lib/python2.5/site-packages/gitosis/app.py", line 38, in main
self.handle_args(parser, cfg, options, args)
File "/opt/lib/python2.5/site-packages/gitosis/serve.py", line 204, in handle_args
os.execvp('git', ['git', 'shell', '-c', newcmd])
File "/opt/lib/python2.5/os.py", line 354, in execvp
_execvpe(file, args)
File "/opt/lib/python2.5/os.py", line 390, in _execvpe
func(fullname, *argrest)

Ich habe mich schon ein wenig schlau gemacht und in einem Post wurde erwähnt dass gitosis wohl Probleme mit Python 2.6 hat, allerdings ist mein gitosis auf 2.5 konfiguriert.
Ich sollte vielleicht erwähnen dass ich versuche es auf einer BusyBox-Distribution über ipkg zu installieren.

Hatte jemand ein ähnliches Problem oder weis was ich hier machen kann (habe keine Ahnung von Python und die BusyBox ist auch nur ein NAS)?

Danke

Von Philipp vor 44 Tagen hinzugefügt

Super Anleitung, hat alles geklappt außer:

Ich muss z.B. für's gitosis-admin eingeben:

git clone user@server:repositories/gitosis-admin.git

... welchen Schritt hab ich da verpasst?

Von Peter vor 41 Tagen hinzugefügt

Danke für die super Anleitung!!

@Marc Falls du dein Problem noch nicht gelöst hast...

Probier mal folgendes:

ln -s /opt/bin/git /usr/bin/

Der Befehl erzeugt einen Symbolischen Link im Verzeichnis /usr/bin/

Danach hat bei mir alles Super funktioniert.

Von Henry vor 17 Tagen hinzugefügt

Dank für die Anleitung.
Eigentlich hat auch alles einwandfrei geklappt. Nur habe ich das gleiche Problem wie Philipp bereits erwähnt hat. (Pfadangabe zum repo mit "repositories/***.git")
Diese Pfadangabe muss ich auch in den einzelnen Projektkonfigurationsdateien angeben, damit der push ohne Fehler funktioniert.
Hat jmd das gleiche Problem bereits lösen können ?
Danke!

Kommentar hinzufügen

Twitter

Uns auf Twitter verfolgen: