Apache with Multiple Dynamic Subversion Repositories

A few days ago I was configuring Subversion on one of my linux servers and I started looking for a way to dynamically expose the repositories complete with a separate users database. I was hoping to make it totally dynamic so that I could just add a new repository, configure the permissions (see my earlier post on per-directory access controls) and create the accounts. I tried something like this:

<VirtualHost virtual-host-1:80>
 ServerName svn.domain.tld
 
 SetEnvIf Request_URI "/([^/]+)(?:/?|/.*)?" REPOSITORY_NAME=$1
 
 <Location />
  DAV svn
  SVNPath /path/to/svnrepositories/${REPOSITORY_NAME}
  AuthzSVNAccessFile /path/to/svnrepositories/${REPOSITORY_NAME}/conf/httpd.access
  AuthUserFile /path/to/svnrepositories/${REPOSITORY_NAME}/conf/httpd.passwd
  Require valid-user
  AuthType Basic
  AuthName "Subversion Repository"
 </Location>
</VirtualHost>

The key is this line: SetEnvIf Request_URI "/([^/]+)(?:/?|/.*)?" REPOSITORY_NAME=$11. If you browse to http://svn.domain.tld/someRepository it conditionally sets an Apache environment variable to someRepository which you can use to reference a specific repository, password file and access list. Perfect, right?

Unfortunately it's not that easy – you can't use dynamically set environment variable in any directive arguments. Crap! There are some other solutions out there like mod_macro, but I've had some issues with that in the past. mod_perl and a <Perl> tag might work, but I've never used that before and I want to keep my configuration simple (and minimize the time spent on this).

I decided to take the easy way out and sacrifice some functionality. The SVNParentPath directive allows you to define a path under which any directories will be assumed to be SVN repositories. Now I can add new repositories on the fly without restarting Apache, but I still don't have multiple user files.

In the end having distinct user files isn't that big of a deal, especially if you aren't worried about username conflicts and because you can control permissions on a per-repository basis in your user file. Here's a sample access file:

[groups]
group1 = bill, joe
 
[/]
# By default no one except corey has permissions at the root level
* =
corey = rw
 
[Some_Project:/]
# grant all members of group1 full permissions on Some_Project
# corey will inherit permissions from /
@group1 = rw

My final Apache configuration looked like this:

<VirtualHost virtual-host-1:80>
 ServerAdmin webmaster@domain.tld
 DocumentRoot /home/domain/public_html
 ServerName svn.domain.tld
 
 <Location />
  DAV svn
  SVNParentPath /home/domain/svn
  AuthzSVNAccessFile /home/domain/svnauth/httpd.access
  AuthUserFile /home/domain/svnauth/httpd.passwd
  Require valid-user
  AuthType Basic
  AuthName "Subversion Repository"
 </Location>
</VirtualHost>

As always, the book Version Control with Subversion (buy it from Amazon) was a big help.

  1. If you want to use parenthesized expressions with SetEnvIf you'll need Apache 2.0.51 or newer. [back]

 

Leave a Reply


© 2007-2013, Corey Gilmore | Posts RSS Feed | Comments RSS Feed | Contact

 

The views expressed on these pages are mine alone and not those of any past or present employer. All information presented on this site was obtained lawfully and not through disclosure under the terms of an NDA.

‹