Mon GIT à la maison ! Git - Gitolite - cgit (ou gitweb)
Par trashy le samedi 17 septembre 2011, 22:11 - PenguinLand - Lien permanent
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$HOMEde l'utilisateurgitolite).
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 !
) :
$ 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/messagesou/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
gitwebdans 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
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.
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 depost-update.> "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 ?
@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.
Salut,je tiens à vous dire un grand merci pour votre contribution sur ce sujet. Votre analyse est la bonne. Bonne journée.