DEV Community

Cover image for Serving a Git repository over HTTP
Mohammad Altaleb
Mohammad Altaleb

Posted on

Serving a Git repository over HTTP

A while ago, I was assigned the task of researching how to serve a Git repository over HTTP. The tutorials and documentations I've found were either messy or incomplete.

After a painful process, I got it to work. But, unfortunately a decision was made to use a different approach to serve the repo.

I didn't want to just throw the effort away. So, here's a blog post about it.

The setup

We'll use Apache web server to serve the repository, and we'll install it on an Ubuntu 16.04.5 machine (AWS EC2 instance in my case).

Installation

Let's start by installing Git and Apache

sudo apt-get update
sudo apt-get install git-core
sudo apt-get install apache2
Enter fullscreen mode Exit fullscreen mode

Creating the repo

For this tutorial, we will create a new Git repository in the documents root (/var/www/html)

cd /var/www/html
mkdir git
cd git
mkdir reponame
cd reponame
git init --bare
chgrp -R www-data /var/www/html/git
chown -R www-data /var/www/html/git
Enter fullscreen mode Exit fullscreen mode

If you want to allow other people to push to the repo, open the file named config which was added to the repository by Git and append the following to it

[http]
    receivepack = true
Enter fullscreen mode Exit fullscreen mode

Authentication

We only want authenticated users to access the repo. So, first we'll create a dummy bash script named auth.sh in (/usr/local/bin/):

cd /usr/local/bin/
touch auth.sh
chmod 755 auth.sh
Enter fullscreen mode Exit fullscreen mode

The script will check a given username and password and exit with 0 code if they are correct or 1 otherwise.
The content of the script is the following:

#! /bin/bash
read user
read password

if [[ ("$user" = "hello") && ("$password" = "world") ]]; then
  exit 0
else
  exit 1
fi
Enter fullscreen mode Exit fullscreen mode

To be able to use our script with Apache, we should install the package libapache2-mod-authnz-external that allows authentication against external services

apt-get install libapache2-mod-authnz-external
Enter fullscreen mode Exit fullscreen mode

Then, we'll make sure the authentication module is enabled

a2enmod authnz_external
Enter fullscreen mode Exit fullscreen mode

Configuring Apache

create an Apache configuration file with the name httpd.conf in (/etc/apache2/)

cd /etc/apache2/
touch httpd.conf
Enter fullscreen mode Exit fullscreen mode

The content of httpd.conf should be the following:

<VirtualHost *:80>

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

    DocumentRoot /var/www/html
    <Directory "/var/www/html">
        Options All Includes Indexes FollowSymLinks
        Order allow,deny
        Allow from all
        AllowOverride All
    </Directory>


    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"

    Alias /git /var/www/html/git

    <Directory /usr/lib/git-core>
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        AuthType Basic
        AuthName "Restricted"
        AuthBasicProvider external
        AuthExternal auth
        require valid-user
    </Directory>

    <Directory /var/www/html/git>
        Options +ExecCGI +Indexes +FollowSymLinks
        Allowoverride None
        AuthType Basic
        AuthName "Restricted"
        AuthBasicProvider external
        AuthExternal auth
        require valid-user
    </Directory>

    AddExternalAuth auth /usr/local/bin/auth.sh
    SetExternalAuthMethod auth pipe

</VirtualHost>
Enter fullscreen mode Exit fullscreen mode

Now, open /etc/apache2/apache2.conf file and comment out the line:

IncludeOptional sites-enabled/*.conf
Enter fullscreen mode Exit fullscreen mode

Then, add the line:

Include /etc/apache2/httpd.conf
Enter fullscreen mode Exit fullscreen mode

Enable mod_cgi, mod_alias and mod_env

a2enmod cgi alias env
Enter fullscreen mode Exit fullscreen mode

Finally, update the repo and restart Apache

cd /var/www/html/git/reponame
git update-server-info

service apache2 restart
Enter fullscreen mode Exit fullscreen mode

Testing

On your machine, clone the repository

git clone http://{SERVER_DOMAIN}/git/reponame/
Enter fullscreen mode Exit fullscreen mode

Add something to the repo and commit it

touch test.txt
git add test.txt 
git commit -m "test commit"
Enter fullscreen mode Exit fullscreen mode

Push the changes to the remote repository

git push -u origin master
Enter fullscreen mode Exit fullscreen mode

And that's about it. If the clone and push succeed, it means we successfully served our repository.

Top comments (5)

Collapse
 
jvleminc profile image
Joris Vleminckx • Edited

Thanks for this tutorial. I managed to clone the repo without entering username/password, but when pushing no username/pasword is requested, an error occurs:

jvleminckx@joris-laptopWork î‚° ~/reponame î‚° î‚  master î‚° git push -u origin master
error: Cannot access URL 198.204.227.93/git/reponame/, return code 22
fatal: git-http-push failed
error: failed to push some refs to '198.204.227.93/git/reponame/'

No credentials asked...

UPDATE: This happened because I hadn't commented out
IncludeOptional sites-enabled/*.conf

in /etc/apache2/apache2.conf. Once done this, the pushing started asking for credentials and the push worked fine.

Collapse
 
bloodtearvn profile image
bloodtearvn

Can you show conffig with php authentication connect mysql (each folder each permission)
Example:
Create 2 repository: pr1, pr2
Create 2 user: user1 user2
now i want only user1 can access pr1 and user2 can access pr2 and user or user can not access another

Collapse
 
swetha1592 profile image
swetha1592

Hi Can u please explain what is www-data here.
Is that an existing folder?

chgrp -R www-data /var/www/html/git
chown -R www-data /var/www/html/git

Collapse
 
jvleminc profile image
Joris Vleminckx

Be sure that apache has been installed after step 1: sudo apt-get install apache2 The user/group should be created by this installation.

Collapse
 
ashtyn3 profile image
Ashtyn

What are my user name and password? I didn't change them from the "hello", "world" in auth.sh script. And when I clone it keeps telling me my username and password are wrong?