Setup Git, Gitweb with git-http-backend / smart http on ubuntu 12.04

Setting up git over http (Smart HTTP in perticular) has it's caveats I will try to emphesize them as I go along.

Final Goal is to run git over http using git-http-backend (a.k.a smart http) in apposed to using webdav which is also called the dumb-method, webdav was never designed to work with git for the reason that it cannot compress object whilst transporting data between the client and the server hosting git [ there is no real git client - git server so i am not referring to it a such].

Versions used in this setup:

  • Ubutnu version 12.04-LTS
  • Git version
  • Apache2 version 2.2.22

1. Install prequirests:

 sudo apt-get install git apache2 gitweb

2. Enable apache2 modules and reload apache:

 a2enmod env alias fcgid auth_digest
 service apache2 restart

3. Create a "site" for git:

let's start with a basic virtual host configuration pointing to gitweb:

vim /etc/apache2/sites-available/git

<virtualhost *:80>
  DocumentRoot /usr/share/gitweb
 ErrorLog ${APACHE_LOG_DIR}/git_error.log
 CustomLog ${APACHE_LOG_DIR}/git_access.log combined

Enable CGI on the gitweb directory

<Directory /usr/share/gitweb>
 Options FollowSymLinks +ExecCGI
 AddHandler cgi-script .cgi
 DirectoryIndex gitweb.cgi

Enable git clone/push/fetch etc over http:

 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))$" \

  SetEnv GIT_PROJECT_ROOT /var/git

The env fcgid modules are exactly for this pupose.


Let's spice it up with good old ACL's [for as you know git doesen't deal with that stuff on it's own ...] - you can use BASIC/DIGEST

(I chose digest for it uses an MD5 digest hash and not clear text like BASIC auth)

<Location />
  AuthType Digest
  AuthName "Shared Git Repo"
  AuthUserFile /var/git/.htpasswd
  Require valid-user

Create /var/git/.htpasswd for my users:

 htdigest -c /var/git/.htpasswd "Shared Git Repo" hagzag

  Change "hagzag" with your username ...


4. Create a "shared", bare repository + set directory permissions to the apache2 user & group

Side note about shared & bare:
Shared: Instead of using default umask git repo will be created with 775 perms
Bare: instead of creating GIT_DIR in .git (defult git init behaviour), it will be created in the repository direcotry]

 cd /var/git && git init --bare --shared myproj.git
 chown -R www-data.www-data /var/git

5. Configure Git Web, /etc/gitweb.conf

 cp /etc/gitweb.conf /etc/gitweb.conf.orig
 echo -e '$projectroot = "/var/git";' > /etc/gitweb.conf
 echo '$git_temp = "/tmp";' >> /tmp/gitweb.conf

6. Enable site (apache2):

 a2ensite git

Which yields:

Enabling site git.
To activate the new configuration, you need to run:
  service apache2 reload

7. Test your new git repository

Clone the repo via http:

 git clone
 Cloning into 'myproj'...
 Username for '': hagzag
 Password for '': 
 warning: You appear to have cloned an empty repository.

... and yes I know it's empty (i created it :)).

Create & Add a file:

 cd myproj/
 echo "some text" > somefile.txt
 git add .

Commit a file:

git commit -m "initial commit"
 [master (root-commit) 3a0e708] initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 somefile.txt

Push it:

git push origin master
 Username for '': hagzag
 Password for '': *****
 Counting objects: 3, done.
 Writing objects: 100% (3/3), 225 bytes, done.
 Total 3 (delta 0), reused 0 (delta 0)
 * [new branch]      master -> master

See it on gitweb:
gitweb demo


Pitfalls / Caveats:

  1. Git directory ownership should be the same user running the httpd / apache2 daemon - if not you will get an error like so:G
    error: unpack failed: unpack-objects abnormal exit
     ! [remote rejected] master -> master (n/a (unpacker error))
    error: failed to push some refs to ''
      At this point I went back to the server and ran:           
  2. fcgid module in apache - if it's missing all the above will not work [same goes for env too but it's enabled by default !]