Wednesday, March 14, 2012

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 
$> 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/
 

  AllowOverride None
  Options +ExecCGI -Includes
  Order allow,deny
  Allow from all
 

  AuthType Basic
  AuthName "My Git Repositories"
  AuthUserFile /etc/gitdata/gitusers.passwd
  Require valid-user
 
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).
$> export GIT_SSL_NO_VERIFY=false
2. Set before each git command the same variable as before.
$> 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:
/etc/ssl/certs/
/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.

No comments:

Post a Comment