Svn – Optimizing Apache Subversion Configuration – Remove duplicate config blocks

apache-2.2svn

I have a repeating authentication block for each of my repositories and was wondering, if there is a way to reuse the block and optimize our setup.

This setup enables us to browse to code.domain.com to view all the repositories and browse the source code (as all repositories are open for read).

Here is my current configuration:

<VirtualHost *:80>
    DocumentRoot /u01/subversion/repositories
    ServerName code.domain.com
    ServerAdmin admin@domain.com

    <Location />
        Options Indexes MultiViews FollowSymLinks IncludesNoExec
        Order allow,deny
        Allow from all      
    </Location>


    <Location /repoA>
        DAV svn
        SVNPath /u01/subversion/repositories/repoA
        SVNIndexXSLT "/share/svnxslt/svnindex.xsl"

        AuthzSVNAccessFile /u01/subversion/svnrepos.acl
        AuthName "Source Code Repository / Repertoire de code"

        AuthBasicProvider ldap
        AuthType Basic
        AuthzLDAPAuthoritative off
        AuthLDAPURL "ldap://domain.com?sAMAccountName" NONE
        AuthLDAPBindDN "bindDN"
        AuthLDAPBindPassword bindPwd
        Satisfy Any
        Require valid-user
    </Location>

    # duplicated Location for repoB, repoC, etc...

</VirtualHost>

I found this (and implemented it), however, I get the following error:

