Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up git over http?

I need to set up a git server with git-over-http (smart http), but the resources available online are a mess, mixing in other apache configuration, missing details or not being explicit enough.

I am answering this question myself based on what I found lacking in the available resources.

like image 864
Marmoy Avatar asked Nov 04 '14 12:11

Marmoy


People also ask

How do I use http in git?

First it is necessary to understand that there are 2 components to git-over-http: git and apache. These two are connected through a script with the name of git-http-backend. The challenge is to configure the interface between these two components, so that http requests to git are forwarded by apache.

Does Git work over http?

Git can use four distinct protocols to transfer data: Local, HTTP, Secure Shell (SSH) and Git.

What is git http backend?

A simple CGI program to serve the contents of a Git repository to Git clients accessing the repository over http:// and https:// protocols. The program supports clients fetching using both the smart HTTP protocol and the backwards-compatible dumb HTTP protocol, as well as clients pushing using the smart HTTP protocol.


2 Answers

First it is necessary to understand that there are 2 components to git-over-http: git and apache. These two are connected through a script with the name of git-http-backend. The challenge is to configure the interface between these two components, so that http requests to git are forwarded by apache.

Note: Security is outside the scope of this guide.

  1. Start out by installing git and apache2 using the package manager of your distribution.

  2. Add the modules needed by apache to enable git-over-http. These are cgi, alias and env

$ a2enmod cgi alias env
  1. Copy the following into /etc/apache2/httpd.conf (without removing whatever else it contains)
<VirtualHost *:80>
    SetEnv GIT_PROJECT_ROOT /data/git
    SetEnv GIT_HTTP_EXPORT_ALL
    SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER
    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/lib/git/git-http-backend/$1"
    Alias /git /data/git
    <Directory /usr/lib/git>
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        AllowOverride None
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>
  1. Now replace the 2 occurrences of /data/git with the parent directory of your git repos on the server (don't worry if you don't have any repos yet, just use the directory where you intend to place it/them)

Also replace /usr/lib/git/git-http-backend with the location of git-http-backend on your system, which can be found using $ find / -name git-http-backend

It may be that on your system REDIRECT_REMOTE_USER actually overwrites a valid REMOTE_USER. If this setup doesn't work when finished, try removing that line.

According to this source, it may be necessary to replace the last two lines within the Directory tag by Require all granted for apache 2.4 and above.

  1. Restart the apache server: $ apache2ctl -k graceful

Now the apache server is set up, but we're not done yet, there are some important parts of setting up the repos that will affect whether this setup works or not.

  1. Set up the repo:
$ mkdir myrepo.git
$ cd myrepo.git
$ git init --bare --shared
$ cp hooks/post-update.sample hooks/post-update
$ git update-server-info
$ chown -R wwwrun:www

Here it is important to understand that the last line changes the owner of the repo to the apache2 user. This user may be different on your system. To find the apache user, execute $ ps aux | egrep '(apache|httpd)'. Then to find the group name of the user, execute $ id user-name. On my system the user is wwwrun and the group www. Replace accordingly.

  1. Use the repo

In order to use the repo, you need to know the url. For this setup the url is http://server.domain/myrepo.git

Note: https will not work.

When accessing the repo from a client, you just add it as a remote:

$ git remote add origin http://server.domain/myrepo.git

Then you can interact with it like any other git repo.

like image 58
Marmoy Avatar answered Sep 23 '22 17:09

Marmoy


Multiples projects with differents access rigths

There is gitolite, but complex... A simple solution is to create macro in apache2 conf as :

## Git root

SetEnv GIT_PROJECT_ROOT /opt/gitroot
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER
SetEnv GITWEB_CONFIG /etc/gitweb.conf

##  SMART Http

ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/

<Directory "/usr/libexec/git-core*">
   Options +ExecCGI +Indexes
   Order allow,deny
   Allow from all
   Require all granted
</Directory>

<Macro Project $repository $developers $users>
    <LocationMatch "^/git/$repository.*$">
        AuthType Basic
        AuthName "Git Access"
        AuthUserFile /opt/basic_auth
        Require $developers $users 
    </LocationMatch>
    <LocationMatch "^/git/$repository/git-receive-pack$">
        AuthType Basic
        AuthName "Git Access"
        AuthUserFile /opt/basic_auth
        Require  $developers
    </LocationMatch>
 </Macro>

 IncludeOptional /opt/git_access.conf

And in /opt/git_access.conf

Use Project test1 "admin john" "mike"
Use Project test2 "admin emma" "all granted"

So, the git project test1 will have read/write access by admin and john, and read only access by mike.

The project test2 will have read access by all authentified users.

The git_access.conf can be produced by your tools from a database of yours projetcs and users for example, and reload by a "service httpd reload".

For the same config for gitweb read access, add in /etc/gitweb.conf :

$export_auth_hook = sub {
        my $repo = shift;
        my $user = $cgi->remote_user;
        if($repo =~ s/\/opt\/gitroot\///) {
           open FILE, '/opt/git_access'; 
           while(<FILE>) {
               if ($_ =~ m/Use Project $repo \"(.*)\" \"(.*)\"/)
                {
                    my $users = $1 . ' ' . $2;
                    $users =~ s/all granted/$user/;
                    $users =~ s/user//;
                    if ( $users =~ m/$user/ ) {
                        return 1;
                    }
                }              
            }
        }
        return 0;
};

This little gitweb hook hide (return 0) the git repositories with no read access for current user.

And into apache2 configuration, the classic gitweb conf :

## Gitweb  

Alias /gitweb /var/www/git

<Directory /var/www/git>
    AddHandler cgi-script .cgi
    DirectoryIndex gitweb.cgi
    Options +ExecCGI +Indexes +FollowSymlinks 
    AllowOverride None    
    AuthType Basic
    AuthName "Git Access"
    AuthUserFile /opt/basic_auth
    Require valid-user
</Directory>

That's my config.

like image 29
tfa Avatar answered Sep 23 '22 17:09

tfa