Setup Git server with read/write HTTPS on Debian

Three months ago we decided to move our projects to Git. I guess you already know the advantages of Git over Subversion, as there are too many discussions for this subject. I will describe here a fast and minimal configuration of how to turn a Debian GNU/Linux box to a Git server that supports read and write actions via HTTP(S).

Git supports 4 network protocols to transfer data: SSH, Local, Git, and HTTP(S). Many people are behind a firewall, which most of times permit access only to HTTP(S). Until recently, Git HTTP(S) was working only for read actions (only clone, fetch, pull, …). Almost 2 years ago Smart HTTP Transport came up. Using these clever cgi scripts, which now are part of stable Git, we can easily setup a Git server that supports read/write via HTTP(S).

Configuration steps

1) Install all required packages on Debian:

$> su -
$> apt-get install git apache2 apache2-utils openssl

2) As we need many Git repositories, we create a base directory that all repositories will be included.

$> mkdir -p /opt/allgit/repos

3) Create a bare Git repository, where developers can pull and push code.

$> cd /opt/allgit/repos
$> mkdir repo1.git
$> cd repo1.git
$> git init --bare

4) We will use Apache 2 HTTP server to support HTTP(S) for Git. On Debian, when you install apache2 package, user www-data is created and is the user of Apache. As we need Apache to execute the Git actions, then www-data user must have read and write permissions on each Git repository.

$> chown -R www-data:www-data repo1.git/

5) The www-data user is used only by Apache and not by developers, so we need to define our Git users somewhere else. We can use HTTP authentication that is provided by Apache. We can use htpasswd, which is an Apache tool that produce an encrypted password from a plain text password for a user. These users are irrelevant to Unix users of OS. So, using this strategy we can define as many Git users as we need, without creating Unix users. Create a specific directory and file, with restricted privileges to www-data user, in order to keep git users and passwords.

$> mkdir /etc/gitdata
$> cd /etc/gitdata
$> htpasswd -c gitusers.passwd gituser1
$> htpasswd gitusers.passwd gituser2

6) I choose to use secure HTTP for Git communication. So, I created a self signed SSL certificate using openssl. On the same directory create the certificate and the private keys pair. Fill all the fields you like that the next command requires.

$> openssl req -x509 -nodes -days 999 -newkey rsa:2048 -keyout mygit_ssl.key -out mygit_ssl.crt

7) Also, we need a few modules to be enabled on Apache, so make sure mod_ssl, mod_cgi, mod_alias, and mod_env are enabled. This can be easily done on Debian with a2enmod command, where it create symbolic links in the next directory.

$> a2enmod <apache_module>
$> ls /etc/apache2/mods-enabled/

8) Now you only need to configure Apache site and you are ready. Assume you already have a domain name (e.g. mygitdomain.com) in order to use it for your server. A fast way to configure your Apache site(and test immediately) is to copy the existing configuration of Apache and make the required configuration changes.

$> cd /etc/apache2/sites-available
$> cp default-ssl mygitdomain.com

9) Add (or alter) the existing configuration of mygitdomain.com file, which you just created, based on the next configuration.

ServerName mygitdomain.com
ServerAdmin webmaster@localhost
ErrorLog /var/log/apache2/git_apache_error.log

SetEnv GIT_PROJECT_ROOT /opt/allgit
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER
ScriptAlias /allgit/ /usr/lib/git-core/git-http-backend/

<Directory "/usr/lib/git-core/">
  AllowOverride None
  Options +ExecCGI -Includes
  Order allow,deny
  Allow from all
</Directory>

<LocationMatch "^/allgit/repos/.*$">
  AuthType Basic
  AuthName "My Git Repositories"
  AuthUserFile /etc/gitdata/gitusers.passwd
  Require valid-user
</LocationMatch>
SSLEngine on

SSLCertificateFile    /etc/gitdata/mygit_ssl.crt
SSLCertificateKeyFile /etc/gitdata/mygit_ssl.key

Test your Git server

1) Configuration is finished. Enable this site in your Apache server and then restart Apache.

$> a2ensite mygitdomain.com
$> /etc/init.d/apache2 restart

2) Try to clone your empty git repository.

$> git clone https://mygitdomain.com/allgit/repos/repo1.git repo1

Certificate verification error

error: server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none while accessing https://mygitdomain.com/allgit/repos/repo1.git/info/refs
fatal: HTTP request failed

You have 3 options to solve this:

  1. Set this variable in the current shell (will be enabled for all the following commands).
    1. $> export GIT_SSL_NO_VERIFY=false
  2. Set before each git command the same variable as before.
    1. $> env GIT_SSL_NO_VERIFY=true
  3. In order to treat your certificate as trusted, even it is a self signed certificate, you can get server’s certificate and install it on one of the next directories:
    1. /etc/ssl/certs/
    2. /usr/share/ca-certificates/

Notes
This is just a fast configuration that I did 3 months ago in order to evaluate Git. There are many points that you can improve (stronger security) in order to have a better configuration.
All the configuration is make by root user.

Regards,
Adrianos Dadis.

Democracy requires Free Software

About Adrianos Dadis

Building Big Data & Stream processing solutions in many business domains. Interested in distributed systems and enterprise integration.
This entry was posted in Administration, GNU/Linux, Software Development and tagged , , . Bookmark the permalink.

12 Responses to Setup Git server with read/write HTTPS on Debian

  1. site says:

    It’s an awesome article designed for all the online people; they will obtain advantage from it I am sure.

  2. Anonymous says:

    i’m stuck on GIT_PROJECT_ROOT is set but PATH_INFO is not, can you help me?

    • Rajesh says:

      I am also struck with this issue GIT_PROJECT_ROOT is set but PATH_INFO is not. how can i resolve this

  3. Anonymous says:

    solved

  4. Anonymous says:

    How did you solve that problem? “GIT_PROJECT_ROOT is set but PATH_INFO is not”

    • Adrianos Dadis says:

      In Debian Wheezy, my configuration works as it is.
      The only configuration changes I have done are these I wrote.
      I guess your GNU Linux distribution needs something extra, which I am not aware of.

  5. Rob says:

    Thank you *so* much !

  6. Bob says:

    fatal: could not create workt tree dir ‘repo1’.???????? ? ???????
    What is it?

  7. web page says:

    Awesome! Its really remarkable post, I have got much
    clear idea regarding from this paragraph.

  8. pat says:

    Excellent post – not explained so well anywhere else.
    On Ubuntu had to:
    sudo a2enmod ssl

    to install mod_ssl.
    then:
    sudo service apache2 restart.
    Thanks – really appreciated.

  9. Anonymous says:

    How about the Directory and LocationMatch closing tags? Are those two separate tags, or is LocationMatch inside Directory? Should the SSL options be inside one of them?

Leave a reply to pat Cancel reply