loading...
Cover image for Serving a Git repository over HTTP

Serving a Git repository over HTTP

mohammadaltaleb profile image Mohammad Altaleb ・3 min read

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

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

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

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

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

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

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

a2enmod authnz_external

Configuring Apache

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

cd /etc/apache2/
touch httpd.conf

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>

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

IncludeOptional sites-enabled/*.conf

Then, add the line:

Include /etc/apache2/httpd.conf

Enable mod_cgi, mod_alias and mod_env

a2enmod cgi alias env

Finally, update the repo and restart Apache

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

service apache2 restart

Testing

On your machine, clone the repository

git clone http://{SERVER_DOMAIN}/git/reponame/

Add something to the repo and commit it

touch test.txt
git add test.txt 
git commit -m "test commit"

Push the changes to the remote repository

git push -u origin master

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

Posted on by:

mohammadaltaleb profile

Mohammad Altaleb

@mohammadaltaleb

Love coding, learning new technologies, AI and Comics

Discussion

pic
Editor guide
 

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.

 

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

 

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

 

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

 

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?