Recently I set up an SVN repository in the hopes that maybe I can show off some of my programming work to potential clients (or maybe just other people who are interested). I ran into sufficient trouble during setup that I thought it would be a good idea to give a run-down of my setup for others.
My setup runs on Apache/Linux, on a subdomain of one of my sites. I have a root SVN directory that can hold multiple repositories. While the repos are accessible via SVN, you can also browse them through a web interface (though it’s fairly simple, basically just lists of “directory” contents). The repos give anonymous access for checkouts and other “read” functions, but are login-protected for commits and other “write” functions.
The guides I came across for setting up SVN mostly want you to put your settings in the file /etc/apache2/mods-available/dav_svn.conf , but I found that it works just fine if you set it up like a regular site/subdomain. That is, as a VirtualHost entry in a file in /etc/apache2/sites-available. So here is my VHost entry for SVN:
<VirtualHost *> ServerName svn.eternicode.com <Location /> Order allow,deny Allow from all DAV svn SVNParentPath /var/www/svn SVNListParentPath on AuthType Basic AuthName "Eternicode SVN Repo" AuthUserFile /etc/apache2/mods-available/dav_svn.passwd <LimitExcept GET PROPFIND OPTIONS REPORT> Require valid-user </LimitExcept> </Location> ErrorLog /var/log/apache2/error_svn.log CustomLog /var/log/apache2/access_svn.log combined </VirtualHost>
Most of the special, SVN-specific stuff comes inside the <Location> tags; the ServerName, ErrorLog, and CustomLog are standard Apache directives.
SVNParentPath is the “root” repo directory; your various repos will be below this directory. If you only want to host a single repo here, change the directive to just “SVNPath”. The SVNListParentPath allows web access to a listing of all available repos; if you use SVNPath, remove SVNListParentPath. If SVNListParentPath is off or omitted, users will get a 403 Forbidden error when browsing the parent directory.
AuthType, AuthName, and AuthUserFile define the login settings; the AuthUserFile is created with the htpasswd command.
The LimitExcept section is where we differentiate between anonymous reads and protected writes. For everything other than GET, PROPFIND, OPTIONS, and REPORT methods, we want to Require a valid-user; if someone wants to commit, they have to authenticate according to the AuthUserFile defined above.
One issue I ran into was that, after everything was seemingly set up properly, any svn commands would result in a “Moved Permanently” error. It turned out that I had defined the DocumentRoot to also be /var/www/svn; this would conflict with the svn settings, confuse apache, and result in the Moved error. Don’t include a DocumentRoot; the svn setup will take care of everything once you give it an SVNParentPath.
Credits: Sematopia.com has a nice little guide that takes you through steps outside of the apache configuration (though their 4-line apache config is scarily sparse). Sellersrank.com has a guide for setting up Apache-run SVN over https; though I’m not using https, this guide helped me get my settings right.
A few notes: Don’t use a DocumentRoot, only use the SVNParentPath. Make sure the parent path is owned by user and group www-data (or whatever user your apache instance uses). You can ensure this by:
$ sudo chown -R www-data.www-data /var/www/svn
While it would be extremely nice to be able to create new repositories with a simple “svn import”, it seems svn’s capabilities are restricted in that area. It wouldn’t be too difficult to set up a cron job to monitor the SVN logs and create new repos as required, but that’d be hacky and inadequate. To create a new repository, you first have to run
$ sudo svnadmin create /var/www/svn/new_repo
on the server. However, in order to not have issues with the fact that the web server owns all the svn files, I’d recommend creating new repos as the www-data user:
$ sudo su www-data -c "svnadmin create /var/ww/svn/new_repo"
Once the initial repo structure is created, you can then use “svn import” on a remote machine to import the first revision.