Running Trac with Gunicorn
Gunicorn (Green Unicorn) is a Python WSGI HTTP Server for UNIX. It's a pre-fork worker model ported from Ruby's Unicorn project. The Gunicorn server is broadly compatible with various web frameworks, simply implemented, light on server resources, and fairly speedy.
- Install gunicorn
Gunicorn is a python project which lives on pypi, so we can use easy_install or pip to install gunicorn :
$> pip install gunicorn
I prefer to use a virtualenv (http://pypi.python.org/pypi/virtualenv), to not have to install gunicorn in a system wide fashion.
- Write your wsgi file
Gunicorn is WSGI compliant, so then We needneeds a simple python script that work as an entry point:
import sys import os sys.stdout = sys.stderr #put here your ENV's Variables # here is an example with multiple instances os.environ['TRAC_ENV_PARENT_DIR'] = '/home/repos/trac/' os.environ['PYTHON_EGG_CACHE'] = '/home/repos/projects/.eggs/' import trac.web.main application = trac.web.main.dispatch_request
Now, we will test it:
$> gunicorn -w2 tracwsgi:application -b 0.0.0.0:8000 2011-03-04 13:21:10 [14900] [INFO] Starting gunicorn 0.12.0 2011-03-04 13:21:10 [14900] [INFO] Listening at: http://127.0.0.1:8000 (14900) 2011-03-04 13:21:10 [14901] [INFO] Booting worker with pid: 14901 2011-03-04 13:21:10 [14902] [INFO] Booting worker with pid: 14902
Now, launch your web browser, and go to http://yourip:8000 and it should work. How it works: gunicorn is looking for a method called "application" in the tracwsgi.py file
- Configure Nginx
So, now we have Gunicorn running, but we will make it works with nginx which will redirect tracs requests to gunicorn:
upstream trac_gunicorn {
server unix:///home/repos/projects/run/trac.sock;
}
server {
listen 80;
server_name trac.example.com;
access_log /var/log/nginx/trac.access.log;
error_log /var/log/nginx/trac.error.log info;
include "/etc/nginx/acl.conf";
location / {
auth_basic "Secure Login";
auth_basic_user_file /etc/nginx/conf/users;
proxy_pass http://trac_gunicorn;
}
location ~ /(.*?)/chrome/site/ {
rewrite /(.*?)/chrome/site/(.*) /$1/htdocs/$2 break;
root /home/repos/trac.enabled;
}
}
Note: Nginx will redirect request to a unix socket. It can be a simple ip:port combination. It can be a multiple instance of gunicorn. Take a look in the nginx documentation : http://wiki.nginx.org/HttpUpstreamModule
To add a basic or digest authentication, you'll have to provide a file as in the example above, created using htpasswd file. To make gunicorn listen on a unix socket, add this option :
gunicorn -w2 -b unix:///home/repos/projects/run/trac.sock tracwsgi:application
Note: It seems the wsgi entry point does not handle the Digest or Basic http authentication. To ensure the authentication middleware are passed, you'll have to hack a little bit the tracwsgi.py :
import sys
import os
sys.stdout = sys.stderr
os.environ['TRAC_ENV_PARENT_DIR'] = '/home/repos/trac.enabled/'
os.environ['PYTHON_EGG_CACHE'] = '/home/repos/projects/.eggs/'
from trac.web.standalone import AuthenticationMiddleware
from trac.web.main import dispatch_request
from trac.web.auth import BasicAuthentication
def application(environ, start_application):
auth = {"*" : BasicAuthentication("/etc/nginx/conf/users", "realm")}
wsgi_app = AuthenticationMiddleware(dispatch_request, auth)
return wsgi_app(environ, start_application)


