Installing Git on Ubuntu 12.04 and enabling HTTP access with Nginx

Git is a good alternative for developers who need a version control supported on both Windows and Linux platforms. Below I provided basic steps for installing Git on Ubuntu 12.04 and enabling HTTP access to the repositories with Nginx web server.

Installing required packages

First, we need to install Nginx and Git packages:

apt-get install nginx git

by default Nginx processes will run as www-data, (check “user” keyword in /etc/nginx/nginx.conf configuration file). Git installation has not created any user yet.

Now we need to install some modules that will help us to link Nginx and Git together:

apt-get install fcgiwrap spawn-fcgi

This will create a socket file /var/run/fcgiwrap.socket owned by www-data user for communication between Nginx and the FCGI process.

The next package we need to install is Git Web that generates HTML for displaying in browser:

apt-get install gitweb

This will create /etc/gitweb.conf – configuration file for Git Web instance that contains the location of projects (/var/cache/git by default) and /usr/share/gitweb/gitweb.cgi – the main CGI script.

Configuring Nginx virtual host for GitWeb

Nginx virtual host for GitWeb should look like this:

server
{
  access_log /var/log/nginx/gitweb.access.log;

  error_log /var/log/nginx/gitweb.error.log info;

  server_name gitweb.developernote.com;

  location /index.cgi {
    root /usr/share/gitweb/;
    include fastcgi_params;
    gzip off;
    fastcgi_param SCRIPT_NAME $uri;
    fastcgi_param GITWEB_CONFIG /etc/gitweb.conf;
    fastcgi_pass  unix:/var/run/fcgiwrap.socket;
  }
  location / {
    root /usr/share/gitweb/;
    index index.cgi;
  }
}

browser shows that there are no Git repository yet at address http://gitweb.developernote.com (below I’ll show how to create it):

HTTP access to Git on Ubuntu 12.04

Creating Git repository

Create user:

cd /home
useradd -d /home/git -m git
usermod -a -G git www-data
chmod o-rwx git

Create a repository and add some files:

su - git
git@london:~/repositories/geographix$ git init
#Initialized empty Git repository in /home/git/repositories/geographix/.git/
git@london:~/repositories/geographix$ git config --global user.email "js8123@gmail.com"
git@london:~/repositories/geographix$ git config --global user.name "John Smith"
git@london:~/repositories/geographix$ mkdir src
git@london:~/repositories/geographix$ mv ~/work/* .
git@london:~/repositories/geographix$ mv test.cpp src/
git@london:~/repositories/geographix$ git add src/test.cpp
git@london:~/repositories/geographix$ git commit -m "First commit" src/*.cpp
git@london:~/repositories/geographix$ exit
ln -s /home/git/repositories/geographix/.git /var/cache/git/geographix.git
service fcgiwrap restart

Now I can see geographix.git repository in my browser:

Web access to Git repository

Configuring Nginx virtual host for git-http-backend

Nginx virtual host for git-http-backend should look like this:

server
{
  access_log /var/log/nginx/git.access.log;

  error_log /var/log/nginx/git.error.log info;

  server_name git.developernote.com;

  gzip off;

  location / {
        root /home/git/repositories;

        fastcgi_pass unix:/var/run/fcgiwrap.socket;
        fastcgi_param SCRIPT_FILENAME   /usr/lib/git-core/git-http-backend;
        fastcgi_param PATH_INFO         $uri;
        fastcgi_param GIT_PROJECT_ROOT  /home/git/repositories;
        fastcgi_param GIT_HTTP_EXPORT_ALL "";
        fastcgi_param REMOTE_USER $remote_user;
        include fastcgi_params;
  }
}

After doing the first attempt to clone a repository with following command

su - test1
git clone http://git.developernote.com/geographix.git ggtest/

I got this:

Cloning into ‘ggtest’…
fatal: http://git.developernote.com/geographix.git/info/refs not found: did you run git update-server-info on the server?

so I did

su - git
cd ~/repositories/geographix
git update-server-info

but got the same message again while doing the next attempt to clone the repository. Finally I succeeded with the following command (removed .git from the repository name):

git clone http://git.developernote.com/geographix ggtest/

The output was:

Cloning into ‘ggtest’…
remote: Counting objects: 4, done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.

so I cannot say for sure is running git update-server-info necessary or not, at least I noticed that it created info/refs file.

Then I tried:

cd ggtest
git pull
git push
git config --global user.email "test@example.com"
git config --global user.name "Test Name"
cd src
git checkout -- test.cpp
nano test.cpp
git commit -a -m "some experimental commit"
cd ..
git push

And the last command produced the following output:

error: Cannot access URL http://git.developernote.com/geographix/, return code 22
fatal: git-http-push failed

I tried this

usermod -a -G git www-data
cd /home
chmod g+w git
cd git
chmod -R g+w repositories/

but with no success. Finally I solved this terrible problem by replacing the original content of server-side /home/git/repositories/geographix/.git/config file:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true

with the following:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = true
        logallrefupdates = true
[http]
receivepack = true

After that git push command succeeded with the following output:

To http://git.developernote.com/geographix
   203ce7c..00b704d  master –> master

and GitWeb shown me the commit with the web interface:

Git commit

After doing some further experimentation I realized that I should create so-called bare repository on the server with the following command:

cd ~/repositories
git init --bare geographix.git

this command creates a new repository in geographix.git folder without src subfolder, and newly created config file looks like this:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = true

Then I used the same commands as before:

ln -s /home/git/repositories/geographix.git /var/cache/git/geographix.git
su - test1
git clone http://git.developernote.com/geographix.git geographix.git/
cd geographix.git/
mkdir src
cd src
nano test1.cpp
git add src/*
cd ..
git commit -m "First commit" src/*
git push origin master

git push command as well as git pull without other arguments did not work saying:

No refs in common and none specified; doing nothing.
Perhaps you should specify a branch such as ‘master’.
Everything up-to-date

probably it is because the repository initially was empty.

Securing the access to the repositories

I do not know yet how restrict the access on per-repository or per-project basis, so I temporarily set the same users and passwords for all the repositories. First I generated ~/.gitpasswd file containing users and passwords processed by htpasswd utility:

apt-get install apache2-utils
su - git
htpasswd -bd ~/.gitpasswd <user> <password>

Then I added the following lines to both git and gitweb Nginx virtual hosts:

server
{
  listen 443 ssl;
  ssl_certificate /usr/share/ca-certificates/nginx/nginx.crt;
  ssl_certificate_key /usr/share/ca-certificates/nginx/nginx.key;

  auth_basic "GitWeb requires authorization";
  auth_basic_user_file /home/git/.gitpasswd;
  
  ...
}

Now when I clone a repository from the command line, it prompts the username and password:

git clone https://git.developernote.com/geographix.git gg1

Cloning into ‘gg1’…
Username for ‘http://git.developernote.com’: dmitriano
Password for ‘http://dmitriano@git.developernote.com’:
remote: Counting objects: 4, done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.

The only problem is that not all clients accepts my self-signed SSL certificate, so I get this:

Cloning into ‘gg3’…
error: server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none while accessing https://git.developernote.com/geographix.git/info/refs
fatal: HTTP request failed

Leave a Reply

Your email address will not be published. Required fields are marked *