a3nm's blog

Setting up SVN and git shared hosting on Debian

This note explains how to setup a shared Git and a shared SVN repository on a Debian stable (jessie) server, incidentally a Raspberry Pi. Both repositories are served with Apache, using mod_dav_svn for SVN, and using the git-http-backend CGI for git. (Note that these aren't the only possible choices, but they are the ones I will present.)

The setup uses Apache Digest authentication (with a file common to both SVN and git): the SVN and git setups are otherwise independent. The setup uses SSL provided with Let's Encrypt, set up with certbot. For brevity I am omitting sudo in all commands of this tutorial.

Note that I am dumping this from memory after having done the setup, but I'm not guaranteeing that everything will work. If something does not work, please email me.

Set up the domain names

If your main domain is example.com, then you probably want to set up svn.example.com and git.example.com to point to the machine where you will be hosting the repositories. This will allow you to configure each service easily using virtual hosts, and makes it easier to move the hosting to a different machine if you want.

You probably want to wait for the new DNS entries to have propagated before doing what follows, in particular for the Let's Encrypt challenge to work.

Install apache2 and certbot

apt-get install apache2 libapache2-svn libapache2-mod-svn
apt-get install certbot python-certbot-apache

Side note: certbot is not yet available on jessie, you need to enable jessie-backports. As my Raspberry Pi uses Raspbian, this also means I had to set up the Debian signing keys: download the keys that apt-get update complains about and install them with apt-key add.

Obviously you should also make sure that SVN and git are installed on the server.

Start your apache2 configuration

Add to the beginning of /etc/apache2/apache2.conf the default hostname of your machine (of course, change it to something reasonable):

ServerName machine.example.com

While you are at it, you can add the following to the bottom to avoid disclosing details of your Apache version:

ServerTokens Prod
ServerSignature Off

Now, create a file /etc/apache2/sites-available/000-git.conf and add the following, changing the domain name and email address (don't worry about the DocumentRoot, it doesn't matter):

<VirtualHost *:80>
        ServerName git.example.com

        ServerAdmin you@example.com
        DocumentRoot /var/www/html/

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

Create /etc/apache2/sites-available/000-svn.conf analogously (replacing git by svn). Then, enable the right sites with:

a2dissite 000-default
a2ensite 000-git
a2ensite 000-svn

Set up SSL with certbot

Run certbot --apache: it should pick up the configuration files that you created and understand what you are doing. Say that you want to enable encryption for both subdomains, that you accept the license, and that you want the Secure setup where users are redirected to the SSL version (we don't want the version control traffic ever to happen in cleartext). Check that https://git.example.com/ and https://svn.example.com/ both work with SSL, and that http:// URLs redirect to the https:// variant. Yes, it's just a 301 redirect, it's not HSTS, but to me this is good enough.

Create the user file

Authentication will be performed by Apache Digest, so create a password file with your own user using the following command (note that the second argument, the realm, is important because it is included in the digest):

htdigest -c /etc/vcs_passwd "example.com version control" yourlogin

Then, when you want to add more users, issue:

htdigest /etc/vcs_passwd "example.com version control" theirlogin

Ensure that the file is owned by www-data and only readable by them:

chown www-data:www-data /etc/vcs_passwd
chmod og-rwx /etc/vcs_passwd

Setting up Subversion

Now that the common SSL setup and user setup is done, let's start by setting up Subversion. For reference, the part of the SVN Book about what we are trying to do is here. I prefer creating one global repository and use path-based authorization to give access to relevant subsets to various users.

Creating the Subversion repository and setting up authorization

Create the repository, e.g.:

mkdir -p /var/svn
svnadmin create /var/svn/repos

We will be using path-based authorization. Create a file /var/svn/paths with a content like the following (check the path-based authorization documentation for details). Caution, it appears that path specifications (between square brackets) do not work if you put a trailing slash, so do not put a trailing slash, as in the following:

yourlogin = rw
close_friend = r

close_friend = rw
other_friend = rw

Give ownership of everything to Apache with:

chown -R www-data:www-data /var/svn

Configuring Apache

First, you should enable the necessary modules:

a2enmod dav_svn authz_svn auth_digest

Next, restart Apache with service apache2 restart.

Edit the file /etc/apache2/sites-enabled/000-svn-le-ssl.conf which was created by certbot, and add the following block in the VirtualHost block:

<Location />
        DAV svn
        SVNPath /var/svn/repos
        AuthType digest
        AuthName "example.com version control"
        AuthUserFile /etc/vcs_passwd
        AuthzSVNAccessFile /var/svn/paths
        Require valid-user

Reload the Apache configuration with service apache2 reload. Hopefully the config should be accepted, and you should be able to checkout on a remote machine:

svn co https://svn.example.com/ myrepos

You should then be able to commit, etc.

This guide does not cover the task of setting up a backup (e.g., a periodic rsync) of the repository, i.e., the /var/svn folder.

Setting up git

We will be using git-http-backend, and create multiple repositories with one user group per repository.

For now, create the structure:

mkdir -p /var/git/repos
touch /var/git/groups

You should then make sure that this is readable by www-data.

Creating each git repository and setting up access rights

To create a git repository for project proj1, do:

cd /var/git/repos
git init --bare proj1
chown -R www-data:www-data .

Now, add to the file /var/git/groups a line to indicate who has the right to access this project (this is both read and write access):

proj1: yourlogin close_friend other_friend

Configuring Apache (initial configuration)

This only needs to be done the first time.

First, you should enable the necessary modules:

a2enmod macro authz_groupfile cgi auth_digest

And restart Apache.

Next, edit the file /etc/apache2/sites-enabled/000-git-le-ssl.conf and add, inside the VirtualHost block:

DocumentRoot /var/git/repos/
SetEnv GIT_PROJECT_ROOT /var/git/repos/
ScriptAlias / /usr/lib/git-core/git-http-backend/

<Macro Project $repos>
        <Location /$repos>
                AuthType digest
                AuthName "example.com version control"
                AuthUserFile /etc/vcs_passwd
                AuthGroupFile /var/git/groups
                Require group $repos

UndefMacro Project

Configuring Apache (for each project)

Now, each time you add a project, say proj1, you should add the following line just before the UndefMacro line:

Use Project proj1

And of course you should issue service apache2 reload. You should now be able to do the following:

git clone https://git.example.com/proj1

To avoid getting asked about your password each time (and storing it in plaintext, which is OK if you trust the security of your machine and you use disk encryption), you can issue the following (see the end of this answer):

git config --global credential.helper store

As with Subversion, you should then arrange to back up the /var/git folder.

comments welcome at a3nm<REMOVETHIS>@a3nm.net