SVN-Repository über svnserve zur Verfügung stellen

Wenn man Dokumente mit SVN verwaltet, wird man schnell feststellen, dass der Zugriff über das file-Protokoll einige Nachteile mit sich bringt. So kann nur der Benutzer der
Repository-Dateien problemlos mit dem Repository arbeiten. Wenn jedoch mehrere Benutzer Zugriff auf das Repository erhalten sollen, müssen entsprechende Dateirechte (gleiche Gruppenzugehörigkeit) gesetzt werden. Für den Zugriff auf das Repository müssen zudem entsprechende Accounts auf dem Rechner bestehen.

Ist das SVN-Repository auf einem Server eingerichtet, müssen alle Clients irgendwie
Zugriff auf die Dateien erhalten. Ein denkbarer Weg wäre, das SVN-Verzeichnis als
Netzwerklaufwerk zu mounten, um Zugriff auf das Repository zu erhalten. Neben dem hier beschriebenen Einrichtungsaufwand gibt es aber viele Punkte, die gegen eine solche
Infrastruktur sprechen:

Der direkte Zugriff auf die SVN-Dateien über file://-URLs ist nicht besonders sicher.
Nutzer greifen ja direkt auf die Datenbankdateien zu und könnten dadurch Dateien
absichtlich oder aus versehen beschädigen, wodurch die Arbeit aller Nutzer
mit einem Schlag zerstört werden könnte.

Außerdem gibt es wenige graphische Clients, die das file://-Protokoll unterstützen.
SmartSVN beispielsweise tut dies nicht. Damit ist der Zugriff auf das Repository
für viele Benutzer weniger komfortabel, denn die einzige Client-Anwendung steht nur
über der Konsole zur Verfügung.

Dabei ist der oben beschriebene Aufwand überhaupt nicht notwendig, da SVN von Hause aus eine einfach konfigurierbare und benutzbare Serveranwendung mitbringt: svnserve.

svnserve als Dienst benutzen

svnserve stellt die einfachste Verbindung zwischen Client und SVN-Repository dar. Die Vorteilevon svnserve lassen sich in folgende Punkte zusammenfassen:

  • Aufsetzen geht schnell und einfach.
  • Netzwerkprotokoll ist schneller als WebDAV, da es zustandsorientiert ist.
  • Keine lokalen Nutzerkonten auf dem Server notwendig.
  • Passwort wird nicht über das Netzwerk übertragen.

Neben all diesen Vorteilen hat die Benutzung von svnserve jedoch auch einige Nachteile.
So gibt es überhaupt keine Protokollierung. Weder die Zugriffe noch Fehler werden durch das System protokolliert. Dies kann in einigen Fällen von Nachteil sein, wenn man eine fehlerhafte Konfiguration debuggen möchte. Außerdem ist die komplette Netzwerkverbindung unverschlüsselt. Dies kann ggf. ein Sicherheitsproblem darstellen, wenn Nutzer aus dem Internet auf das SVN-Repository zugreifen können.
Ein weiterer Nachteil von svnserve ist, dass die Passwörter der Benutzeraccounts im Klartext abgespeichert werden. Das bedeutet zum einen, dass man als Administrator dafür Sorge tragen muss, dass die Datei entsprechend vor unbefungtem Zugriff geschützt ist, und stellt zum anderen natürlich auch ein potentielles Sicherheitsproblem dar.

Im SVN-Buch werden eine Reihe von Alternativen besprochen, die einige dieser Nachteile beseitigen, jedoch selbst Nachteile gegenüber svnserve haben. So kann man  beispielsweise eine verschlüsselte Verbindung zum SVN-Repository einrichten, indem man die Verbindung über SSH tunnelt. Ferner bietet sich Apache als weitere Lösung an, Neben der Möglichkeit, https einzusetzen, besitzt Apache noch ein fein granuliertes Logging und bringt von Haus aus eine Reihe von Authentifizierungsmechanismen mit. Letzten Endes empfehlen die Autoren des SVN-Buches für kleinere Teams den Einsatz von svnserve. Näheres zu den Vor- und Nachteilen dieser Lösungen kann man im Kapitel 6 des SVN-Buchs nachlesen.

SVN-Repository mit svnserve betreiben

Im vorhergehenden Posting habe ich ein Repository im home-Verzeichnis des Users eingerichtet. Das ist freilich nicht sinnvoll, wenn mehrere User Zugriff auf das Repository haben sollen. Es bietet sich daher an, das Repository innerhalb des Verzeichnises /var/svn/ anzulegen. Dieses Verzeichnis sollte zudem einem Benutzer gehören, dem auch der jeweilige svnserve-Prozess gehört. Es ist also naheliegend, vorher einen entsprechenden Benutzer anzulegen:

