<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="/stylesheet.xsl"?>

<page name="Subversion on Apache Without Tears"
	xmlns="http://www.csparks.com/XMLWithoutTears"
	version="2014-12-23"
	author="H. Sparks"
	url="http://www.csparks.com/Subversion.xml">

<s name="Introduction">
	<p>
	You can let apache be your subversion server and
	<i>never</i> use command line tools to create or
	manage the repositories.
	</p>

	<p>
	The idea is very simple: overlap a <i>WebDAV</i> location
	with the top level <i>SvnDAV</i> location. Now users with
	appropriate credentials can create their own repositories
	using a GUI such as <i>TortoiseSVN.</i>
	</p>
</s>

<s name="Configuring WebDAV">
	<p>
	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. 
	</p>

	<p>
	Here is a configuration to setup a WebDAV directory:	
	</p>

	<code><![CDATA[
        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> ]]></code>

	<p>
	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.
	</p>

</s>

<s name="Configuring SvnDAV">
	<p>
	This is the configuration to make Apache perform subversion
	server functions. Note that it uses a <i>Location</i> section
	rather than a <i>Directory</i> section: Apache would be 
	confused if two directories explicitly overlapped.
	</p>

	<code><![CDATA[
	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> ]]></code>

	<p>
	The <i>AuthDigestDomain</i> directive causes Apache to
	inform the client browser about all URIs on the server
	that are protected by the same digest <i>realm.</i>
	(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.
	</p>

	<p>
	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. 
	</p>
	
	<p>
	The <i>Satisfy Any</i> 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.
	</p>

	<p>
	IMPORTANT: Don't use <i>Satsify Any</i> without svnusers.conf
	properly configured or anonymous users will be able to alter 
	your repositories!
	</p>

	<p>
	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.
	</p>

	<p>
	It turns out that Apache mod_security and mod_svn_dav don't
	get along very well. Omer Dawelbeit has discovered
	a <link name="solution" ref="modFix"/> that worked for me, 
	with some caveats. To use his discovery, add this section inside 
	the Location element listed above:
	</p>

	<code><![CDATA[
	<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>]]></code>

	<p>
	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 <i>tollerating</i> 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:
	</p>

	<code><![CDATA[
	<IfModule mod_security2.c>
		SecRuleEngine off
	</IfModules>]]></code>

</s>

<s name="Adding users for digest authentication">
	<p>
	Apache has many access control mechanisms, but for use
	with svn, <i>digest</i> authentication has the advantage
	of supporting <i>realms.</i>
	</p>

	<p>
	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.
	</p>

	<p>
	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:
	</p>

	<code><![CDATA[
	htdigest -c davusers.digest "SVN Users" yourUserName ]]></code>

	<p>
	Subsequent additions are done without the -c options:
	</p>

	<code><![CDATA[
	htdigest pathToFile realmName userName ]]></code>

	<p>
	You are prompted for the password when adding users.
	To change a password, just use the name of an existing user.
	</p>

	<p>
	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 <i>AuthzSVNAccessFile</i> directive described below.
	</p>
</s>

<s name="Using Subversion access control">
	<p>
	After digest authentication, finer control is imposed
	by the AuthzSVNAccessFile:
	</p>

	<code><![CDATA[
	AuthzSVNAccessFile svnusers.conf ]]></code>
	
	<p>
	It contains lines of the form:
	</p>

	<code><![CDATA[
	# 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 ]]></code>

	<p>
	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.
	</p>

	<p>
	In the example shown above, the <i>OpenSourceProject</i> has
	an expression <i>*=r</i> which will allow anonymous read-only
	access to the repository. This feature requires the <i>Satisfy Any</i>
	directive in the Apache configuration.
	</p>
</s>

<s name="Testing subversion access policies">
	<p>
	On windows clients, when you check the "Remember password" box,
	TortoiseSVN saves your credentials in:
	</p>

	<code><![CDATA[
	C:\Documents and Settings\UserName
		\Application Data\Subversion\auth\svn.simple ]]></code>

	<p>
	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 <i>svn.simple</i> directory, you
	credentials are forgotten. Then you can test access permissions
	as some other user.
	</p>
</s>

<s name="Creating a repository template">
	<p>
	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.	
	</p>

	<p>
	On the server, create a template repository:
	</p>

	<code><![CDATA[
	svnadmin create AATemplate ]]></code>

	<p>
	If the server is running linux, you need to make
	Apache the owner of the new repository:
	</p>

	<code><![CDATA[
	chown -R apache:apache AATemplate ]]></code>

	<p>
	If you use the standard trunk, branches, tags structure
	on your projects, you can add these to the template
	using your svn client software.
	</p>

	<p>
	With the template completed, you can create a new
	repository in just a few seconds:
	</p>

	<ol>
	<li>Mount the svndav directory.</li>
	<li>Duplicate the AATemplate repository.</li>
	<li>Rename the new repository. </li>
	</ol>

	<p>
	On a windows client, you can rapidly duplicate the 
	repository by selecting AATemplate and typing the 
	key sequence &lt;control&gt;C &lt;control&gt;V.
	</p>

	<p>
	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.
	</p>
</s>

<s name="Fixing Windows">
	<ss name="Applying patches">
	<p>
	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 
	<i>Web Folders</i> so you won't be confused by the
	thousands of articles on the web that use the term
	<i>WebDAV.</i> ;-)
	</p>

	<p> 
	Here is 
	<link name="patch 1" ref="XP_Patch"/> 
	for Windows XP <i>and</i> Vista. 
	Here is 
	<link name="patch 2" ref="Vista_Patch"/>
	for Vista. Patch 2 is already supplied by Vista SP1,
	but patch 1 is still needed.
	</p>
	</ss>

	<ss name="Running the Windows XP Web Folder Fixer">
	<p>
	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. 
	</p>

	<p>
	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!
	</p>

	<p>
	In the Run box, enter webfldrs.msi and hit Ok.
	A window will appear with buttons. Press "Select
	reinstall mode", then check every box <i>except</i>
	"Reinstall only if file is missing." Hit Ok to return
	to the main window and then press "Reinstall." You
	don't have to reboot.
	</p>

	</ss>

	<ss name="AuthDigestDomain is required">
	<p>
	When using a Windows client (and maybe others), the AuthDigestDomain
	directive on the server is very necessary in this situation:
	</p>

	<ol>
	<li>You host multiple WebDAV areas protected by different realms.</li>
	<li>You use same domain name to access all these areas.</li>
	</ol>

	<p>
	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:
	</p>

	<code><![CDATA[
	Digest: realm mismatch - got `xxxx' but expected `yyyy' ]]></code> 
	</ss>

	<ss name="Clearing the credentials cache on Windows XP">
	<p>
	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:
	</p>

	<code><![CDATA[
	c:\Documents and Settings\<username>\Microsoft\Credentials\<your SSID>]]></code>

	<p>
	In that folder, delete the file named <i>Credentials.</i> 
	All network credentials will be erased so you will be prompted for them
	the next time you try to access the protected resources.
	</p>

	<p>
	Subversion also maintains a cache for credentials which you can reset.
	The directory is here:
	</p>

	<code><![CDATA[
	C:\Documents and Settings\<username>\Application Data\Subversion\auth]]></code>
	
	<p>
	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.
	</p>

	<p>
	When I'm fussing around with Apache security, I keep shortcuts to both
	of these caches on the Windows desktop.
	</p>
	</ss>

	<ss name="SSL works best">
	<p>
	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 name="link" ref="BasicAuth"/> to get you started.
	</p>
	</ss>
</s>

<references name="References">
	<def name="Version Control with Subversion - Online book"
		url="http://svnbook.red-bean.com/"/>
	<def name="Wikipedia WebDAV article includes history and Windows woes."
		url="http://en.wikipedia.org/wiki/WebDAV"/>
	<def name="Linux Journal - Setting up Subversion for One or Multiple Projects"
		url="http://www.linuxjournal.com/article/7655"/>
	<def ref="XP_Patch" name="Web Folders patch for Windows XP"
		url="http://support.microsoft.com?kbid=907306"/>
	<def ref="Vista_Patch" name="Web Folders patch for Windows Vista Pre-SP1"
		url="http://support.microsoft.com?kbid=945435"/>
	<def ref="modFix" name="Subversion and Mod_Security"
		url="http://omerio.com/2009/09/26/subversion-and-mod_security"/>
	<def ref="BasicAuth"
		name="Enable basic authentication for Windows XP and Vista"
		url="http://support.microsoft.com/?kbid=841215"/>
	<def name="Subversion webdav internals"
		url="http://subversion.tigris.org/webdav-usage.html"/>
	<def name="SVNListParentPath doesn't work with mod_authz_svn"
		url="http://subversion.tigris.org/issues/show_bug.cgi?id=2753"/>
</references>

</page>

