The trashiest blog in the World...

Aller au contenu | Aller au menu | Aller à la recherche

Mon GIT à la maison ! Git - Gitolite - cgit (ou gitweb)

Ces derniers temps, je m'intéresse de plus en plus à Git en remplacement partiel de mes anciens dépôts SVN (partiel seulement, car j'apprécie aussi Mercurial, certains de mes anciens projets ont dores et déjà migré).

Ce que je souhaite :

  • avoir un accès via le web au dépôt, au minimum pour consulter le code,
  • pouvoir assez facilement régler les droits en lecture et/ou écriture par dépôt.

Côté accès web, je dispose actuellement de nombreux outils pour naviguer dans mes dépôts SVN :

Mercurial n'est pas en reste ; puisqu'il est est facile de mettre en place une interface web de consultation des dépôts.

L'interface web, en plus de me permettre de consulter mes dépôts depuis n'importe quel matériel permet de lancer un navigateur web, donne aussi un aspect public pour mes projets (la plupart étant sous licence libre) ; l'écriture étant restreinte aux accès SSH.

Le pendant Git de ces interfaces est Gitweb, utilisé par de nombreux projets hébergé sous Git, comme le Projet Fedora par exemple. Cependant, j'ai très vite rencontré certaines « limites » avec gitweb, qui ne me semblent pas acceptables :

  • je ne suis pas parvenu (bien qu'à priori cela soit possible) à mettre en place le clonage des dépôts via HTTP :-/
  • lorsqu'un dépôt n'est pas autorisé en lecture à l'utilisateur spécial gitweb, il n'est certes pas affiché dans la liste des dépôts ; mais est tout de même accessible via l'interface, pour le peu que l'on connaisse le nom du dépôt !

J'ai donc décidé de me tourner vers une alternative à gitweb : cgit.

Bien entendu, des service d'hébergement Git tels que gitorious ou github existent ; mais ce n'est absolument pas envisageable pour le travail ; et à titre personnel, j'aurai aimé avoir des dépôts privés, ce qui n'est pas possible avec les formules gratuites de tels hébergeurs. De plus, seul gitorious repose actuellement sur des technologies libres...

En ce qui concerne la gestion des accès, j'avais évoqué ici-même l'utilisation de mercurial-server sous Fedora ; dont le pendant Git est gitolite (en quelque sorte le successeur de gitosis).

Let's go :

$ sudo yum install git-all gitolite

git-all installera l'ensemble des paquets git-* présents sur les dépôts, vous pouvez si vous le souhaitez préférer ne lister à la place que les paquets que vous souhaitez réellement installer :-)

gitolite

En plus des explications fournies ici, je vous conseille vivement de consulter la documentation d'installation de gitolite ;-)

Commençons par mettre en place gitolite. Le paquet présent sur les dépôts installera bien entendu tout ce dont vous aurez besoin :

  • les fichiers de l'application (ben oui, heureusement !),
  • un utilisateur dédié (gitolite),
  • un répertoire de stockage (/var/lib/gitolite - qui est également le $HOME de l'utilisateur gitolite).

Gitolite offre un accès aux dépôts Git via SSH. L'intégralité des dialogues avec le serveur passeront donc par l'utilisateur gitolite ; le programme se chargera ensuite de vérifier qui vous êtes et ce à quoi vous avez accès... ou pas :-p Il vous faut donc créer une clé SSH (si ce n'est déjà fait) :

$ ssh-keygen

Il faut ensuite copier la clé sur le serveur en la renommant de la forme username.pub. Il faudra pour la suite que cette clé soit lisible par l'utilisateur gitolite, la copier dans /tmp semble une bonne idée :

$ scp ~/.ssh/ir_rsa.pub user@server:/tmp/machin.pub

Note : le nom de la clé SSH n'est pas anodin. En effet, c'est sous ce nom que vous serez identifié ; et c'est celui qui sera utilisé un peu plus tard lors de la configuration des droits des dépôts. Cette remarque est valable d'une façon générale avec gitolite ; on y reviendra ;-)

Sur le serveur, il faudra ensuite initialiser gitolite :

# su - gitolite
$ gl-setup /tmp/machin.pub
creating gitolite-admin...
Initialized empty Git repository in /var/lib/gitolite/repositories/gitolite-admin.git/
[...]
 2 files changed, 6 insertions(+), 0 deletions(-)
 create mode 100644 conf/gitolite.conf
 create mode 100644 keydir/machin.pub

Et... Voilà ! Gitolite est installé et configuré sur votre serveur ; vous pouvez profiter de la magie !!

L'administration de Gitolite se fait par... un dépôt Git, on peut voir qu'il a été créé et peuplé par la commande gl-setup Récupérons un clone (depuis la machine sur laquelle est installée la clé SSH uploadée. Ben ouais ; faut suivre un peu ! :-D ) :

$ git clone gitolite@server:gitolite-admin.git

Examinons le dépôt ainsi cloné :

$ tree gitolite-admin 
gitolite-admin
|-- conf
|   `-- gitolite.conf
`-- keydir
    `-- machin.pub

On a donc un dossier conf qui contient l'unique fichier de configuration de gitolite ; et un dossier keydir dont la fonction est de recevoir toutes les clés des utilisateurs. Le fichier de configuration par défaut donne tous les droits à l"utilisateur machin sur le dépôt d'administration, un dépôt de test accessible librement à tous créé à l'initialisation est aussi configuré :

$ cat conf/gitolite.conf
        repo    gitolite-admin
                RW+     =   machin

        repo    testing
                RW+     =   @all

        repo    mailletest
                RW+      =  machin chouette
                R        =  chose gitweb

Pour créer un nouveau dépôt, il suffit d'ajouter l'entrée au fichier de configuration. Dès que vous aurez fait un git push dans le dépôt gitolite-admin, le nouveau dépôt sera initialisé automatiquement. Cool, non ? :-p
Le dépôt ajouté portera le nom mailletest ; il sera accessible en lecture/écriture aux autilisateurs machin et chouette, en lecture seule pour les utilisateurs chose et gitweb. N'oubliez pas dans ce cas d'ajouter les fichiers chouette.pub et chose.pub dans le dossier keydir, et de les ajouter au dépôt avant de commiter. En cas d'oubli, gitolite se fera un plaisir de vous informer que le ou les utilisateurs qui ont été configurés n'ont pas de clé. L'utilisateur gitweb est particulier, il définit la liste des dépôts qui seront exportés dans le fichier projects.list.

$ git add
$ git commit conf/gitolite.conf -m"Test de création de dépôt"
[...]
$ git push 
[...]
remote: Initialized empty Git repository in /var/lib/gitolite/repositories/mailletest.git/
[...]

Votre installation de gitolite est complète, votre premier dépôt est créé ! Que demander de plus ? Ha oui, une interface web on avait dit...

Si vous souhaitez en savoir plus sur les possibilités de gitolite :

Interface web

Si vous souhaitez utiliser une des interfaces web sur les futurs dépôts créés, il faudra effectuer une petite modification supplémentaire dans la configuration de gitolite. Dans le fichier /var/lib/gitolite/.gitolite.rc, changez la valeur pour $REPO_UMASK de 0077 à 0027 (les commentaires présents dans le fichier devraient être assez parlants).

La configuration expliquée ici est basée sur le serveur web Apache HTTPD. Il est évidemment possible d"utiliser les différentes interfaces web à Git avec n'importe quel serveur web capable de faire du CGI, mais cela dépasse largement le cadre de ce tutoriel.

Notez que lors de l'installation des paquets de chacune des interfaces présentées ici, un fichier de configuration par défaut sera placé dans le dossier /etc/httpd/conf.d/, nommés respectivement cgit.conf, git.conf et webgit-caching.conf. Comme nous utiliserons un hôte virtuel dédié, nous commenterons chacune des lignes présentes dans le fichier par défaut (on ne supprime pas le fichier, puisqu'il est fourni avec le paquet RPM ;-) ).

Chaque dépôt sur le serveur requiert d'être initialisé pour répondre aux requêtes HTTP :

$ cd /var/lib/gitolite/repositories/mailletest.git
$ git update-server-info

L'opération est à répéter après chaque commit. Évidemment, il y a une solution automatisée, le faire à la main n'est même pas envisageable ;-) Utilisons les hooks pour parvenir à nos fins, l'opération sera automatiquement effectuée sur le dépôt après chaque commit :

$ cd /var/lib/gitolite/repositories/mailletest.git
$ cp ./hooks/post-update.sample ./hooks/post-update
$ chmod +x ./hooks/post-update

Gérer les droits...

On arrive à une partie un peu plus sensible : la gestion des droits. En effet, les dossiers et les dépôts créés sont par défaut uniquement accessibles à l'utilisateur gitolite ; mais nous souhaitons que l'utilisateur apache puisse y accéder. Heureusement, nous avons modifié les REPO_MASK de gitolite. Voyons ce qu'on a :

# ls -al /var/lib/gitolite/projects.list
-rw-------. 1 gitolite gitolite 0 16 sept. 23:43 /var/lib/gitolite/projects.list
#  `--# ls -al /var/lib/gitolite/repositories 
total 40
drwxrwxr-x. 5 gitolite gitolite 4096 16 sept. 23:43 .
drwxr-x---. 5 gitolite gitolite 4096 16 sept. 23:13 ..
drwx------. 8 gitolite gitolite 4096 16 sept. 23:43 gitolite-admin.git
drwxr-x---. 7 gitolite gitolite 4096 16 sept. 23:43 mailletest.git
drwx------. 7 gitolite gitolite 4096 16 sept. 23:43 testing.git

Ok, commençons par ajouter l'utilisateur apache au groupe gitolite. Une fois cela fait, le dépôt nouvellement créé (mailltest.git) sera accessible depuis le web ; mais pas gitolite-admin, c'est voulu. En effet, je ne souhaite vraiment pas que le dépôt de configuration soit accessible par le web ; ne pas pas autoriser le serveur à lire son contenu est un bon moyen ; bien qu'il soit aussi possible de configurer les dépôts que gitweb n'affichera pas... L'un n'exclut de toutes façons pas l'autre « Deux précautions valent mieux qu'une ».
Nous aurons aussi à adapter les droits sur le fichier projects.list pour que apache puisse le lire :

# usermod -a -G gitolite apache
# chmod g+r /var/lib/gitolite
# chmod g+r /var/lib/gitolite/projects.list

SELinux...

Mais-heu ! SELinux, il est méchant avec moi, il me bloque l'accès à mes jolis dépôts Git avec lesquels moi je veux m'amuser !

Si SELinux est activé (je ne vois pas pourquoi il ne le serait pas, à plus forte raison sur un serveur !!), l'accès aux fichiers et dossiers de Git sera bloqué depuis les interfaces web. Il semble que la solution consiste à utiliser le contexte git_system_content_t sur les fichiers adéquats.

Toutefois, appliquer ce contexte sur certains dossiers pourrait poser problème. Un mauvais contexte sur le dossier ~/.ssh entraînerait l'impossibilité de se connecter au dépôt via SSH... Plutôt gênant, non ? :-p
J'ai donc choisi de modifier le dossier home de l'utilisateur pour séparer les données système de l'utilisateur, et les données des dépôts Git :

# usermod -d /home/gitolite -m gitolite
# mkdir /var/lib/gitolite && chown -R gitolite:gitolite /var/lib/gitolite
# chmod o-rx /var/lib/gitolite
# mv /home/gitolite/* /var/lib/gitolite/
# mv /home/gitolite/.gitolite* /var/lib/gitolite
# su - gitolite
$ ln -s /var/lib/gitolite/* .
$ ln -s /var/lib/gitolite/.gitolite* .

Appliquons maintenant le contexte SELinux adéquat :

# semanage fcontext -a -t git_system_content_t '/var/lib/gitolite(/.*)?'
# restorecon -R -v /var/lib/gitolite

Bon... On ne devrait pas être trop mal là :-) Lancez donc votre navigateur sur votre sous domaine, et voyez si ça fonctionne !

En cas de problèmes :

  • si c'est SELinux qui bloque, les erreurs vous seront signalées dans /var/log/messages ou /var/log/audit/audit.log,
  • s'il s'agit de problèmes de droits ; vous n'obtiendrez pas d'erreurs dans les logs, juste un 404 dans le navigateur. Assurez vous que le groupe ait le droit de lire les fichier et dossiers, et de traverser les dossiers,
  • tout semble correct, et pourtant, votre dépôt n'apparaît pas ? Vérifiez que vous avez bien ajouté les droits en lecture sur le dépôt pour l'utilisateur gitweb dans la configuration de gitolite.

cgit

Cgit est est une application CGI écrite en C, un peu comme gitweb. Pour l'installer :

$ sudo yum install cgit

La configuration de cgit passe par le fichier /etc/cgitrc. Il suffira d'ajouter les lignes suivantes à ce fichier :

enable-gitweb-owner=1
project-list=/var/lib/gitolite/projects.list
scan-path=/var/lib/gitolite/repositories/

Ensuite, nous configurerons notre hôte virtuel apache pour utiliser cgit :

# git repositories
<VirtualHost *:80>
        ServerName git.domain.com

        # Logs :
        ErrorLog /var/log/httpd/git_error_log
        CustomLog /var/log/httpd/git_access_log combined

        Alias /cgit-data /usr/share/cgit
        ScriptAlias /cgit /var/www/cgi-bin/cgit

        RewriteEngine on
        RewriteCond %{REQUEST_URI} !^/cgit
        RewriteRule (.*) http://git.domain.com/cgit$1 [P]

        <Location />
                Options FollowSymLinks

                # Limitation commits
                <Limit POST PUT>
                        Require valid-user
                </Limit>
        </Location>
</VirtualHost>

Vous aurez ainsi accès à l'interface cgit depuis l'URL http://git.domaine.com ; et pourrez cloner un dépôt en utilisant le protocole HTTP :

$ git clone http://git.domaine.com/mailletest.git

Vous pouvez afficher automatiquement les différents URL de clonage de vos dépôts via cgit, en renseignant dans le fichier de configuration :

clone-prefix=http://git.domain.com ssh://gitolite@git.domain.com

gitweb

Gitweb est aussi une application CGI. Pour l'installer :

$ sudo yum install gitweb

Créons ensuite notre hôte virtuel dans le fichier /etc/httpd/conf.d/git.mondomaine.com.conf avec le contenu suivant :

# git repositories
<VirtualHost *:80>
        ServerName git.mondomaine.com
        DocumentRoot /var/www/git/

        # Logs :
        ErrorLog /var/log/httpd/git_error_log
        CustomLog /var/log/httpd/git_access_log combined

        <Directory /var/www/git>
                DirectoryIndex gitweb.cgi
                Options ExecCGI FollowSymLinks

                ## Controls who can get stuff from this server.
                Order allow,deny
                Allow from all

                <Files gitweb.cgi>
                        SetHandler cgi-script
                </Files>

                # Limit commits
                <Limit POST PUT>
                        Require valid-user
                </Limit>

                # Redirections
                RewriteEngine on
                RewriteRule ^$ gitweb.cgi [L]
                RewriteCond %{REQUEST_FILENAME} !-f
                RewriteCond %{REQUEST_FILENAME} !-d

                RewriteRule (.*) /gitweb.cgi/$1 [QSA,L]
        </Directory>
</VirtualHost>

Le fichier de configuration principal de GitWeb se trouve à /etc/gitweb.conf. Pour notre configuration, il faut simplement configurer deux choses : le fichier qui liste les projets, et le dossier contenant les différents dépôts. On ajoutera donc au fichier gitweb.conf les lignes suivantes :

$projects_list = "/var/lib/gitolite/projects.list";
$projectroot = "/var/lib/gitolite/repositories/";
Clonage via http

Le clone d'un dépôt en utilisant le protocole HTTP n'est pas natif avec la configuration mise en place. D'abord, nous allons ajouter sur la pages des différents projets l'URL de clonage. Ajoutez la ligne suivante dans le fichier /etc/gitweb.conf

@git_base_url_list = qw(http://git.mydomain.com)

Normalement, il suffit d'ajouter une règle de ré-écriture semblable à celle-ci pour que le clonage avec une adresse du type http://git.domain.com/mailletest.git soit opérationnel :

RewriteRule ^/(.*\.git/(?!/?(HEAD|info|objects|refs)).*)?$ gitweb.cgi%{REQUEST_URI}  [L,PT]

Je ne suis cependant pas encore parvenu à faire fonctionner ceci :'(

gitweb-caching

giweb-caching fournit les mêmes fonctionnalités que gitweb, mais avec le support du cache en sus. Pour l'installer :

$ sudo yum install gitweb-caching

Pour l'activer il suffira de remplacer les deux occurrences /var/www/git par /var/www/gitweb-caching dans le fichier de configuration de l'hôte virtuel apache.

Le script CGI installé par défaut ne possède pas le contexte SELinux adéquat pour fonctionner, il faudra le modifier :

# semanage fcontext -a -t httpd_git_script_exec_t '/var/www/gitweb-caching/gitweb.cgi'
# restorecon -v /var/www/gitweb-caching/gitweb.cgi

Et c'est tout ! :-)

Notez que les remarques concernant le clonage de dépôts par HTTP sont également valables pour gitweb-caching :'(

Commentaires

1. Le dimanche 18 septembre 2011, 02:04 par llaumgui

Sinon il y a Indefero qui est tout en 1 : Mercurial, GIT et SVN. Il gère à la fois les repositories et le mode web.

2. Le dimanche 18 septembre 2011, 11:00 par trashy

Une petite coquille s'était glissée dans l'article, que je viens de corriger.

En effet, je faisais mention pour le clonage de dépôts via HTTP au hook post-commit... Il s'agissait en fait de post-update.

3. Le lundi 19 septembre 2011, 04:31 par bochecha

> "Bien entendu, des service d'hébergement Git tels que gitorious ou github existent ; mais ce n'est absolument pas envisageable pour le travail ;"

Tu veux dire que pour certaines raisons vous pouvez pas vous heberger un Gitorious au travail ?

   [https://gitorious.org/gitorious/pages/Home]
4. Le lundi 19 septembre 2011, 07:30 par trashy

@bochecha : non... À vrai dire, je n'y avais même pas songé ; j'ai ajouté la partie sur les github/gitorious alors que le billet était déjà bien avancé :-) Ce sont leur service en ligne que nous ne pouvons pas utiliser.