Subversion on Apache Without Tears

H. Sparks
2014-12-23
http://www.csparks.com/Subversion.xhtml

Introduction

You can let apache be your subversion server and never use command line tools to create or manage the repositories.

The idea is very simple: overlap a WebDAV location with the top level SvnDAV location. Now users with appropriate credentials can create their own repositories using a GUI such as TortoiseSVN.

Configuring WebDAV

WebDAV is a scheme that allows you to mount remote directories using only web access to the remote server. The effect is similar to ftp, but it only uses http.

Here is a configuration to setup a WebDAV directory:

        Alias /svndav  /var/www/svn

        <Directory /var/www/svn >
		DAV on
		Satisfy all
		Order deny,allow
		Allow from all
		AuthType Digest
		AuthName "SVN Users"
		AuthDigestDomain /svndav /svn
		AuthUserFile davusers.digest
		Require valid-user
		SSLRequireSSL
        </Directory> 

If you don't want regular users to create new repositories, a different realm may be used such as "SVN Administrators." Details about configuring digest authentication are covered below.

Configuring SvnDAV

This is the configuration to make Apache perform subversion server functions. Note that it uses a Location section rather than a Directory section: Apache would be confused if two directories explicitly overlapped.

	LoadModule dav_svn_module modules/mod_dav_svn.so
	LoadModule authz_svn_module modules/mod_authz_svn.so

	<Location /svn>
		DAV svn
		SVNParentPath /var/www/svn
		SVNAutoversioning on
		Order deny,allow 
		Allow from all
		Satisfy any
		AuthType Digest
		AuthName "SVN Users"
		AuthDigestDomain /svndav /svn
		AuthUserFile davusers.digest
		AuthzSVNAccessFile svnusers.conf
		Require valid-user
		SSLRequireSSL
	</Location> 

The AuthDigestDomain directive causes Apache to inform the client browser about all URIs on the server that are protected by the same digest realm. (See the next section for a discussion of realms.) The browser will ask for a username and password the first time the user visits one of these URIs. But after that, the user can visit any of the others and the browser will supply the same credentials automatically.

There seems to be some confusion on the web about the use of trailing "/" characters in the paths specified with AuthDigestDomain. It seems to work best if the path names match the names specified in the Location or Alias directives. There is no need for trailing slashes as long as the expressions agree.

The Satisfy Any directive tells Apache to allow access if either the Allow directive is satisfied or one of the Auth modules is satified. The "Allow from all" is always satisfied. But we have two Auth modules: AuthzSVN and AuthDigest. In this case AuthzSVN will look into the svnusers.conf file. If no user name is required for the requested resource, no prompt for authentication will occur. But if a username is required, the AuthDigest module will come into play and prompt for credentials. The authorized name is allowed to do whatever the AuthzSVNAccessFile permits.

IMPORTANT: Don't use Satsify Any without svnusers.conf properly configured or anonymous users will be able to alter your repositories!

SSL is almost essential if you access your repositories over the internet. But even on a LAN, Windows clients will not work easily without registry adjustments.

It turns out that Apache mod_security and mod_svn_dav don't get along very well. Omer Dawelbeit has discovered a solution that worked for me, with some caveats. To use his discovery, add this section inside the Location element listed above:

	<IfModule mod_security2.c>
		SecRuleRemoveByID 960032
		SecRuleRemoveByID 960015
		SecRuleRemoveByID 960904
		SecRuleRemoveByID 960010
		SecRuleRemoveByID 960035
		SecRule REQUEST_METHOD "^(PROPFIND|PROPPATCH)$" allow
		SecRule REQUEST_METHOD "^(REPORT|OPTIONS)$" allow
		SecRule REQUEST_METHOD "^(MKACTIVITY|CHECKOUT)$" allow
		SecRule REQUEST_METHOD "^(PUT|DELETE|MERGE)$" allow
		SecRule REQUEST_METHOD "^(MKCOL)$" allow
	</IfModule>

With these incantations, everything seemed to work on my server, but the ssl_error_log rapidly filled with mod_security messages. Evidently mod_security was simply tollerating my use of subversion with disguised revulsion.. After a week or two looking for answers, my aggravation quota was used up. I changed the section to read:

	<IfModule mod_security2.c>
		SecRuleEngine off
	</IfModules>

Adding users for digest authentication

Apache has many access control mechanisms, but for use with svn, digest authentication has the advantage of supporting realms.

In the Apache config file above, the AuthName directive specifies the name of a digest authentication realm. The realm concept lets you use the same AuthUserFile for several different authentication tasks. For example, you could have a realm for subversion users and another for webdav access to your home page.

To create the file and add the first user, go into the top level apache config folder (/etc/httpd on redhat/fedora systems) and run this command:

	htdigest -c davusers.digest "SVN Users" yourUserName 

Subsequent additions are done without the -c options:

	htdigest pathToFile realmName userName 

You are prompted for the password when adding users. To change a password, just use the name of an existing user.

This level of authentication is all-or-none: If the user is in the digest file, they can see all of the repositories and have full read/write access. This gets fixed by using the AuthzSVNAccessFile directive described below.

Using Subversion access control

After digest authentication, finer control is imposed by the AuthzSVNAccessFile:

	AuthzSVNAccessFile svnusers.conf 

