Trac on Red Hat Enterprise Linux 5
Installing Trac software and dependencies
Installing Trac on Red Hat Enterprise Linux 5 is relatively easy thanks to RPMforge packages from Dag and Dries. Visit http://dag.wieers.com/rpm/FAQ.php#B for details on how to configure your server to be able to access RPMforge.
Once you have your server configured to use the RPMforge package repository, installing Trac is accomplished by running:
yum install trac
Once the software is installed, you will need to configure it as documented below to get it up and going.
Configuration overview
This guide will result in the following configuration:
- HTTP requests will be handled by Apache HTTP Server ("Apache"):
- Trac will be run within its own separate and limited user account:
- No Trac code will be executed inside Apache processes;
- Trac data will be stored within a SQLite database;
- All data files are owned/readable/writable only by the dedicated Trac user account;
- HTTP requests will be proxied from Apache to Trac via mod_proxy_ajp.
The rationale for this configuration is:
- We can take advantage of Apache's features such as SSL, and advanced authentication (eg LDAP);
- No extra code or modules that could effect the security or stability of the Apache server are introduced;
- Individual instances of Trac are isolated and can have their resource usage easily measured;
- Multiple versions of Trac could be run if so desired.
If you are dedicating an entire machine to Trac and don't require such high levels of isolation, you may wish to simply embed Trac in Apache. See TracOnRHEL for details. It is a much simpler procedure.
You may also want to simply just run the trac standalone daemon on a high port.
It is assumed that Subversion is already installed/configured and in a working state.
In the examples below, the end goal will to have a trac environment setup for PROJECT_NAME available at:
https:trac.example.org/PROJECT_PATH
Creating the dedicated Trac account
Create a user account for Trac:
$ su - # useradd -d /home/trac -c 'Trac server user' trac
Be sure to add the trac user to any groups necessary for access to your subversion repository. You may also need to add it to the group that owns the Apache password file so that it can authenticate users.
Create a new project environment
# su - trac $ mkdir -p -m 0700 $HOME/projects $ trac-admin $HOME/projects/PROJECT_NAME initenv
See TracInstall for generic information.
Web server gateway
In order to connect Apache to Trac we will make use of http://trac.saddi.com/flup which is an AJP to WSGI gateway. Download the latest prepackaged tarball version of flup into the trac account and install:
$ tar zxf flup-0.5.tar.gz $ cd flup-0.5 $ mkdir -p -m 0700 $HOME/lib/python $ PYTHONPATH=$HOME/lib/python python setup.py install --home=$HOME
Now we need to create a simple gateway:
$ mkdir -m 0700 $HOME/bin
then create the file $HOME/bin/ajp_to_wsgi_gateway with the following contents:
#! /usr/bin/python # # # AJP to WSGI gateway to run Trac. import os, sys # System path configuration. Nasty hack below. sys.path.append(os.environ['HOME'] + '/lib/python/setuptools-0.6c3-py2.4.egg') sys.path.append(os.environ['HOME'] + '/lib/python/flup-0.5-py2.4.egg') def usage() : print """Usage: ajp_to_wsgi_gateway PATH_TO_TRAC_ENV URL_PREFIX PORT""" sys.exit(1) if __name__ == '__main__': if len(sys.argv) != 4 : usage() else : path = sys.argv[1] prefix = sys.argv[2] port = int(sys.argv[3]) # WSGI application configuration. os.environ['TRAC_ENV'] = path os.environ['PYTHON_EGG_CACHE'] = path + '/eggs' import trac.web.main application = trac.web.main.dispatch_request # AJP to WSGI gateway. import logging from flup.server.ajp import WSGIServer ret = WSGIServer(application, bindAddress=('localhost', port), scriptName=prefix, loggingLevel=logging.ERROR, debug=False ).run() sys.exit(ret and 42 or 0)
You may need to modify the script above to fixup the system path information. Set the permissions on the script:
chmod 700 $HOME/bin/ajp_to_wsgi_gateway
Create $HOME/bin/trac_server_wrapper with the following contents:
#! /bin/bash # # Wrapper script to start a trac server for multiple environments. export PYTHONPATH=$HOME/lib/python trac_project() { local trac_env=$1 local path_prefix=$2 local port=$3 local status=42 while test $status -eq 42; do $HOME/bin/ajp_to_wsgi_gateway "$trac_env" "$path_prefix" $port status=$? done & } # Individul project servers. trac_project $HOME/projects/PROJECT_NAME /PROJECT_PATH SERVER_PORT
Edit the script to replace PROJECT_NAME, PROJECT_PATH, and SERVER_PORT as appropriate. PROJECT_PATH must not have a '/' after it and does not include the protocol or hostname.
Set the permissions on the script:
chmod 700 $HOME/bin/trac_server_wrapper
Set the server script to start on system boot:
$ cat <<EOF > cron.fragment @reboot $HOME/bin/trac_server_wrapper EOF $ crontab cron.fragment $ rm cron.fragment
Now start the gateway:
trac_server_wrapper
Alternative web server interface
At the time of writing, the above scripts appear to have problems with escape sequences in URLs. For example, this will mean you can't put spaces in milestone names, and you won't be able to browse source files whose names contain spaces. There is however an alternative way of presenting an AJP interface to Apache which can be configured to avoid this problem, and yet retain the advantages of running Trac in its own user account.
The way to do this is to run tracd
with --protocol=ajp
and the --unquote
switch that was added in trac 0.11.4 (if you're running an earlier version, refer to this patch). For example:
tracd --auth="*",/var/www/passwords/passwd,MyRealm --port=SERVER_PORT --hostname=localhost --protocol=ajp --unquote --env-parent-dir=$HOME/projects --base-path=/PROJECT_PATH --daemonize --pidfile=$HOME/trac.pid --umask=63
but all one line. It's probably easiest to put this in a shell script somewhere. You'll need to add this to the trac
user's crontab to be executed at each reboot.
Common web content
Now we copy the common icons, stylesheets, etc that Apache will server directly into our hosting account:
$ mkdir -m 0701 $HOME/public_html $ cp -a /usr/share/trac/htdocs/* $HOME/public_html/trac $ chmod 701 $HOME
Edit $HOME/projects/PROJECT_NAME/conf/trac.ini and adust the following values:
- In the [header_logo] section set src to /trac/trac_banner.png
- In the [project] section set icon to /trac/trac.ico
- In the [trac] section set htdocs_location to https:trac.example.org/trac
Start trac servers
Start trac by running:
$ trac_server_wrapper
SELinux configuration
Apache will need network access in order to communicate to the trac daemon. As root run:
# setsebool httpd_can_network_connect on
For Apache to be able to access the common trac files, the will need to be correctly labeled. As root run:
# fixfiles restore /home/trac
Apache configuration
Create your SSL certificate for trac.example.org. As root:
# cd /etc/pki/tls/certs # make trac.example.org.crt
Make sure the mod_ssl' package is installed.
Create an Apache virtual host in /etc/httpd/conf/httpd.conf (or an included file) with contents like:
<VirtualHost YOUR_IP_ADDRESS:443> ServerName trac.example.org:443 ServerAdmin support@example.org DocumentRoot /home/trac/public_html CustomLog logs/trac.example.org_log combined ErrorLog logs/trac_error_log <IfModule mod_ssl.c> SSLEngine on SSLCertificateFile /etc/pki/tls/certs/trac.example.org.crt SSLCertificateKeyFile /etc/pki/tls/private/trac.example.org_key #SSLCACertificateFile /etc/pki/tls/certs/A_CA_CERT.crt </IfModule> # Security restrictions. <Location /> # Require password authentication via LDAP. #AuthType basic #AuthName "Trac" #AuthBasicProvider ldap #AuthLDAPURL ldap://localhost/dc=example,dc=org #AuthLDAPGroupAttribute memberUID #AuthLDAPGroupAttributeIsDN off #require ldap-group cn=devel,ou=Groups,dc=example,dc=org #Order Allow,Deny #Allow from staff.example.org </Location> # Trac runs as a daemon inside the 'trac' account. # It is written in Python, however there is a # AJP <-> WSGI gateway that handles the requests on # a per project basis. Redirect /PROJECT_PATH https://trac.example.org/PROJECT_PATH/ ProxyPass /PROJECT_PATH/ ajp://localhost:SERVER_PORT/PROJECT_PATH/ ProxyPassReverse /PROJECT_PATH/ ajp://localhost:SERVER_PORT/PROJECT_PATH/ </VirtualHost>
Check the syntax via service httpd configtest and restart via service httpd restart.
Everything should now work!
Troubleshooting
The above is quite complicated and easy to make a mistake with. Things to check:
- Check the apache server error log and the trac user error log;
- Check with ps xfwww that ajp_to_wsgi_gateway is running;
- Check with netstat -tunlp that the gateway is listening on the correct port;
- Modify ajp_to_wsgi_gateway and set debug to True and loggingLevel to logging.DEBUG to see the requests hit the gateway;
- Modify $HOME/projects/PROJECT_NAME/conf/trac.ini and set log_type to stderr to get error messages from trac itself.