0

I've tried this in many different ways. Here is probably the best configuration I've managed to come up with.

nginx:

server {
    server_name   git.domain.com;
    access_log   /var/log/nginx/git.domain.com-access.log;
    error_log   /var/log/nginx/git.domain.com-error.log;

    include common;

    location / {
        fastcgi_pass   unix:/var/run/fcgiwrap.socket;

        # fastcgi_param   DOCUMENT_ROOT   /home/yuri/git;
        # fastcgi_param   SCRIPT_NAME   /1.pl;
        fastcgi_param   DOCUMENT_ROOT   /usr/lib/git-core;
        fastcgi_param   SCRIPT_NAME   /git-http-backend;
        include fastcgi_params;
        fastcgi_param   DOCUMENT_ROOT   /home/yuri/git;

        fastcgi_param   GIT_HTTP_EXPORT_ALL   "";
        fastcgi_param   GIT_PROJECT_ROOT   /home/yuri/git;
        fastcgi_param   PATH_INFO   $request_uri;
    }
}

I've written a little script to intercept data between fcgiwrap and git-http-backend. Here it is:

#!/usr/bin/perl
use Data::Dumper;
my $output = `/usr/lib/git-core/git-http-backend`;
open my $fh, '>', '/home/yuri/git/1/1.txt';
print $fh $output;
print $fh Dumper {map {$_ => $ENV{$_}} 'QUERY_STRING', 'REQUEST_METHOD', 'CONTENT_TYPE', 'CONTENT_LENGTH', 'SCRIPT_NAME', 'REQUEST_URI', 'DOCUMENT_URI', 'DOCUMENT_ROOT', 'SERVER_PROTOCOL', 'GATEWAY_INTERFACE', 'SERVER_SOFTWARE', 'REMOTE_ADDR', 'REMOTE_PORT', 'SERVER_ADDR', 'SERVER_PORT', 'SERVER_NAME', 'REDIRECT_STATUS'};
print $output;

And here is the output I get:

$ git clone http://git.domain.com/1.git
Cloning into '1'...
fatal: http://git.domain.com/1.git/info/refs?service=git-upload-pack not found: did you run git update-server-info on the server?

Apparently, I did run git update-server-info. Because for example I can clone this repository without git-http-backend:

server {
    server_name   git.domain.com;
    root   /home/yuri/git;
}

And here is the data I get in 1.txt:

Status: 404 Not Found^M
Expires: Fri, 01 Jan 1980 00:00:00 GMT^M
Pragma: no-cache^M
Cache-Control: no-cache, max-age=0, must-revalidate^M
^M
$VAR1 = {
          'SERVER_NAME' => 'git.domain.com',
          'SCRIPT_NAME' => '/1.git/info/refs',
          'CONTENT_LENGTH' => '',
          'REQUEST_METHOD' => 'GET',
          'SERVER_SOFTWARE' => 'nginx/0.7.67',
          'REMOTE_PORT' => '53908',
          'QUERY_STRING' => 'service=git-upload-pack',
          'SERVER_PORT' => '80',
          'REDIRECT_STATUS' => '200',
          'REMOTE_ADDR' => 'x.x.x.x',
          'CONTENT_TYPE' => '',
          'SERVER_PROTOCOL' => 'HTTP/1.1',
          'DOCUMENT_URI' => '/1.git/info/refs',
          'REQUEST_URI' => '/1.git/info/refs?service=git-upload-pack',
          'GATEWAY_INTERFACE' => 'CGI/1.1',
          'SERVER_ADDR' => 'x.x.x.x',
          'DOCUMENT_ROOT' => '/home/yuri/git'
        };

I'm running Debian squeeze, fcgiwrap-1.0, git-1.7.2.5, nginx-0.7.67.

UPD I would be grateful if someone could at least provide me with the output of my script under apache?


On a side note, this version of fcgiwrap ignores SCRIPT_FILENAME. DOCUMENT_ROOT and SCRIPT_NAME are concatenated and split back again into the script name and PATH_INFO. But the first fastcgi_param DOCUMENT_ROOT must point to the right location, otherwise fcgiwrap wouldn't find the script to be launched for some reason. That is, this doesn't work:

        fastcgi_param   DOCUMENT_ROOT   $document_root;   # /usr/local/nginx/html
        fastcgi_param   DOCUMENT_ROOT   /home/yuri/git;

But this works:

        fastcgi_param   DOCUMENT_ROOT   /home/yuri/git;
        fastcgi_param   DOCUMENT_ROOT   $document_root;   # /usr/local/nginx/html

That is the reason behind slightly obscure nginx configuration:

        fastcgi_param   DOCUMENT_ROOT   /usr/lib/git-core;
        ...
        include fastcgi_params;
        fastcgi_param   DOCUMENT_ROOT   /home/yuri/git;

But there are some setups when it works...

