January 27, 2013

Trac on CentOS 6.3, Part 2

Recently I had the need to set up a Trac instance on a 64-bit machine running CentOS 6.3. In part 1 I installed some prerequisite software and Trac itself. In part 2, I will be installing Apache as a front end to Trac. In part 3, I will configure Trac to use an Active Directory domain for authentication.

First we need to install Apache. We will be using WSGI within Apache to execute Trac’s python code. We will also need to open the firewall for HTTP traffic. Warning: Don’t mess with your firewall unless you know what you are doing. If your server has a GUI, there are straightforward GUI tools for opening the firewall for HTTP, use those instead of command line configurations below.

yum install httpd mod_wsgi
# Set Apache to start on boot
chkconfig httpd on
# Open HTTP port on firewall
# Figure out the value for line below by using the highest line number
# output from "iptables -t INPUT -L --line-numbers">
iptables --insert INPUT $line \
         --match state \
         --state NEW \
         --protocol tcp \
         --destination-port 80 \
         --source \
         --jump ACCEPT
# Check that the firewall state is as you want it before saving!
iptables -t INPUT -L --line-numbers
# If your firewall is screwed up use "service iptables restart" to restore it
# instead of saving it
service iptables save

Now we will configure Apache with a virtual server for our Trac instance. First, comment out the NameVirtualHost directive in /etc/httpd/conf/httpd.conf. Then create a new file in /etc/httpd/conf.d called myproject.mydomain.tld.conf, where myproject.mydomain.tld is the domain name you want to use for the trac server. (The name of the file isn’t important, except for the .conf sufix, but a good naming scheme will make your life easier.) The contents should like like this:

<VirtualHost *:80>
    DocumentRoot /var/www/myproject.mydomain.tld/html
    ServerName myproject.mydomain.tld

    ErrorLog logs/myproject.mydomain.tld-error_log
    CustomLog logs/myproject.mydomain.tld-access_log common

Then create the root directory:

mkdir -p /var/www/myproject.mydomain.tld/html

This is a good point to make a dummy file in the directory (say index.html) and test the server:

echo '<html><body>Hello!</body></html>' >/var/www/myproject.mydomain.tld/html/index.html
service httpd start
wget http://myproject.mydomain.tld/index.html

At this point we are ready to export scripts and static resources from Trac and set permissions for Apache:

trac-admin /var/trac/myproject deploy /tmp/deploy
mv /tmp/deploy /var/trac/myproject/deploy

chown -R apache:apache /var/trac/myproject

Now we copy in the Trac WSGI script into Apache’s cgilib directory:

cp /var/trac/myproject/deploy/cgi-bin/trac.wsgi /var/www/cgi-bin/myproject.trac.wsgi

Then edit /etc/httpd/conf.d/myproject.mydomain.tld.conf and add the following within the virtual server definition:

    WSGIScriptAlias /trac /var/www/cgi-bin/myproject.trac.wsgi

    <Directory /var/www/cgi-bin>
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all

Now if you restart Apache (service httpd restart) and browse to http://myproject.mydomain.tld/trac/, you will get the following error:

TracError: No Trac environment found at /var/trac/myproject [Errno 13] Permission denied: /var/trac/myproject/VERSION

Now we are getting into some CentOS 6 specific territory. The problem is that CentOS includes SELinux, which adds a much more detailed and configurable security structure on top of the standard Linux security infrastructure inherited from Unix. Fortunately the fix is easy, when you know what to do:

chcon -R -t httpd_sys_content_t /var/trac/myproject
chcon -R -t httpd_sys_script_rw_t /var/trac/myproject
setsebool -P httpd_can_network_connect on

Now you should be able to connect to your Trac instance at http://myproject.mydomain.tld/trac/.

Finally, we can map the static resources we exported.

cp -r /var/trac/myproject/deploy/htdocs /var/www/myproject.mydomain.tld/trac/

Edit /etc/httpd/conf.d/myproject.mydomain.tld.conf adding the following before the WSGIScriptAlias directive:

    Alias /chrome/common /var/www/myproject.mydomain.tld/trac/htdocs/common
    Alias /chrome/site /var/www/myproject.mydomain.tld/trac/htdocs/site

In part 3, I will configure Trac to use an Active Directory instance for authentication.