git

Mon réseau

Ça faisait un petit moment que je devais refaire ma homepage. C'est chose faite (rechargez la page si vous avez encore l'ancienne en cache, c'est full statique avec un trèèèès long ttl).

J'y décris un peu ce qui se passe dans les trois serveurs que j'administre, pour moi, pour les amis, pour des logiciels libres comme wmfs et pour les causes que je défends avec une association, le cerf de grésigne et un miroir wikileaks.

En modifiant ma map nagios j'ai réussi à faire quelque chose de pas mal pour mieux visualiser la chose :

network

Ça fait maintenant deux ans que l'aventure a commencée, objectif auto-hébergement et auto-formation à l'administration systèmes. Je dois dire que ça a plutôt bien marché puisque l'infrastructure et mes connaissances n'ont cessés de progresser.

  • Fin 2008 Pendant les 3 premiers mois philpep.org n'existait que sur mon portable (sous gentoo, allumé 24h/24), c'était un serveur git pour partager mon code.
  • Début 2009 j'ai récupéré un vieux pentium III gracieusement donné par une association Toulousaine sur lequel j'ai installé FreeBSD (7.0 puis 7.1) qui a commencé à faire du mail.
  • Mai 2009 je récupère un pentium 4 avec plus de RAM.
  • Fin 2009 je m'achète une alix2d3
  • Début 2010 je prends une machine virtuelle chez lost-oasis (sous FreeBSD puis Debian) pour fournir un MX et DNS secondaire.
  • Juillet 2010 je m'achète une nouvelle machine avec plus de RAM et qui consomme moins
  • Fin 2010, la machine virtuelle est maintenant chez Hetzner, et sous FreeBSD 8.1 avec un vpn entre mes deux locations.

installation serveur git avec gitosis, lighttpd et cgit

date
11 / 8 / 2010
comments
1

Pour faire revivre un peu ce blog déserté (en particulier par moi même), un petit billet sur la config de mon serveur git.

Les dépôts git peuvent se trouver sous deux formes :

  • Une forme pour le développeur/contributeur, c'est ce qu'on obtient avec git clone
  • Une forme pour le serveur, que l'on a avec git clone --bare

En fait on clone toujours depuis un dépôt bare, de la même manière on push sur un dépôt bare.

% git clone --bare git://git.wmfs.info/wmfs.git
Initialized empty Git repository in /tmp/wmfs.git/
remote: Counting objects: 5011, done.
remote: Compressing objects: 100% (1096/1096), done.
remote: Total 5011 (delta 3909), reused 5011 (delta 3909)
Receiving objects: 100% (5011/5011), 844.06 KiB, done.
Resolving deltas: 100% (3909/3909), done.

% ls wmfs.git
branches  config  description  HEAD  hooks  info  objects  packed-refs  refs

% git clone ./wmfs.git
Initialized empty Git repository in /tmp/wmfs/.git/

% ls wmfs
CMakeLists.txt  cmake_uninstall.cmake.in  COPYING  rc  README  src  TODO  wmfs.1  wmfs.desktop  wmfs.doxygen.in  wmfsrc.in

Dans ce dépôt bare il y a tout un tas de choses, notamment les hooks qui permettent de lancer des commandes avant/après un push et tout autre sortes d'événements.

Git permet de cloner/pusher depuis/vers des dépôts bare d'au moins trois manières différentes.

  • Par ssh
  • Par le protocole git (sur le port 9418 par défaut)
  • Par http

Pour ssh, si la sécurité nécessite d'avoir des droits par utilisateurs on peut utiliser gitosis qui va créer un utilisateur git avec un ~git/.ssh/authorized_keys qui limite l'accès aux utilisateurs.

L'install et l'utilisation est simplisme, voyez la doc de gitosis pour faire des choses plus velues :

% make -C /usr/ports/devel/py-gitosis install
% sudo -H -u git gitosis-init < /votre/clef/ssh/publique/id_rsa.pub
% git clone git@serveur:gitosis-admin.git
% cd gitosis-admin    
% >> gitosis.conf
[repo foo]
daemon = yes
^D
% git commit -a -m "Ajout depot foo" && git push
% mkdir /tmp/foo && cd /tmp/foo
% echo "foo" > bar
% git init
% git add bar
% git remote add origin git@serveur:foo.git
% git push origin master:refs/heads/master

Et voilà votre premier dépot git.

Bon là par ssh, seuls les utilisateurs autorisés pourront cloner. Il nous faut un moyen public pour permettre à quiconque de cloner.

Par le protocole git c'est très facile :

% >> /etc/rc.conf
git_daemon_enable="YES"
git_daemon_directory="--base-path=/usr/local/git/repositories"
^D
% /usr/local/etc/rc.d/git_daemon start
# Testons par le protocole git
% git clone git://serveur/foo.git