root@linux:~# adduser svnowner --home /var/svn --system

Dieser Befehl legt einen neuen Systembenutzer an. Der neue Benutzer svnowner landet zudem in der Gruppe nogroup und verfügt also über sehr eingeschränkte Zugriffsrechte auf Dateisystemebene. Für Systembenutzer muss zudem kein Passwort hinterlegt werden, sodass es also unmöglich ist, sich als Benutzer svnowner im System anzumelden. Zudem sollte unbedingt das Home-Verzeichnis von svnowner mit der --home-Option auf das Basisverzeichnis des SVN-Repositorys gesetzt werden, da andernfalls standardmäßig ein Verzeichnis unter /home/ gesetzt wird.

Die Funkion adduser legt zudem gleich auch das fehlende Verzeichnis /var/svn/ für svnowner an, in das die Repositorys angelegt werden können – daher können wir uns diesen Schritt sparen.

Nun kann root im Verzeichnis /var/svn/ das Repository anlegen. (Falls man als User bereits ein Repository in seinem Home-Verzeichnis angelegt hat, kann man das auch nach /var/svn kopieren und spart sich den ganzen Anlegestress.)

root@linux:/var/svn# svnadmin create repos

Subversion legt nun in das Verzeichnis /var/svn/ ein Unterverzeichnis repos an, das alle notwendigen Dateien für das Repository (Konfigurationsdateien und Datenbankdateien) enthält.

Im nächsten Schritt sollte das Verzeichnis und alle darin enthaltenen Dateien dem rechtmäßigen Besitzer zugewiesen werden:

root@linux:/var/svn# chown -R svnowner:nogroup repos

Zudem sollten wir sicherstellen, dass nur svnowner Lese- und Schreibreche über das Repository besitzt:

root@linux:/var/svn# chmod -R 700 repos

Im folgenden Schritt kann nun der svnserve-Dienst eingerichtet werden.

Svnserve-Dienst einrichten

Der einfachste Weg, svnserve als Daemon zu starten, besteht in folgendem Befehl in der Kommandozeile:

root@linux:~# svnserve -d

Wenn du den Dienst aber immer parat haben willst, möchtest du natürlich nicht jedes Mal diesen Befehl in die Konsole eingeben. Schöner wäre es, wenn svnserve bereits beim Booten starten würde. Über entsprechende Startup-Scripte im Verzeichnis /etc/init.d/ kann man das sicherlich einrichten, aber ich möchte gerne einen einfachen und leichter wartbaren Weg gehen.

Glücklicherweise gibt es in der Unix-Welt den inetd-Dienst. Dieser Dienst lauscht für uns an Port 3390, ob ein Client irgendwelche Anfragen an svnserve stellt. Ist dies der Fall, startet inetd für uns svnserve. Da inetd in Ubuntu-Linux (Stand dieses Blog-Eintrags ist 8.10) nicht standardmäßig mitinstalliert ist, müssen wir das entsprechende Paket vorher über apt-get installieren:

root@linux:~# apt-get install openbsd-inetd

Im folgende Schritt müssen wir die Konfigurationsdatei /etc/inetd.conf so einstellen, dass
svnserve bei Anfragen von SVN-Clients gestartet wird. Dazu hängen wir der Datei folgende Zeile an:

# Dienst Socket-Typ Protokoll Wait-Status Prozess-Besitzer Programm-Pfad Startbefehl+Parameter
svn stream tcp nowait svnowner /usr/bin/svnserve svnserve -i

Die Zeile ist so zu verstehen, dass alle Anfragen für den Dienst svn, die über tcp reinkommen, zum Start von svnserve führen. Besitzer des Prozesses ist zudem svnowner – wir wollen nicht, dass der Server von root gestartet wird, sondern von einem User, der möglichst wenig Rechte hat. Außerdem sollte der hier angegebene User der einzige sein, der volle Lese- und Schreibrechte über die Dateien des SVN-Repositorys hat.

Der letzte Eintrag in der Zeile ist der wichtigste: Er enthält den Befehl, mit dem svnserve gestartet wird. Dieser Befehl sollte unbedingt die Option -i (Langform: --inetd) enthalten. Sie muss angegeben werden, wenn svnserve über inetd gestartet wird.

Näheres zu den hier nicht erwähnten Feldern der Konfigurationsdatei könnt ihr in der Manpage von inetd.conf finden.

