I chose to replace the stock Ubuntu apache2.conf. The stock configuration created and maintained by Ubuntu is a somewhat clever collection of included files, but … the stock Trac and Subversion install did not do what I wanted. Figuring out what was not working was tricky enough, so I simplified and re-built the configuration from scratch.

Since I am not especially familiar with configuring Apache, and since I prefer exact control, reducing the configuration to a single file was a lot easier to understand.

This Trac server was meant for use inside a company intranet. As such it made sense to allow anyone already on the intranet to read anything in Trac or Subversion. Only authenticated users are allowed to make changes. Basic authentication is sufficient, in this context. The extra protection offered by SSL (i.e. https://) was not needed. I did want performance to be reasonably optimal.

What this does:

  • Subversion access is via Apache (HTTP).
  • Multiple Subversion repositories are allowed.
  • Multiple Trac projects are allowed.
  • Anyone can browse Trac or Subversion, but only authenticated users can make changes.
  • The same username/password file is shared between Subversion and Trac.
  • mod_python is used for (more) optimal Trac performance.
  • The Expires: header is set for static web files used by Trac.
#
#   Apache2 configuration
#

TransferLog /var/log/apache2/access.log
ErrorLog /var/log/apache2/error.log
ServerRoot /etc/apache2
DocumentRoot /var/www

#LogLevel debug

ServerAdmin preston@bannister.us
ServerName trac.bannister.home
Listen 80

User www-data
Group www-data

AddDefaultCharset UTF-8
DefaultType text/plain

LoadModule dir_module           /usr/lib/apache2/modules/mod_dir.so
LoadModule env_module           /usr/lib/apache2/modules/mod_env.so
LoadModule info_module          /usr/lib/apache2/modules/mod_info.so
LoadModule mime_module          /usr/lib/apache2/modules/mod_mime.so
LoadModule alias_module         /usr/lib/apache2/modules/mod_alias.so
LoadModule autoindex_module     /usr/lib/apache2/modules/mod_autoindex.so
LoadModule dav_module           /usr/lib/apache2/modules/mod_dav.so
LoadModule dav_svn_module       /usr/lib/apache2/modules/mod_dav_svn.so
LoadModule auth_basic_module    /usr/lib/apache2/modules/mod_auth_basic.so
LoadModule authn_file_module    /usr/lib/apache2/modules/mod_authn_file.so
LoadModule authz_host_module    /usr/lib/apache2/modules/mod_authz_host.so
LoadModule authz_user_module    /usr/lib/apache2/modules/mod_authz_user.so
LoadModule authz_svn_module     /usr/lib/apache2/modules/mod_authz_svn.so
LoadModule python_module        /usr/lib/apache2/modules/mod_python.so
LoadModule expires_module       /usr/lib/apache2/modules/mod_expires.so

TypesConfig /etc/mime.types

Alias /icons /usr/share/apache2/icons

#
#   Access to Subversion
#

<Location /svn>
    DAV svn
    SVNParentPath /var/lib/svn

    <LimitExcept GET PROPFIND OPTIONS REPORT>
        Require valid-user
    </LimitExcept>

    AuthType Basic
    AuthName "Subversion Repository"
    AuthUserFile /etc/apache2/projects/users

    AuthzSVNAccessFile /etc/apache2/projects/access
</Location>

#
#   Access to Trac
#

<Location /projects>
    SetHandler mod_python
    PythonHandler trac.web.modpython_frontend
    PythonOption TracEnvParentDir /var/lib/trac
    #PythonDebug on
    ExpiresActive On
    ExpiresDefault A10
</Location>

<LocationMatch /projects/[^/]+/login>
    AuthType Basic
    AuthName Trac
    AuthUserFile /etc/apache2/projects/users
    Require valid-user
</LocationMatch>

<LocationMatch /projects/[^/]+/chrome>
    Order allow,deny
    Allow from all
    ExpiresDefault "now plus 12 hours"
</LocationMatch>

The last part is a bit of a trick. Naturally it is possible to have Apache serve the static files directly, but this approach is nearly as efficient, and a lot less trouble. Since I am building Trac checked out from Subversion (the 0.11dev trunk), the path to the static files changes with each update and build. With this approach static files are served through the python code - which is less efficient - but this only happens once. The “Expires:” header allows the browser to use the local cached static files on subsequent requests - which reduces server load and improves response times.