Mais si vous voulez offrir un service un peu plus complet comme github, il faut permettre le clone par http parce que si les utilisateurs sont derrière un firewall nazi qui laisse passer que le port 80 sortant ils ne pourrons pas contribuer à vos softs.

Pour celà il suffit de configurer le serveur web qui sert /usr/local/git/repositories, ainsi nos amis nazis pourront faire du git clone http://serveur/foo.git.

Allons y avec lighttpd puisqu'il faut faire un choix.

% >> /usr/local/etc/lighttpd.conf
$HTTP["host"] == "serveur" {
    server.document-root = "/usr/local/git/repositories"
}
% /usr/local/etc/rc.d/lighttpd reload
% git clone http://serveur/foo.git
# Arf ça marche pas, permission denied
% cd /usr/local/git/repositories
% chmod o+rx foo.git
% git clone http://serveur/foo.git
# Arf, ça marche toujours pas, il me cause d'un git update-server-info
% cd /usr/local/git/repositories/foo.git
% git update-server-info
% cp hooks/post-update.sample hooks/post-update
% git clone http://serveur/foo.git
\o/

Bon et pour faire un peu plus "pro", il nous faut un gitweb celui par défaut en perl me plait pas trop, je préfère nettement cgit

% make -C /usr/ports/devel/cgit
% >> /usr/local/etc/cgitrc
clone-prefix=git://serveur
virtual-root=/
snapshots=tar.gz tar.bz2

repo.url=foo.git
repo.path=/usr/local/git/repositories/foo.git
^D

Comme on est malins, on va le mettre sur le même virtualhost. Et on va faire même encore plus fort, on va le mettre le gitweb ET le clone sur http://serveur/foo.git.

Pour ça il faut matcher le client git dans la conf lighttpd :

$HTTP["host"] = "serveur" {
    server.document-root = "/usr/local/git/repositories"
    # Et si ce n'est pas le client git
    $HTTP["useragent"] !~ "^git" {
         server.document-root = "/usr/local/www/cgit/"
         index.file.name = ("cgit.cgi")
         cgi.assign ("cgi.git" => "")
         server.error-handler-404 = "cgit.cgi"
         url.rewrite-once = ("^/([^?/]+/[^?]*)?(?:\?(.*))?$" => "/cgit.cgi?url=$1&$2")
     }
}

(D'ailleurs je me demande si y'a pas un morceau de code qui fait ça tout seul dans cgit... à voir).

Voilà, mettez vos petits softs sur le nainternet et attendez les contributions ;)

Si vous voulez aller encore plus loin, mettez un bot irc qui parle quand ça push sur le dépôt git.

Un bot IRC à la CIA en python

date
9 / 5 / 2010
comments
0

Quand vous utilisez git à plusieurs et qu'en plus vous utilisez IRC pour en discuter, il peut être agréable d'avoir un bot qui informe le canal des commit sur le serveur. En particulier pour éviter des merge branch à tout va si on oublie de pull avant de commit. Il y a un service sur le net qui propose de tels bots IRC, c'est CIA.vc. Sauf que le service est à des fins de statistiques sur les logiciels libres et j'aime pas trop que ces données sortent du serveur même si elles sont publiques, puis leur bot on sait pas trop ce qu'il fait.

Donc je me suis mis à coder ce petit bot en python qui se connecte sur le canal IRC et attend des ordre via xmlrpc, cet ordre est lancé à chaque commit via un hooks sur le serveur git.

Pour ça, tout est dans la librairie python standard, sauf irclib et gitpython.

