Tag Archives: gitolitev3

today’s buzzwords: gitolitev3, gitweb, nginx, gitolite-shell

NOTE: This article has not been written by me. The author is someone who is able to do all this magic stuff, but still hasn’t managed to create an account on noblogs.org. Go figure.

We would set up gitolite with wild repos to have a structure like CREATOR/..* , so for example the amin manages the keys and everyone can have her repositories and permission config (given the roles supplied by the aministrator). The hosting user of gitolite will be `git` with home directory /srv/vcs/git/ and the one for nginx will be `www-data` with base root in /srv/www/hostname/ (put www-data in the git group with gpasswd -a www-data git).

We will have key authenticathed repositories with ssh, and anonymous one by https (if you like you could switch basic auth in nginx and have out of the box authenticated gitolite access).

To create a new repo a user gives the gitolite admin her ssh keys, and then does

git clone git@hotname:user/repo.git

Now to give read permission to user2 she does

ssh git@hostname perms user/repo + READERS user2

Finally, to have a repo with gitweb and anonymous clone she does

ssh git@hostname perms user/repo + READERS @PUB

In debian wheezy there is still no gitolite 3, pull that from source.
install it and config a gitolite-admin like this:

 repo gitolite-admin
      RW+     =   admin

  @PUB = gitweb daemon

  repo    CREATOR/..*
      C   =   @all
      RW+D =   CREATOR
      RW  =   WRITERS
      R   =   READERS

      config  gitweb.url = git clone https://hostname/%GL_REPO.git
      config  gitweb.owner = %GL_CREATOR
      config  receive.denyNonFastforwards = true

in /srv/vcs/git/.gitolite.rc modify

UMASK                       =>  0027,
GIT_CONFIG_KEYS             =>  'gitweb\.(owner|description|category|url) receive.denyNonFastforwards receive.denyDeletes',
COMMANDS                    =>
     {
            'help'              =>  1,
            'desc'              =>  1,
            # 'fork'            =>  1,
            'info'              =>  1,
            # 'mirror'          =>  1,
            'perms'             =>  1,
            # 'sskm'            =>  1,
            'writable'          =>  1,
            'D'               =>  1,
        },

sskm is useful to have users upgrade their supplied ssh keys, activate it if needed.

Now configure gitweb to use gitolite-shell to manage authorization and put those files in /srv/www/hostname/ , for exampe put there gitweb.conf site/gitweb.css site/gitweb.js etcetera.

# ----------------------------------------------------------------------

# Per-repo authorization for gitweb using gitolite v3 access rules
# Read comments, modify code as needed, and include in gitweb.conf

# Please note that the author does not have personal experience with gitweb
# and does not use it.  Some testing may be required.  Patches welcome but
# please make sure they are tested against a "github" version of gitolite and
# not an RPM or a DEB, for obvious reasons.

# ----------------------------------------------------------------------

# First, run 'gitolite query-rc -a' (as the gitolite hosting user) to find the
# values for GL_BINDIR and GL_LIBDIR in your installation.  Then use those
# values in the code below:

BEGIN {
    $ENV{HOME} = "/srv/vcs/git/";   # or whatever is the hosting user's $HOME
    $ENV{GL_BINDIR} = "/usr/share/gitolite";
    $ENV{GL_LIBDIR} = "/usr/share/gitolite/lib";
}

# Pull in gitolite's perl API module.  Among other things, this also sets the
# GL_REPO_BASE environment variable.
use lib $ENV{GL_LIBDIR};
use Gitolite::Easy;
use CGI;
my $cgi = new CGI;

# Set projectroot for gitweb.  If you already set it earlier in gitweb.conf
# you don't need this but please make sure the path you used is the same as
# the value of GL_REPO_BASE in the 'gitolite query-rc -a' output above.
$projectroot = $ENV{GL_REPO_BASE};

# Now get the user name.  Unauthenticated clients will be deemed to be the
# 'gitweb' user so make sure gitolite's conf file does not allow that user to
# see anything sensitive.
$ENV{GL_USER} = $cgi->remote_user || "gitweb";

$export_auth_hook = sub {
    my $repo = shift;
    # gitweb passes us the full repo path; we need to strip the beginning and
    # the end, to get the repo name as it is specified in gitolite conf
    return unless $repo =~ s/^\Q$projectroot\E\/?(.+)\.git$/$1/;

    # call Easy.pm's 'can_read' function
    return can_read($repo);
};

# stylesheet to use
$stylesheet = "gitweb.css";

# javascript code for gitweb
$javascript = "gitweb.js";

# logo to use
$logo = "git-logo.png";

# the 'favicon'
$favicon = "git-favicon.png";

# enable nicer uris
$feature{pathinfo}{default} = [1];
#
# # root link text
$home_link_str = 'hostname';
$site_name = 'hostname';

Now configure nginx to serve gitweb and gitolite-shell for anonimous clone, not the default paths of gitweb.cgi and gitolite-shell that are the defaults in debian.

server {
    listen   [::]:80;
    server_name hostname;
    rewrite ^ https://$uri permanent;
}
server {
    listen [::]:443 ssl;

    ssl_certificate /etc/ssl/private/nginx/web.pem;
    ssl_certificate_key /etc/ssl/private/nginx/web.key;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
    ssl_prefer_server_ciphers on;

    server_name hostname;

    access_log /srv/www/hostname/log/nginx/access.log;
    error_log /srv/www/hostname/log/nginx/error.log;

    root /srv/www/hostname/;

    # static repo files for cloning over https
    # requests that need to go to git-http-backend
    location ~ ^(.*\.git/objects/([0-9a-f]+/[0-9a-f]+|pack/pack-[0-9a-f]+.(pack|idx)))|(^.*\.git/(HEAD|info/refs|objects/info/.*|git-(upload|receive)-pack))$ {
        root /srv/vcs/git/;

        fastcgi_param HTTPS on;
        fastcgi_param SCRIPT_FILENAME   /usr/bin/gitolite-shell;
        fastcgi_param PATH_INFO         $uri;
        fastcgi_param GITOLITE_HTTP_HOME  /srv/vcs/git;
        fastcgi_param GIT_PROJECT_ROOT  /srv/vcs/git/repositories;
        if ($remote_user ~ ""){
            set $user "gitweb";
        }
        if ($remote_user !~ ""){
            set $user $remote_user;
        }

        fastcgi_param REMOTE_USER $user;
        include fastcgi_params;
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
    }

    location ~ .cgi {
        try_files @gitweb 404.html;
    }
    location ~ ^/site/ {
        try_files $uri 404.html;
    }
    # send anything else to gitweb if it's not a real file
    location /  {
        fastcgi_param HTTPS on;
        fastcgi_param SCRIPT_FILENAME   /usr/share/gitweb/gitweb.cgi;
        fastcgi_param PATH_INFO         $uri;
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_param GITWEB_CONFIG     /srv/www/hostname/gitweb.conf;
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
   }
}