How to install and configure Trac on CentOS 4.
Table of Contents
After a fairly drawn-out process of identifying which wiki software to deploy at work, we finally settled on Trac, which in addition to a wiki provides a bunch of project-management tools: trouble tickets, milestones, and strong ties to the Subversion revision-control system.
The system hosting Trac is running CentOS 4, a freely redistributable rebuild of Red Hat Enterprise Linux 4. The trouble is that CentOS doesn’t ship with Trac, and our our system setup and implementation requirements conspired to make Trac’s installation a somewhat involved process. This document tries to spell out all the special instructions someone would have to follow to re-implement our Trac setup.
Before launching into the gory details of installing and configuring Trac and Subversion on our wiki server, it’s worth noting our local conventions:
We expected to host multiple Trac instances. One instance would be the default, primus inter pares, but all instances would live at the same level in the filesystem.
The /srv
directory hosts both the Subversion repositories (/srv/svn) and Trac instances
(/srv/trac).
Apache manages all access to Subversion repositories on the wiki server.
Our wiki server, like all Red Hat-based systems, manages most software with rpm, the Red Hat package manager. The system’s security constraints are partly governed by SELinux, which is running what Red Hat calls a targeted policy. Certain applications, Apache among them, are governed by fairly strict and comprehensive security policies. All three of these pieces—package management, SELinux, and Apache—needed modification in our setup.
A few Apache- and Python-related packages, along with packages on which they depend, must be installed from the base CentOS distribution for Trac to function: httpd, mod_dav_svn, mod_python, and subversion.
The base CentOS distibution doesn't include Trac or the ClearSilver template library on which it depends. Rather than building those packages in house, I used pre-built packages from Dag Wieers’ repository.
Somewhat later, after Trac was up and running, I discovered that its reStructuredText capabilities required python-docutils, a collection of Python modules not included with CentOS. Dag’s repository didn’t have a package for it either, so I fetched it instead from Karanbir Singh’s repository.
CentOS uses yum to handle dependency checking and remote installation of packages, so using packages from the other repositories was a simple matter of expanding the yum configuration on the host system:
[dag] name=Dag RPM Repository for Red Hat Enterprise Linux baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag gpgcheck=1 enabled=0 includepkgs=clearsilver python-clearsilver trac [kbs-CentOS-Extras] name=CentOS.Karan.Org-EL$releasever - Stable gpgcheck=1 gpgkey=http://centos.karan.org/RPM-GPG-KEY-karan.org.txt enabled=0 baseurl=http://centos.karan.org/el$releasever/extras/stable/$basearch/RPMS/ includepkgs=python-docutils python-imaging
Please note that the enabled directives in both third-party repository definitions is set to
0 (false). This allows yum to work automatically from the official CentOS repository without
hitting any snags from the other repositories. To get updates from dag and/or pyvault, use yum’s --enablerepo option:
yum --enablerepo=dag --enablerepo=kbs-CentOS-Extras update
In Red Hat’s targeted SELinux policies, the Apache web server can only read files assigned a security context type of
httpd_sys_content_t. The standard context for a web-readable directory can be seen in a listing
of /var/www/html on Red Hat systems:
$ stat -Z -c %C /var/www/html system_u:object_r:httpd_sys_content_t
To get Trac to work in an SELinux-enabled environment, therefore, all web content needs to be typed as httpd_sys_content_t. Retyping is done via the chcon utility. Given the local filesystem setup, the retyping took a single invocation of chcon:
chcon -R \ -u system_u -r object_r -t httpd_sys_content_t \ /srv/svn /srv/trac
The security profile of our Trac site wasn’t terribly stringent, so there was no need to establish an SSL
infrastructure. On the other hand, HTTP Basic authentication is terribly weak, so authentication for Trac access is
provided by the HTTP digest access scheme. Digest
authentication poses one difficulty: it cannot currently be used in conjunction with LDAP, PAM, /etc/passwd, or any other system-authentication scheme. The digest password database is completely
divorced from system accounts.
Trac is a fairly hefty process, so it is typically run under FastCGI or mod_python rather than plain CGI. Since CentOS
includes mod_python in its standard Apache package, that’s the acceleration method we chose to employ. The Apache
configuration file, /etc/httpd/conf/httpd.conf, needs to load the Python module at start
time. It also needs the subversion and DAV modules.
As mentioned above, all Trac instances live in /srv/trac and all Subversion repositories
live in /srv/svn. Apache rewards such simplicity by providing directives that understand
parent paths for both applications. Interestingly, the Location of the Subversion directory
root must not be specified via an Alias or a symlink
from the DocumentRoot; it’s a completely manufactured URI, managed by the Subversion/DAV
modules.
...
# load relevent modules
LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
LoadModule python_module modules/mod_python.so
...
<VirtualHost *:80>
...
### trac
Alias /trac/ "/srv/trac/"
<Directory "/srv/trac">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
# mod_python speeds things up considerably
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir "/srv/trac"
PythonOption TracUriRoot "/trac"
# authentication
AuthType Digest
AuthName "wiki-server"
AuthDigestDomain /trac
AuthDigestFile "/etc/httpd/conf/digestpw"
Require valid-user
# authorization is handled internally by trac
</Directory>
### subversion
<Location "/svn">
DAV svn
SVNParentPath /srv/svn
Order allow,deny
Allow from all
# authentication
AuthType Digest
AuthName "wiki-server"
AuthDigestDomain /svn
AuthDigestFile "/etc/httpd/conf/digestpw"
Require valid-user
# authorization
AuthzSVNAccessFile "/etc/httpd/conf/svn-auth.ini"
</Location>
</VirtualHost>
The process for adding a new Trac instance requires several steps. The easiest way to list them is in the language of the Unix shell:
### subversion
# create the repo; use the filesystem backend
svnadmin create /srv/svn/projectname --fs-type fsfs
# give Apache user ownership
chown -R apache /srv/svn/projectname
# tell everyone to go away
chmod -R go-rwx /srv/svn/projectname
# tell SELinux this is valid web content
chcon -R -u system_u -t httpd_sys_content_t /srv/svn/projectname
### trac
# create the instance
trac-admin /srv/trac/projectname initenv
# assign group ownership to Apache
chgrp -R apache /srv/trac/projectname
# give Apache total ownership of a few important directories
chown -R apache /srv/trac/projectname/{attachments,db,log}
# tell everyone else to go away
chmod -R o-rwx /srv/trac/projectname
# tell SELinux this is valid web content
chcon -R -u system_u -t httpd_sys_content_t /srv/trac/projectname
After instantiating the new Trac, its trac.ini configuration file needs to be tweaked
according to local conventions and project needs. Most of the default settings are acceptable, though we always try to use
UTF-8 charsets whenever possible. (UTF-8 is also the default charset in the stock CentOS Apache configuration.)
[trac] default_charset = UTF-8
Apache handles general user authentication (agreeing that you are who you say you are), but Trac and Subversion will
also try to authorize your ability to do different tasks: read, write, commit, delete, etc. Trac provides a much wider
range of permissions than Subversion, and it requires some thought to figure out who can do what. Each application uses a
different tool for configurating authorization. Trac uses the trac-admin
command-line tool. Subversion relies on a text file (specified in the sample Apache configuration above as /etc/httpd/conf/svn-auth.ini).
In general, the configuration process consists of three steps: identifying users and privileges, using trac-admin to alter basic Trac permissions, and editing svn-auth.ini to specify Subversion privileges.
The first step is to identify users who will administer this Trac/Subversion instance, any non-admin users who have some elevated privileges, and the base privileges for everyone else. The TracPermissions help page contains a list of the various settings that can be tweaked. You'll also want to decide if you want to apply special controls to any areas of your Subversion repository.
An important question is the status of anonymous users. On a corporate intranet, we don’t have to worry too much about spambots and malicious users. On the wider Internet, however, you’ll have to decide if anonymous users should be able to post content.
It’s possible, for example, to use trac-admin to remove all write
privileges for anonymous users, add TRAC_ADMIN privileges for administrators, add any other
elevated privileges, and tweak base privileges for all other authenticated users:
# remove write privileges for anonymous visitors trac-admin /srv/trac/projectname permission remove anonymous \ TICKET_CREATE TICKET_MODIFY WIKI_CREATE WIKI_MODIFY for n in adminuser1 adminuser2; do trac-admin /srv/trac/projectname permission add $n TRAC_ADMIN done for n in projectuserA projectuserB projectuserC; do trac-admin /srv/trac/projectname permission add $n WIKI_DELETE done trac-admin /srv/trac/projectname permission add authenticated \ BROWSER_VIEW CHANGESET_VIEW FILE_VIEW LOG_VIEW MILESTONE_VIEW \ REPORT_SQL_VIEW REPORT_VIEW ROADMAP_VIEW SEARCH_VIEW \ TICKET_CREATE TICKET_MODIFY TICKET_VIEW TIMELINE_VIEW \ WIKI_CREATE WIKI_MODIFY WIKI_VIEW
Note that the default permissions don’t allow people to delete anything, since deletion is a non-reversible action in Trac.
Finally, edit /etc/httpd/conf/svn-auth.ini (or whatever you choose to call it) to specify
Subversion permissions. This file uses the syntax for Subversion's per-directory access control. Optionally, you
might also want to create groups of users to simplify things a bit.
[groups] projectadmins = adminuser1, adminuser2 othercoolfolks = projectuserA, projectuserB, projectuserC # repository (r = read, w = write, or none) [projectname:/] @projectadmins = rw @othercoolfolks = rw * = r [projectname:/admin-only/] @projectadmins = rw @othercoolfolks = r * = none
If all those special instructions aren’t enough, our local Trac installation also makes use of a third-party patch that provides role-based access control (RBAC) over specific sections of wiki content.
In general, it’s worth noting that the RBAC patch is fairly complex. The configuration outline provided below presumes that you’ve read the its documentation.
After applying the patch, the updated web_ui.py and rbac.py
files need to be compiled and have their SELinux contexts reset:
python -c 'from trac.wiki import web_ui, rbac' chcon -u system_u -r object_r -t lib_t \ /usr/lib/python2.3/site-packages/trac/wiki/*
The RBAC patch requires some mandatory additions to trac.ini.
[wiki] authz_svn_module_name = projectname-wiki authorization_mode = require_all authz_file = /etc/httpd/conf/svn-auth.ini
You can set authz_svn_module_name to just about any abritrary string. In our setup, we put
wiki authorization stuff into the Subversion authorization file, so we make sure Subversion and the wiki have different
namespaces.
There’s little reason for us to set authorization_mode to anything but require_all, but your needs may require otherwise.
As mentioned, we point authz_file at Subversion’s configuration file. For us, it cuts down
on overhead; your mileage may vary. Here’s what an expanded configuration might look like.
[groups] projectadmins = adminuser1, adminuser2 othercoolfolks = projectuserA, projectuserB, projectuserC ### repository (r = read, w = write, or none) [projectname:/] @projectadmins = rw @othercoolfolks = rw * = r [projectname:/admin-only/] @projectadmins = rw @othercoolfolks = r * = none ### wiki (a = admin, r = read, w = write, ### c = create, d = delete, or none) [projectname-wiki:/] @projectadmins = a @othercoolfolks = rwcd * = rw [projectname-wiki:/PrivateStuff/] @projectadmins = a @othercoolfolks = rw * = none
The RBAC patch is subtractive only. It can only limit permissions granted via
trac-admin; it cannot add them. In this example, for instance, the
* = rw setting for the wiki doesn’t allow anonymous users write access, since they were denied
that by the earlier trac-admin invocations. On the other hand the settings
for wiki pages beginning with /PrivateStuff/ will prohibit users in the othercoolfolks group
from creating or deleting pages in that tree and will prohibit all other users, whether anonymous or authenticated, from
reading them.
This article is licensed under a Creative Commons License.