My background task over the Christmas holidays was to ensure that I had the ability to give read/write access to a subversion repository situated on a machine within our corporate network so that staff or external contractors can access it via the interweb but without me needing to open up additional ports on our firewall.
The server running Debian ‘etch’ is sitting within our DMZ and is only open to the outside world via port 80 for apache and also for ssh listening on a non-standard port. Internally we can access the repositories using the svn:// method between the internal network and the DMZ using the standard svn password-db authentication (and the handy password caching that this provides).
To give external access it seemed a no-brainer that I’d tunnel over ssh especially when I found out that I could set it up so that authentication would be dealt with by maintaining system (i.e. ssh) users for remote access (which all relevant staff have anyway) and could then administrate separately my local-only svn users that access via the plain-text svn://method. On balance I figured this would work for me as I’d rarely need to give access to an ‘outsider’ and when I did then them having a non-privileged user account on the machine wouldn’t be a big deal.
In the end it turned out to not be too difficult to get working though there was a bit of hoop jumping; I was expecting as much after reading this in the svn book:
Once you’ve jumped through these hoops, your repository should be accessible by all the necessary processes. It may seem a bit messy and complicated, but the problems of having multiple users sharing write-access to common files are classic ones that are not often elegantly solved.
Permissions were the biggest issue and the first thing that I did was to add all external users to the svn group. I already have everything chmoded 2770 with owner/group being ‘svn’ but when accessing over ssh the lock files (amongst others) are read-only for everyone except the svn user. To fix this I had to create two wrapper scripts for the svn and svnserve binaries respectively that set the correct umask:
…where svn-real is the renamed svn binary and this script is /usr/bin/svn, repeat for /usr/bin/svnserve.
That was pretty much it except that for external access the way to connect was slightly different. Firstly the connection ‘URL’ was of the form svn+ssh:// for example:
svn co svn+ssh://hostname/path/to/remote/project/trunk
Also, because we’re connecting over ssh via a non-standard port I needed to set an environment variable for the user on the client machine. To do so I simply added the following to their ~/.profile:
export SVN_SSH="ssh -p PORT_NUMBER".
That was it.
So, in summary to give external access all I now need do is:
- Create a system account on the svn server
- Add that account to the svn group
- Tell that user to create a local SVN_SSH environment variable so they connect via ssh over the right non-standard port
Complicated to set-up? Not really. Easy to administer? Yes. Secure? As good as I could make it.