Search code examples
gitgitolitegitweb

git-http-backend returns error 502


I'm running gitweb and gitolite on my server: http://git.jshawl.com/

I'm having trouble setting up the git-http-backend to allow anonymous cloning.

Here's what my vhosts file (/etc/apache2/extra/httpd-vhosts.conf) looks like:

<VirtualHost *:80>
DocumentRoot "/Users/git/repositories"
ServerName git.jshawl.com
 <Directory "/Users/git/repositories">
    Options ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch
    AllowOverride All
    order allow,deny
    Allow from all
    AddHandler cgi-script cgi
    DirectoryIndex gitweb.cgi
</Directory>

<LocationMatch "^/.*/git-receive-pack$">
    AuthType Basic
    AuthName "Git Access"
    Require group committers
</LocationMatch

SetEnv GIT_PROJECT_ROOT /Users/git/repositories
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAliasMatch \
    "(?x)^/(.*/(HEAD | \
        info/refs | \
            objects/(info/[^/]+ | \
                [0-9a-f]{2}/[0-9a-f]{38} | \
                    pack/pack-[0-9a-f]{40}\.(pack|idx)) | \
            git-(upload|receive)-pack))$" \
    /usr/libexec/git-core/git-http-backend/$1

ScriptAlias / /Users/git/repositories/gitweb.cgi/

`

I followed the directions here: http://www.kernel.org/pub/software/scm/git/docs/git-http-backend.html, but am consistently confronted with that 502 error.

My apache error log says: [Fri Aug 24 19:29:32 2012] [error] [client 198.228.200.148] client denied by server configuration: /usr/libexec/git-core/git-http-backend

Also, adding all of this has taken down my gitweb installation (which used to be at http://git.jshawl.com)

What am I doing wrong?


Solution

  • Here is another approach in this httpd.conf which works well for cloning/pushing/pulling, but it doesn't call gitweb.cgi:

    GitWeb is for browsing, not for cloning

    (small extract, removing Auth details, and SSL details)

    # GitHttp on @PORT_HTTP_HGIT@
    Listen @PORT_HTTP_HGIT@
    <VirtualHost @FQN@:@PORT_HTTP_HGIT@>
      ServerName @FQN@
      ServerAlias @HOSTNAME@
      SetEnv GIT_PROJECT_ROOT @H@/repositories
      SetEnv GIT_HTTP_EXPORT_ALL
      SetEnv GITOLITE_HTTP_HOME @H@
      ScriptAlias /hgit/ @H@/gitolite/bin/gitolite-shell/
      SetEnv GIT_HTTP_BACKEND "@H@/usr/local/apps/git/libexec/git-core/git-http-backend"
      <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
      </FilesMatch>
      <Location /hgit>
        AddHandler cgi-script cgi
      </Location>
    </VirtualHost>
    

    In other words:

    • git-http-backend is referenced by the variable GIT_HTTP_BACKEND, but you won't need it if you are using Gitolite V3.
    • gitolite-shell is called when you are using /hgit/ in your cloning address: theat GitoliteV3 script will check if you have the right to clone the repo, and if yes, will call the commands behind the script git-http-backend: 'git-receive-pack' (for push) or 'git-upload-pack' (for clone/pull/fetch), straight from the git source itself http-backend.c.

    So:

    git clone https://yourServer/hgit/yourRepo
    

    Will call gitolite, which will call 'git-receive-pack' or 'git-upload-pack'.
    It will first analyze the http request by calling sub http_simulate_ssh_connection()

    sub http_simulate_ssh_connection {
        # these patterns indicate normal git usage; see "services[]" in
        # http-backend.c for how I got that. Also note that "info" is overloaded;
        # git uses "info/refs...", while gitolite uses "info" or "info?...". So
        # there's a "/" after info in the list below
        if ( $ENV{PATH_INFO} =~ m(^/(.*)/(HEAD$|info/refs$|objects/|git-(?:upload|receive)-pack$)) ) {
            my $repo = $1;
            my $verb = ( $ENV{REQUEST_URI} =~ /git-receive-pack/ ) ? 'git-receive-pack' : 'git-upload-pack';
            $ENV{SSH_ORIGINAL_COMMAND} = "$verb '$repo'";
        } else {
            # this is one of our custom commands; could be anything really,
            # because of the adc feature
            my ($verb) = ( $ENV{PATH_INFO} =~ m(^/(\S+)) );
            my $args = $ENV{QUERY_STRING};
            $args =~ s/\+/ /g;
            $args =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
            $ENV{SSH_ORIGINAL_COMMAND} = $verb;
            $ENV{SSH_ORIGINAL_COMMAND} .= " $args" if $args;
            http_print_headers(); # in preparation for the eventual output!
        }
        $ENV{SSH_CONNECTION} = "$ENV{REMOTE_ADDR} $ENV{REMOTE_PORT} $ENV{SERVER_ADDR} $ENV{SERVER_PORT}";
    }