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.
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.
Start out by installing git and apache2 using the package manager of your distribution.
Add the modules needed by apache to enable git-over-http. These are cgi, alias and env
$ a2enmod cgi alias env
- 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>
- 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.
- 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.
- 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.
- 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.
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.