x-yuri
  • 2,141
  • 2
  • 24
  • 29
  • Aside, you have your host name visible in the top `server_name`. – Lekensteyn May 29 '13 at 09:31
  • Oh, thanks for your remark :) though, it's password-protected... – x-yuri May 29 '13 at 12:35
  • @Lekensteyn, I can't comment your answer, so... First off, I have `fcgiwrap-1.0-1+squeeze1` and it ignores `SCRIPT_FILENAME`. You can see it by inspecting commit history of [v1.0.1](https://github.com/gnosek/fcgiwrap/commits/v1.0.1) and [v1.0.2](https://github.com/gnosek/fcgiwrap/commits/v1.0.2). Anyway, I've checked it with the following [nginx config](http://sprunge.us/DETg?nginx) and the following [test script](http://sprunge.us/QYUB?perl). – x-yuri May 30 '13 at 17:20
  • I decided to make order of fastcgi_param a [separate question](http://serverfault.com/questions/512028/nginx-fcgiwrap-how-come-order-of-fastcgi-param-matters). – x-yuri May 30 '13 at 18:22
  • I am using a development version containing [a patch for a way to restrict executable files](https://github.com/gnosek/fcgiwrap/commit/3a94c2) on Wheezy. I knew the squeeze one was buggy, so I never bothered trying that one. Hey, it is a single executable anyway. – Lekensteyn May 30 '13 at 22:33

2 Answers2

1

DOCUMENT_ROOT + SCRIPT_NAME cannot be combined with PATH_INFO. Use an absolute SCRIPT_FILENAME instead (since your git-http-backend program is located out of your document root).

As a debugging hint, to test whether smart HTTP works, look at your access logs.

The following configuration is tested on Debian 7.0 Wheezy:

# based on http-backend.c from git v1.8.2.1, service_cmd
location ~ "^/[a-zA-Z0-9._-]+/(git-(receive|upload)-pack|HEAD|info/refs|objects/(info/(http-)?alternates|packs)|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))$" {
    fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
    fastcgi_param GIT_PROJECT_ROOT /home/yuri/git;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    include fastcgi_params;
    fastcgi_pass unix:/var/run/fcgi-wrap.sock;
}

Adding options like GIT_HTTP_EXPORT_ALL is an exercise for the reader.

Lekensteyn
  • 6,241
  • 6
  • 39
  • 55
  • Still doesn't work, here are the [nginx config](http://sprunge.us/idBA), [shell output](http://sprunge.us/VXHR) and [perl-script output](http://sprunge.us/OAcF). By the way, PATH_INFO doesn't get passed, as opposed to PATH_INFO2 e.g. Could you tell what you're getting (when it works, of course)? – x-yuri Jun 01 '13 at 11:24
  • @x-yuri, since it seems a personal server, can you upgrade from Squeeze to Wheezy to make your software more up-to-date? What does `fastcgi_params` contain? Mine is at http://fpaste.org/15991/ – Lekensteyn Jun 01 '13 at 13:39
  • Actually it's a production server :) And well I can install wheezy on my PC, but that would take time. And I'd be grateful if you'd tell what environment of CGI process is when it works. Because that's what I guess is causing the problems. My `fastcgi_params` is [like this](http://sprunge.us/dgMH). – x-yuri Jun 04 '13 at 12:57
  • @x-yuri You mentioned that `SCRIPT_FILENAME` gets ignored with your fcgiwrap version. I strongly recommend you upgrading `fcgiwrap` to a more recent version where this is fixed if you are unable to upgrade to Wheezy. This also holds for production environments. – Lekensteyn Jun 04 '13 at 13:09
  • Lekensteyn: I just tested your config on a vanilla wheezy installation and it worked after two minor changes: - changed /var/run/fcgi-wrap.sock to /var/run/fcgiwrap.socket (the default on wheezy) - installed git 1.8.x from wheezy-backports. git 1.7 refused to work for some reason. Thanks for your help. – Luca Gibelli Mar 21 '14 at 14:16
  • @LucaG. I have actually compiled fcgiwrap from source because the one in Wheezy was insufficient, that's why your paths may be different than mine. If you take fcgiwrap from jessie or sid (1.1.0-1), then you also have a `-p` option to restrict the allowed programs (see https://github.com/gnosek/fcgiwrap/pull/12 for details) which is why I compiled it manually. – Lekensteyn Mar 21 '14 at 14:38
0

The problem it didn't work was that PATH_INFO wasn't set correctly. Since "DOCUMENT_ROOT and SCRIPT_NAME are concatenated and split back again into the script name and PATH_INFO". This is the configuration that works:

server {
    server_name   domain.com;
    root   /home/yuri/git;
    access_log   /var/log/nginx/domain.com-access.log;
    error_log   /var/log/nginx/domain.com-error.log;

    location / {
        fastcgi_pass   unix:/var/run/fcgiwrap.socket;

        fastcgi_param   DOCUMENT_ROOT   /usr/lib/git-core;
        fastcgi_param   SCRIPT_NAME   /git-http-backend$fastcgi_script_name;
        include   fastcgi_params;

        fastcgi_param   GIT_HTTP_EXPORT_ALL   "";
        fastcgi_param   GIT_PROJECT_ROOT   /home/yuri/git;
    }
}

Then you can clone repositories like this:

git clone http://domain.com/1.git

where 1.git is located in /home/yuri/git.

x-yuri
  • 2,141
  • 2
  • 24
  • 29