Für den Zugriff auf das Repository muss man im Client den vollen Pfad zum Repository-Verzeichnis angeben. In unserem Beispiel wäre das /var/svn/repos. Da dies nicht besonders kurz ist, wäre es natürlich schön, wenn man im Client lediglich das Repository-Verzeichnis angeben müsste. Dazu muss man svnserve beim Starten lediglich den Pfad zum Basisverzeichnis des Repositorys mitteilen. Dies macht man mit der -r-Option, die an die Zeile in der initd.conf angehängt wird:

# Dienst Socket-Typ Protokoll Wait-Status Prozess-Besitzer Programm-Pfad Startbefehl+Parameter
svn stream tcp nowait svnowner /usr/bin/svnserve svnserve -i -r /var/svn

An dieser Stelle könnte man bereits versuchen, mit einem Client Zugriff auf das Repository zu erlangen. Dazu gibt man im Client einfach folgende URL an:

svn://localhost/repos

Der Zugriff auf das Repository schlägt jedoch fehl, weil wir svnserve noch nicht konfiguriert haben.

svnserve konfigurieren

Alle für die Konfiguration notwendigen Dateien liegen innerhalb des Repository-Verzeichnisses, in unserem Fall also innerhalb von /var/svn/repos. Dieses Verzeichnis enthält ein Unterverzeichnis conf/, in dem sich alle relevanten Konfigurationsdateien befinden:

Datei Funktion
authz Konfigurationsdatei, mit der sehr fein granulierte Zugriffe auf
das Repository eingestellt werden können.
passwd Enthält Benutzernamen und Passwort.
svnserve.conf Die Hauptkonfigurationsdatei für snvserve.

svnserve.conf bearbeiten

Das Bearbeiten der Konfigurationsdatei gestaltet sich sehr einfach, da sie bereits ausführlich kommentierte Standardeinstellungen enthält, die teilweise einfach nur einkommentiert werden müssen.

Zum Einstellen von svnserve öffnen wir zunächst die svnserve.conf. Im Abschnitt [general] müssen wir lediglich die Zeile mit password-db einkommentieren:

password-db = passwd

Die Option password-db enthält den Namen der Datei, die jeweils den Benutzernamen und das Passwort aller Benutzer enthält, die Zugriff auf das Repository erhalten. Standardmäßig ist dies passwd. Die Datei liegt im selben Verzeichnis wie svnserve.conf.

Die Option authz-db wird in diesem Beispiel nicht benötigt und sollte auskommentiert bleiben.

Die Option realm hingegen sollte einkommentiert werden und kann mit einem eigenen Namen ausgefüllt werden:

realm = Mein eigenes Repository

realm bezeichnet hier die Anmeldedomäne. Der Name ist frei wählbar und wird zusammen mit dem Hostnamen und dem Port des Servers als Anmeldenachweis benutzt.

Im folgenden Schritt müssen die Zugriffsrechte für anonyme und authentifizierte Nutzer eingerichtet werden. SVN unterscheidet hier zwischen drei möglichen Stufen:

Zugriffsoption Beschreibung
none Keine Zugriffsrechte
read Nur lesender Zugriff erlaubt
write Sowohl lesernder als auch schreibender Zugriff erlaubt.

Zunächst kommentieren wir die Option anon-access ein. Diese Option regelt die Zugriffsrechte für nicht authentifizierte anonyme User. Da wir dieser Nutzergruppe überhaupt keinen Zugriff gestatten möchten, setzen wir diese Option auf none:

anon-access = none

Schließlich kommentieren wir die Option auth-access ein. Diese Option regelt die Zugriffsrechte für authentifizierte User. Dieser Nutzergruppe wollen wir natürlich die vollen Zugriffsrechte geben – schließlich wollen wir selbst ja mit dem Repository arbeiten. Dazu setzen wir diese Option auf write:

auth-access = write

Im letzten Schritt müssen wir nur noch Benutzerkonten für das Repository anlegen.

passwd bearbeiten

Um Benutzerkonten für das Repository anzulegen, öffnen wir zunächst die Datei passwd, die im selben Verzeichnis zu finden ist wie svnserve.conf. Im Abschnitt [users] können wir nun ein Benuteraccount für das Repository anlegen, indem wir ein Paar bestehend aus Benutzername und Passwort einfügen. Benutzername und Passwort werden lediglich von einem ‘=‘ voneinander getrennt. Ein Beispiel sieht wie folgt aus:

[users]
harry = mysecretpassword
sally = mysecretpassword

Im obigen Eintrag sind also zwei Accounts definiert. Der Benutzername des ersten Accounts lautet harry und das dazugehörige Passwort ist mysecretpassword.

Nachdem alle gewünschten Accounts angelegt worden sind, kann der SVN-Server neu gestartet werden. Nach dem Neustart sind alle Accounts gültig und die angemeldeten Benutzer können mit ihren Clients auf das Repository zugreifen.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>