[Fri Jul 26 14:41:37 2013] [error] [client x.x.x.x] (25)Inappropriate ioctl for device: The URI does not contain the name of a repository. [403, #190001]

Configuration file:

<VirtualHost *:80>
    DocumentRoot /u01/subversion/repositories
    ServerName code.domain.com
    ServerAdmin admin@domain.com

    <Location />

        Options Indexes MultiViews FollowSymLinks IncludesNoExec
        Order allow,deny
        Allow from all

          DAV svn
          SVNParentPath /u01/subversion/repositories
          AuthBasicProvider ldap
          AuthzLDAPAuthoritative Off
          AuthLDAPURL "ldap://domain.com?sAMAccountName" NONE
          AuthLDAPBindDN "bindDN"
          AuthLDAPBindPassword "bindPwd"
          AuthType Basic
          AuthName "Use your sAMAccountName to connect. If you're unsure, write to contact@...com."
    </Location>

    <Location /repoA>
      SVNPath /u01/subversion/respositories/repoA
      Satisfy Any
      require valid-user
    </Location>

    # Other Locations for each repoB, repoC, etc...
</VirtualHost>

Worst case, I keep the redundant configuration I guess.

Update #1

Almost there… can't browse the root of the domain however – get a 401 error…

<VirtualHost *:80>
    ServerName code.domain.com
    ServerAdmin admin@domain.com

    DocumentRoot /u01/subversion/repositories/
    <Directory /u01/subversion/repositories/>
        Options Indexes MultiViews FollowSymLinks IncludesNoExec
        Order allow,deny
        allow from all
    </Directory>

    <Location />
        AuthBasicProvider ldap
        AuthType Basic
        AuthzLDAPAuthoritative off
        AuthName "SVN Repository. Authorization required."
        AuthLDAPBindDN "bindDN"
        AuthLDAPBindPassword "bindPwd"
        AuthLDAPURL "ldap://domain.com?sAMAccountName" NONE
        AuthzSVNAccessFile /u01/subversion/svnrepos.acl
        SVNParentPath /u01/subversion/repositories

        Satisfy Any
        Require valid-user
    </Location>



    <Location /repoA>
        DAV svn
        SVNPath /u01/subversion/repositories/repoA
         SVNIndexXSLT /share/svnxslt/svnindex.xsl
    </Location>

    # Other Locations   


</VirtualHost>

Update #2

I'm getting this error now when browsing the root only:
Directory index forbidden by Options directive: /u01/subversion/repositories/

However, I see that Indexes is present in the Option declaration in the Directory directive…

Update #3 (Lazy Badger proposed solution)

When I access the root, I see .xsl and .css files and not the repositories. However, /svn/ will list the repo, but the end goal is to have /svn/ be the root of the site instead.

<VirtualHost *:80>
    ...

    # /u01/subversion-docs is where .xsl and .css reside
    DocumentRoot "/u01/subversion-docs"

    <Directory />
      Options Indexes MultiViews FollowSymLinks IncludesNoExec
      AllowOverride None
      Order allow,deny
      Allow from all

      RewriteEngine on
      RewriteCond %{REQUEST_URI} ^/svn$
      RewriteRule ^(.*/svn)$ %1/ [R=301,L]
    </Directory>

    <Location /svn/>
      DAV svn

      SVNListParentPath on
      SVNParentPath /u01/subversion/repositories
      SVNIndexXSLT "/svnindex.xsl"  

      ...

      Satisfy Any
      require valid-user

    </Location>

</VirtualHost>

Best Answer

I'm sorry, but you must to read and remember some ABCs before going deeper

  • Single <Location> can handle any amount of Subversion repositories (if they are childs of common directory)
  • Single AuthzSVNAccessFile can handle any amount of repositories and paths inside these repositories
  • Directives, defined in <Location> container, are inherited in subpaths of location, if not explicitly redefined

If you business-task is really

Have a collection of repositories with common LPAD-authentication and XSLT-based templating of HTML-pages with path-based authorization

Let's transform my ugly draft (VisualSVN Server default config used, less important parts skipped) into functional solution for your case

...
ServerRoot SOME/PATH/TO/SERVER
...
DocumentRoot "htdocs"
...
<Directory />
  Options FollowSymLinks
  AllowOverride None

  RewriteEngine on
  RewriteCond %{REQUEST_URI} ^/svn$
  RewriteRule ^(.*/svn)$ %1/ [R=301,L]
</Directory>
...
<Location /svn/>
  DAV svn

  SVNListParentPath on
  SVNParentPath /PATH/TO/PARENT/OF/REPO/DIR
  SVNIndexXSLT "/svnindex.xsl"  
...
  AuthName 
  AuthType Basic
  AuthBasicProvider file
  AuthUserFile "...htpasswd"
  AuthzSVNAccessFile "...authz"

  Satisfy Any
  require valid-user

...
</Location>
...

Notes

  • ServerRoot defined in order to use relative paths later
  • DocumentRoot doesn't correlate with DAV-location later and it's ordinary (not WebDAV) part of site, which contain template for SVNIndexXSLT directive
  • WebDAV location moved out of root of site in order to have "normal" part of site for ordinary http

First change: basic auth replaced by LDAP-powered

<Location /svn/>
  DAV svn

  SVNListParentPath on
  SVNParentPath /PATH/TO/PARENT/OF/REPO/DIR
  SVNIndexXSLT "/svnindex.xsl"  
...
  AuthBasicProvider ldap
  AuthType Basic
  AuthzLDAPAuthoritative off
  AuthName "SVN Repository. Authorization required."
  AuthLDAPBindDN "bindDN"
  AuthLDAPBindPassword "bindPwd"
  AuthLDAPURL "ldap://domain.com?sAMAccountName" NONE
  AuthzSVNAccessFile "...authz"
  Satisfy Any
  require valid-user    
...
</Location>

Second change: SVNParentPath

<Location /svn/>
  DAV svn

  SVNListParentPath on
  SVNParentPath /u01/subversion/repositories/
  SVNIndexXSLT "/svnindex.xsl"

Third change: ServerRoot+DocumentRoot

Define these roots somehow, don't forget to place svnindex.xsl and all other needed files to DocumentRoot

Fourth change

Add ACLs to AuthzSVNAccessFile, write paths inside collection of repo as [REPO:/PATH/IN/REPO]