Setting Up Trac on CentOS
Paul Heinlein
First published on March 23, 2006
Last updated on October 3, 2006
Contents
Introduction
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.
Local conventions
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.
System Modifications
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.
System Packages
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
SELinux Policies
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
Apache Configuration
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.
# snip lead-in stuff for brevity
# 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>
Adding a Trac
Instantiating Trac and Subversion
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
Configuring trac.ini
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
Authorization settings
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
Role-based access for Trac wiki
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.
Applying the patch
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/*
RBAC configuration
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.