It contains lines of the form:

	# All repositories: 
	[/]
	bill=r
	john=rw
	peter=rw
	badguy=

	# Only Walter can access PrivateProject
	[PrivateProject:/]
	walter=rw

	# Janet is the administrator of OpenSourceProject,
	everyone else can read:
	[OpenSourceProject:/]
	janet=rw
	*=r

	# Define some groups
	[groups]
	friends=mark,goober
	others=john,bill,peter
	writers=sally,doug

	# Friends have read/write access to BigProject, others not:
	[BigProject:/]
	@friends=rw
	@others=r

	# Writers can work on /trunk/Documents in ANY project
	[/trunk/Documents]
	@writers=rw 

All the names must also be configured in the digest file. After entering your credentials once at the digest prompt, they are shared by AuthzSVN transparently.

In the example shown above, the OpenSourceProject has an expression *=r which will allow anonymous read-only access to the repository. This feature requires the Satisfy Any directive in the Apache configuration.

Testing subversion access policies

On windows clients, when you check the "Remember password" box, TortoiseSVN saves your credentials in:

	C:\Documents and Settings\UserName
		\Application Data\Subversion\auth\svn.simple 

If you are the repository admin and have saved your credentials, it is hard to test more refined criteria for new users and groups. If you delete the files in the svn.simple directory, you credentials are forgotten. Then you can test access permissions as some other user.

Creating a repository template

You can use a GUI client such as TortoiseSVN to create a local repository and then drag it to the mounted svndav directory. But this will only work properly if the subversion database format is the same for both the server and the client. A better way is to create a template repository on the server and then use webdav to duplicate and rename it to become your new repository.

On the server, create a template repository:

	svnadmin create AATemplate 

If the server is running linux, you need to make Apache the owner of the new repository:

	chown -R apache:apache AATemplate 

If you use the standard trunk, branches, tags structure on your projects, you can add these to the template using your svn client software.

With the template completed, you can create a new repository in just a few seconds:

  1. Mount the svndav directory.
  2. Duplicate the AATemplate repository.
  3. Rename the new repository.

On a windows client, you can rapidly duplicate the repository by selecting AATemplate and typing the key sequence <control>C <control>V.

Now you can checkout the trunk on the client and start adding files. If you are starting a new repository for an existing project, checkout the trunk of the new repository right on top of the existing project directory. The subversion client will complain that the directory is not empty, but you can safely ignore this warning. Next, go into the project directory, select all the files (except .svn) and do "svn add" followed by "svn commit". Your new repository is completed.

Fixing Windows

Applying patches

Both XP and Vista require patches from Microsoft to make webdav work properly. This is still true as of XP SP3 and Vista SP1. Microsoft uses the term Web Folders so you won't be confused by the thousands of articles on the web that use the term WebDAV. ;-)

Here is patch 1 for Windows XP and Vista. Here is patch 2 for Vista. Patch 2 is already supplied by Vista SP1, but patch 1 is still needed.

Running the Windows XP Web Folder Fixer

Because I (and others) have thrashed around for weeks trying to get Windows clients working with the Apache server, a certain amount of folklore has been reported. The use of the following "repair tool" fits into that category.

Some people have reported that is is helpful to run this repair tool after installing the patches described above. (Most things work without this, but prompting for credentials sometimes fails if you don't.) I am uncertain about what it does. It may even remove all or part of the patch!

In the Run box, enter webfldrs.msi and hit Ok. A window will appear with buttons. Press "Select reinstall mode", then check every box except "Reinstall only if file is missing." Hit Ok to return to the main window and then press "Reinstall." You don't have to reboot.

AuthDigestDomain is required

When using a Windows client (and maybe others), the AuthDigestDomain directive on the server is very necessary in this situation:

  1. You host multiple WebDAV areas protected by different realms.
  2. You use same domain name to access all these areas.

If you don't configure AuthDigestDomain correctly in that situation, Windows clients will get confused about which domain names go with which realms when you check the "Remember password" box. Subsequent access attempts will prompt for credentials and write access will fail. The Apache server's ssl_error_log will report:

	Digest: realm mismatch - got `xxxx' but expected `yyyy' 

Clearing the credentials cache on Windows XP

If you're having trouble with Apache authorization from a Windows client, it is often helpful to make Windows forget all the remembered network credentials. They are cached in this directory:

	c:\Documents and Settings\<username>\Microsoft\Credentials\<your SSID>

In that folder, delete the file named Credentials. All network credentials will be erased so you will be prompted for them the next time you try to access the protected resources.

Subversion also maintains a cache for credentials which you can reset. The directory is here:

	C:\Documents and Settings\<username>\Application Data\Subversion\auth

In this directory are several subdirectories. You can safely delete all of them. Subversion (or your favorite subversion client) will prompt you for new credentials the next time you access the remote repository.

When I'm fussing around with Apache security, I keep shortcuts to both of these caches on the Windows desktop.

SSL works best

For me, the big secret of getting Windows XP and Vista to work as trouble-free clients for Apache WebDAV was using the https protocol with real SSL certificates. All other solutions I tried (and I tried nearly everything suggested on the web) has drawbacks or irregular annoyances. If you want to fight with using basic authentication without SSL, here is a link to get you started.

References