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 !
) :
$ 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 :'(