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.
Top comments (5)
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?