Назад | Перейти на главную страницу

как заставить git smart http Transport работать на nginx?

Я пробовал это разными способами. Вот, наверное, лучшая конфигурация, которую мне удалось придумать.

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;
    }
}

Я написал небольшой скрипт для перехвата данных между fcgiwrap и git-http-backend. Вот:

#!/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;

И вот результат, который я получаю:

$ 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?

Видимо, я сбежал git update-server-info. Потому что, например, я могу клонировать этот репозиторий без git-http-backend:

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

И вот данные, которые я получаю 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'
        };

я бегу Debian squeeze, fcgiwrap-1.0, git-1.7.2.5, nginx-0.7.67.

UPD Буду признателен, если кто-нибудь сможет хотя бы предоставить мне вывод моего скрипта под apache?


Кстати, эта версия fcgiwrap игнорирует SCRIPT_FILENAME. DOCUMENT_ROOT и SCRIPT_NAME объединяются и снова разделяются на имя скрипта и PATH_INFO. Но первая fastcgi_param DOCUMENT_ROOT должен указывать на правильное место, иначе fcgiwrap по какой-то причине не мог найти запускаемый скрипт. То есть это не работает:

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

Но это работает:

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

Это причина немного неясного nginx конфигурация:

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

Но есть некоторые настройки, когда он работает ...

DOCUMENT_ROOT + SCRIPT_NAME нельзя сочетать с PATH_INFO. Используйте абсолютное SCRIPT_FILENAME вместо этого (поскольку ваш git-http-backend программа находится вне корня вашего документа).

В качестве подсказки для отладки, чтобы проверить, работает ли интеллектуальный HTTP, просмотрите свои журналы доступа.

Следующая конфигурация протестирована на 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;
}

Добавление таких опций, как GIT_HTTP_EXPORT_ALL это упражнение для читателя.

Проблема в том, что это не сработало. PATH_INFO установлен неправильно. Поскольку "DOCUMENT_ROOT и SCRIPT_NAME объединяются и снова разделяются на имя скрипта и PATH_INFO". Это работающая конфигурация:

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;
    }
}

Затем вы можете клонировать репозитории следующим образом:

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

где 1.git расположен в /home/yuri/git.