Balaji Vajjala's Blog

A DevOps Blog from Trenches

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 1.7.9.5
  • Apache2 version 2.2.22

1. Install prequirests:

1
 sudo apt-get install git apache2 gitweb

2. Enable apache2 modules and reload apache:

1
2
 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

1
2
3
4
5
6
<virtualhost *:80>
 ServerName git.example.com
 DocumentRoot /usr/share/gitweb
 ErrorLog ${APACHE_LOG_DIR}/git_error.log
 CustomLog ${APACHE_LOG_DIR}/git_access.log combined
</virtualhost>

Enable CGI on the gitweb directory

1
2
3
4
5
<Directory /usr/share/gitweb>
Options FollowSymLinks +ExecCGI
AddHandler cgi-script .cgi
DirectoryIndex gitweb.cgi
</Directory>

Enable git clone/push/fetch etc over http:

1
2
3
4
5
6
7
8
9
10
11
12
 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-core/git-http-backend/$1

  SetEnv GIT_PROJECT_ROOT /var/git
  SetEnv GIT_HTTP_EXPORT_ALL
  SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER

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)

1
2
3
4
5
6
<Location />
  AuthType Digest
  AuthName "Shared Git Repo"
  AuthUserFile /var/git/.htpasswd
  Require valid-user
</Location>

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

1
 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]
1
2
 cd /var/git &amp;&amp; git init --bare --shared myproj.git
 chown -R www-data.www-data /var/git

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

1
2
3
 cp /etc/gitweb.conf /etc/gitweb.conf.orig
 echo -e &#39;$projectroot = "/var/git";&#39; > /etc/gitweb.conf
 echo &#39;$git_temp = "/tmp";&#39; >> /tmp/gitweb.conf

6. Enable site (apache2):

1
 a2ensite git

Which yields:

1
2
3
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:

1
2
3
4
5
 git clone http://git.example.com/myproj.git
 Cloning into &#39;myproj&#39;...
 Username for &#39;http://git.example.com&#39;: hagzag
 Password for &#39;http://hagzag@git.example.com&#39;:
 warning: You appear to have cloned an empty repository.

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

_**Create &amp; Add a file**_:
1
2
3
 cd myproj/
 echo "some text" > somefile.txt
 git add .

Commit a file:

1
2
3
4
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:

1
2
3
4
5
6
7
8
git push origin master
 Username for &#39;http://git.example.com&#39;: _**hagzag**_
 Password for &#39;http://hagzag@git.example.com&#39;: _*********_
 Counting objects: 3, done.
 Writing objects: 100% (3/3), 225 bytes, done.
 Total 3 (delta 0), reused 0 (delta 0)
 To http://git.example.com/proj2.git
 * [new branch]      master -> master

See it on gitweb:

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
1
2
3
4
5
error: unpack failed: unpack-objects abnormal exit
To http://git.example.com/proj2.git
 ! [remote rejected] master -> master (n/a (unpacker error))
error: failed to push some refs to &#39;http://git.example.com/proj2.git&#39;
  At this point I went back to the server and ran:
  1. 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 !]

References: