Version 12 (modified by 9 years ago) ( diff ) | ,
---|
Running Trac with Gunicorn
Gunicorn (Green Unicorn) is a Python WSGI HTTP Server for UNIX. It is 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, to not have to install Gunicorn in a system wide fashion.
- Write your wsgi file
Gunicorn is WSGI compliant, so we need a simple Python script tracwsgi.py
that functions 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 to 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
In your web browser go to http://localhost:8000 and it should work. How it works: Gunicorn is looking for a method called "application" in the tracwsgi.py file.
- Configure Nginx
Now we will make it work with Nginx, which will redirect Trac 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 requests to a UNIX socket. This can either be a simple ip:port combination or multiple instances of Gunicorn. Take a look in the Nginx documentation.
To add a basic or digest authentication, you will have to provide a file as in the example above, created using the 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 is passed, you have to modify 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)
Note: If you are using digest authentication, you must create the authentication handler outside of the application def, otherwise the DigestAuthentication object won't retain state between requests.
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 DigestAuthentication digest_auth = DigestAuthentication("/etc/nginx/conf/users.htdigest", "realm") def application(environ, start_application): auth = {"*" : digest_auth} wsgi_app = AuthenticationMiddleware(dispatch_request, auth) return wsgi_app(environ, start_application)