Le serveur (j'ai enlevé toutes les fonctionnalités qui ne rentrent pas dans le cadre de ce billet) :

#!/usr/bin/env python

import threading
import irclib

chan = '#staff'
nick = 'napalm0'
server = ('irc.philpep.org', 6667)
xmlrpcserver = ('localhost', 8888)

class PbotIRCClient(irclib.SimpleIRCClient):
    def on_welcome(self, s, e):
        s.join(chan)

# Classe de contrôle du bot par xmlrpc
class PbotControl:
        def commit(self, name, files, summary, base, id):
                # On formate la chaine de commit (Projet: Commiter (fichiers_touchés) sommaire_du_commit
                str = '%s: %s (\x0323%s\x03) %s' % (base, name, files, summary)
                pbot.connection.privmsg(chan, str)
                # Et un lien vers le commit diff
                pbot.connection.privmsg(chan, 'http://git.philpep.org/'+base+'.git/commit/?id='+id)

# Le serveur xmlrpc
class PbotXMLRPCServer(threading.Thread):
        def run(self):
                obj = PbotControl()
                srv = SimpleXMLRPCServer(xmlrpcserver, allow_none=True)
                srv.register_instance(obj)
                srv.serve_forever()

if __name__ == '__main__':
    pbot = PbotIRCClient()
    pbot.connect(server[0], server[1], nick)
    t = PbotXMLRPCServer()
    t.start()
    pbot.start()

Et le hooks à mettre dans le bare repo hooks/post-commit :

#!/usr/bin/env python

from sys import argv
from git import Repo
from xmlrpclib import ServerProxy

# Path vers le bare repo (peut être avec '.' ça marche aussi ?)
r = Repo('/usr/home/git/repositories/pblog2.git')
c = r.commit(argv[1])
s = ServerProxy('http://localhost:8888', allow_none=True)
# Liste des fichiers touchés par le commit
try:
        file = ' '.join([e.a_blob.path for e in c.diff(r, c.parents[0])])
except:
        file = ''
# Appel de la méthode xmlrpc
s.commit(c.author.name, file, c.summary, 'pblog2', argv[1])

Voilà, en quelques lignes de python vous avez un bot sympa et vous savez comment il fonctionne laissez parler votre imagination pour l'améliorer.

git-daemon sous FreeBSD

date
26 / 1 / 2010
comments
0

Si vous avez un serveur git sous FreeBSD, vous aurez très rapidement des problèmes avec /usr/local/etc/rc.d/git_daemon, genre il démarre mal, et refuse de redémarrer.

En fait il suffit d'utiliser l'option --reuseaddr qui passe SO_REUSEADDR à setsockopt pendant la création du socket serveur. Du coup il peut redémarrer même si il y avait une connexion active sur le port.

En lisant le script rc, on peut même éviter de le modifier et devoir le refaire à chaque mise à jours de git, dans /etc/rc.conf

git_daemon_enable="YES"
git_daemon_directory="--reuseaddr --base-path=/usr/home/git/repositories"

EDIT : ce n'est plus nécessaire maintenant PR ports/143275

Gitweb fastcgi lighttpd et FreeBSD

date
10 / 9 / 2009
comments
0

Vu la galère pour mettre en place un gitweb sous lighttpd en fastcgi, voici un petit mémo pour moi et j'èspère qu'il servira à d'autres. (J'explique sous FreeBSD mais ça peut être transposé facilement sur d'autres OS)

Donc, d'abord mettre en place git et lighttpd :

make -C /usr/ports/devel/git install clean
make -C /usr/ports/www/lighttpd install clean
echo lighttpd_enable=\"YES\" >> /etc/rc.conf

Ensuite j'ai utilisé un script de la doc lighttpd.

fetch http://philpep.org/pub/perl-cgi
mv perl-cgi /usr/local/bin

Ce script utilise deux modules Perl qu'il faut installer, le premier (CGI::Fast) est dans les ports FreeBSD, mais je n'ai pas trouvé le second (Embed::Persistent) donc je l'ai installé "à la mano"

make -C /usr/ports/www/p5-FastCGI install clean
fetch http://search.cpan.org/CPAN/authors/id/D/DO/DOUGM/ExtUtils-Embed-1.14.tar.gz
tar xvzf ExtUtils-Embed-1.14.tar.gz
cd ExtUtils-Embed-1.14
perl Makefile.PL
make
make install

Ensuite la conf lighttpd : (je met tout dans /usr/local/www)

cp /usr/local/share/examples/git/gitweb/gitweb* /usr/local/www
cp /usr/local/share/examples/git/gitweb/*.png /usr/local/www

Et ceci dans /usr/local/etc/lighttpd.conf

# /usr/local/etc/lighttpd.conf
server.port = 80
server.bind = "10.0.0.3"
server.username = "www"
server.groupname = "www"
server.document-root = "/usr/local/www/"
server.event-handler = "freebsd-kqueue"
server.pid-file = "/var/run/lighttpd.pid"
index-file.names = ( "gitweb.cgi" )
server.errorlog = "/var/log/error_log"

server.modules  = (
      "mod_setenv",
      "mod_fastcgi",
      "mod_rewrite",
      )

fastcgi.server = ( ".cgi" =>
      (( "socket" => "/tmp/application.fcgi.socket",
         "bin-path" => "/usr/local/bin/perl-cgi",
       ))
      )

setenv.add-environment = (
      "GITWEB_CONFIG" => "/home/git/gitweb.conf",
      )

# Le petit rewrite qui fait bien
url.rewrite-once = ( "^/([a-zA-Z]+.git)(.*)$" => "/gitweb.cgi/$1$2" )

mimetype.assign             = (
      ".png"          =>      "image/png",
      ".css"          =>      "text/css",
# default mime type
      ""              =>      "application/octet-stream",
      )

Et voilà, un petit

/usr/local/etc/rc.d/lighttpd start