Sunday, April 24, 2011

Hosting a Git repository on Ubuntu 10.04 LTS

I thought I'll post this recipe for anyone having issues hosting their own Git repos via HTTP. It's not that hard but a few things have to happen to actually make it work.

The automated way


If you're as lazy as I am here's a script that you can just download, execute as root and all the steps below will be executed for you. This means that you can turn a plain vanilla Ubuntu 10.04 installation into Git host in a matter of seconds:

https://gist.github.com/1034042 (raw)

The manual way


Install packages

sudo apt-get install apache2 git-core gitweb

Create folder to host your repositories

sudo mkdir /srv/git

Configure Apache to serve the repositories

Add the following to /etc/apache2/conf.d/git (create the file if it does not exist!):

# GIT
SetEnv GIT_PROJECT_ROOT /srv/git/
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAliasMatch \
"(?x)^/git/(.*/(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-core/git-http-backend/$1
ScriptAlias /git /usr/share/gitweb/index.cgi

<LocationMatch "^/git/.*/git-receive-pack$">
AuthType Basic
AuthName "Git repository"
AuthUserFile /srv/git/users
Require valid-user
</LocationMatch>

Create a link to gitweb.js

This step is required so that the proper javascript library is available for GitWeb:
sudo ln -s /usr/share/gitweb/gitweb.js /var/www

Create users file

sudo htpasswd -c /srv/git/users john
and type the password twice

Create script to create repositories

Create a file /srv/git/create.sh with the following content:
#!/bin/sh
git init --bare $1.git
cd $1.git
git config http.receivepack true
git config gitweb.owner "John Doe"
cd ..
chown www-data:www-data -R $1.git

Use the create.sh script to create a repository

cd /srv/git
sudo sh create.sh example

Update path to repos for gitweb

In /etc/gitweb.conf update the $projectroot to:
$projectroot = "/srv/git"

Restart apache

sudo invoke-rc.d apache2 restart

That's it! you should now be able to clone and browse your repository using the smart HTTP transport!

The outcome


Remember that when you use this setup you'll have a Git repository that than be cloned by everyone but only users specified in /srv/git/users can push to this repo! This means that you'll have to provide username in the URL like this:
http://john@myserver/git/example.git

If you don't do that you'll see the following error while trying to push:
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 1.05 KiB, done.
Total 3 (delta 0), reused 0 (delta 0)
error: RPC failed; result=22, HTTP code = 401
fatal: The remote end hung up unexpectedly
fatal: The remote end hung up unexpectedly

Hope this will save someone some time :)

5 comments:

gabel said...

Awesome simple!! I spent hours thinking of a dead simple solution for our environment.. and thats it!

Saša Tomić said...

That was fantastic! Thanks!

Fotis Paraskevopoulos said...

Excellent post!

You could also add

Alias /static /usr/share/gitweb/static

to avoid the soft link

tdnguyen said...

Hi padcom,

Thanks for the super detailed guide. While I'm able to push/fetch my repos, I'm unable to call "git clone" on them. I can't figure out what's wrong with my command:

git clone http://john@myserver/git/example.git

Have you had any issue cloning your repos after your setup?

Thanks,

Matthias Hryniszak said...

Quite frankly I have not had that kind of situation where I can push/pull but not fetch from a repository. You could try the ip address of your server instead of a name.