I use Trac for almost any project and so I have have a server running with several instances of Trac. One instance per project. The different Trac installs I manage are accessed through a subdomain, trac.example.org for example. Each Trac instance is located in a virtual directory, e.g. trac.example.org/trac1, trac.example.org/trac2, etc.
For some projects I use subversion. I configured apache to serve subversion through DAV. The subversion repositories are accessible using svn.example.org as subdomain and a virtual directory per repository, similar to Trac.
Now as I am the only user of these projects I used a messy configuration that led to some sort of single sign on. Now I've reached the point that more people are going to use Trac and SVN, so the single sign on is no longer desirable (except for me, the administrator). So I came up with a solution to let apache determine access at directory level and let Trac manage its own permissions.
In my apache's "vhost.d" directory I've put a file named trac.conf. This configuration file looks like this:
<IfDefine TRAC> #only run this file if TRAC is defined
<IfModule !dav_svn_module> #load dav_svn_module if it isn't loaded already (required by authz_svn_module)
LoadModule dav_svn_module modules/mod_dav_svn.so
</IfModule>
<IfModule !authz_svn_module> #load authz_svn_module if it isn't loaded
LoadModule authz_svn_module modules/mod_authz_svn.so
</IfModule>
Listen 443 #listen on port 443 (SSL)
NameVirtualHost *:443
<VirtualHost *:443>
ServerName trac.example.org #hostname, just an example
Include /etc/apache2/vhosts.d/ssl.include #include some ssl stuff
Include /etc/apache2/vhosts.d/trac/*.conf #include trac projects
Alias /[^/]+/chrome/common /var/www/trac/common #map common trac libs
<Location />
SVNPath /var/www/trac #directory containing Trac http dirs
AuthzSVNAccessFile /var/www/trac/access #policy file
Require valid-user
AuthType Digest
AuthName "/" #must match the realm in the digest file
AuthUserFile /var/www/trac/trac.htpasswd #the digest file
Order deny,allow
SSLRequireSSL #because I want things to be safe :-)
</Location>
</VirtualHost>
</IfDefine>
In the "vhost.d" directory I have a directory named "trac" containing config files that create a trac instance.
example:
<IfDefine TRAC>This file only maps the virtual directory to the Trac wsgi script, generated by trac-admin.
WSGIScriptAlias /project1 /var/www/trac/project1/cgi-bin/trac.wsgi
<Directory /var/www/trac/project1/cgi-bin>
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
</IfDefine>
The Trac hosting is done with this. The SVN hosting is done by a module. The module is located in apache's "modules.d" directory and it's named "47_mod_dav_svn.conf".
Mine looks like this:
<IfDefine SVN> #only host when SVN is defined
<IfModule !dav_svn_module> #load dav_svn_module
LoadModule dav_svn_module modules/mod_dav_svn.so
</IfModule>
<IfDefine SVN_AUTHZ>
<IfModule !authz_svn_module> #load authz module if desired
LoadModule authz_svn_module modules/mod_authz_svn.so
</IfModule>
</IfDefine>
<VirtualHost *:443> #again only listening on SSL
ServerName svn.example.org
Include /etc/apache2/vhosts.d/ssl.include #include common ssl stuff
<Location />
DAV svn
SVNParentPath /var/svn #directory containing the repositories
AuthType Digest
AuthName "/" #matching the digest realm
AuthUserFile /var/www/trac/trac.htpasswd #same digest file as the one used for Trac
AuthzSVNAccessFile /var/svn/access #access file for all SVN repositories
Order deny,allow
Require valid-user
SSLRequireSSL #require SSL :-)
</Location>
</VirtualHost>
</IfDefine>
Now I can define access for SVN per repository using a ACL file. Example:
[groups]
admin = admin, siebz0r
prjA = foo
prjB = bar
[/]
@admin = rw
[project-A:/]
@prjA = rw
[project-B:/]
@prjB = rw
The file defines 3 groups:
- admin
- prjA
- prjB
prjA only has read/write access to the project-A repository.
prjB only has read/write access to the project-B repository.
note: You can do more things like add a group to a group.
To revoke all permissions in a directory simply specify the user or group followed by a =.
For example if I would like to revoke all permissions for "foo" I'd write a line "foo = " under the directory I want.
The file for the Trac environments is likewise. The difference is that in stead of "[project-A:/]" I would have to specify "[/project-A]" to configure the directory.
Only read access is required as the rest of the permissions depend on Trac's configuration.
The only caveats are that if you use a global config/policy file for all Trac environments and if a user has access to multiple Trac environments, the user has the same permissions in all environments. Luckily this doesn't create a problem for me.