Subversion transparent proxy with svnsync + WebDAV proxy

Introduction

This article describes a a master-slave setup of subversion, where the slave acts as a transparent proxy, in the sense that the user connecting to the slave server does not really know that he is talking to a slave server and not the master.

This setup integrates two modules, WebDAV proxy and svnsync to achieve its purpose. The following item list explains how they work together:

Index

Slave configuration

WebDAV proxy support is new in subversion 1.5. At the time of writing, v1.5 has not been released yet. This article does not describe how to build your own subversion binary. As a small hint: I compiled my version with the following line (if this does not help you, then it might be safe for you to wait for the final release of version 1.5):

./configure --prefix /usr/local/subversion \
        --with-httpd --with-apxs=apxs2 --disable-mod-activation \
        --without-berkeley-db --without-neon --with-serf=/usr

Slave Apache setup

In order to set up a WebDAV proxy server in Apache, all we need to do is to load the modules dav_module (mod_dav.so), dav_svn_module (mod_dav_svn.so) and proxy_module (mod_proxy.so). The configuration is straight-forward. Let's say we want to mirror a remote repository from https://svn.example.org/source/repos to the local path /path/to/local/repository, and this repository shall be accessible at the location /local/repository. All we need is to add the following Location directive in the Apache configuration file:

<Location /local/repository>
    DAV svn
    SVNPath /path/to/local/repository
    SVNMasterURI https://svn.example.org/source/repos
</Location>

Slave repository setup

Now let's create the slave repository, accessible for the user svnsync:

svnadmin create /path/to/local/repository
chown svnsync: /path/to/local/repository -R

Before svnsync update the data from the server, we have to manually create the file /path/to/local/repository/hooks/pre-revprop-change with the following content:

#!/bin/sh
USER="$3"

if [ "$USER" != "svnsync" ]; then
    echo >&2 "Only the svnsync user can change revprops"
    exit 1
fi

exit 0

Let's make it executable with the following command and we're ready to go.

chmod +x /path/to/local/repository/hooks/pre-revprop-change

The slave repository is initialised by the following command line:

svnsync init --username svnsync file:///path/to/local/repository \
                                https://svn.example.org/source/repos

Once the repository is initialised, further updates need only the minimal command line:

svnsync sync file:///path/to/local/repository

Should the synchronisation fail and leave the repository locked, then the following line deletes. the lock. Please be aware that you can seriously screw your repository up if you delete the lock while svnsync is running!

svn pdel --revprop -r 0 svn:sync-lock file:///path/to/local/repository

The SVN slave sync script

The operations described in this section can be performed by the mighty SVN slave sync script.

Master configuration

The master server must run subversion 1.4 or higher in order to provide support for svnsync. Strictly speaking, no configuration is needed on the server to allow the slave to mirror a repository, but as soon as data is committed on the server, the slave's repository will get more and more out of date. We need thus a mechanism to trigger the replication from the master to the slave server. We can do this easily by editing the post-commit hook script on the master repository. That script might look like:

#!/bin/sh
#
# REPOS="$1"
# REV="$2"

ssh -l svnsync svn-slave.example.org "/path/to/svn-sync-slave.sh -r /path/to/local/repository"

Obviously ssh must be configured in a way not to ask the password. The page How to setup SSH without password (one out of many) explains how to add a non-password login with ssh.

The svnsync documentation is minimal but enough for a quick start. The article using svnsync gives more hands-on information. For WebDAV proxy configuration, see the WebDAV proxy documentation.