Running TurboGears behind Nginx via WSGI

Nginx is a fast and light HTTP server, reverse proxy, load balancer (and more).

It’s possible to get TurboGears set up behind a Nginx server so that it proxies requests to a uWSGI server that directly communicates with your TurboGears application without resorting to the CherryPy server.

Note that the following documentation assumes you are using TurboGears 1.5.1 and CherryPy 3.2 or newer versions. We also assume that you are deploying on a Linux server, though this setup may be possible on other platforms as well.

Install uWSGI

The best way of deploying Python application with the Nginx web server is by using the uWSGI server. Follow its installation instructions to install the uWSGI server on your system. The easiest way of installing uWSGI is by using the pip command:

pip install uwsgi

You may get an error message telling you to install the libxml2-devel package. In this case, install the required package and try again.

Install the uwsgi NGinx module

For using Nginx as a WSGI gateway, we need the uwsgi Nginx module. Nginx modules must be selected during compile, different from Apache, run time including of modules is not supported. Luckily, however, uwsgi is already included as a standard module in newer versions of Nginx. You can check your Nginx configuration with the following command:

nginx -V

In the configure arguments, you should find the option --http-uwsgi-temp-path, and the option --without-http_uwsgi_module should not be set. Otherwise, refer to the Nginx documentation for installing a recent version with the uwsgi NGinx module.

Create a WSGI script file

To access your application via WSGI, you need to create a WSGI script file. We recommed creating a separate directory for your WSGI script files. This directory must be accessible by Nginx, but should not be located somewhere below the root directory of your static files. A good place would be a sibling directory to an existing cgi-bin directory on your system, or a directory under your TurboGears project directory, but not under the static subdirectory. If you are using a virtual enviroment for your TurboGears project, then a subdirectory of the virtual enviroment directory would also be a good place for the WSGI script file.

In the following we assume your WSGI script file directory is /srv/www/wsgi-scripts. We recommend naming your WSGI script file after your TurboGears application. So if your TurboGears project is called myapp, the WSGI script file would be /srv/www/wsgi-scripts/myapp.wsgi. The content of this file can be as simple as this:

"""WSGI script for myapp"""

from myapp import command

application = command.start()

Configure uWSGI

We recommend using a config file for storing the uWSGI settings. If can be stored as /etc/uwsgi.ini and look like follows:

[uwsgi]
socket = /tmp/uwsgi.socket
wsgi-file = /srv/www/wsgi-scripts/myapp.wsgi
daemonize = /var/log/uwsgi.log

You can find many more options explained in the uWSGI documentation.

The uWSGI server can be run from the command line with

uwsgi --ini /etc/uwsgi.ini

but of course you should better use a start sript in etc/init.d or start uWSGI indirectly via supervisor. For security reasons, the uWSGI server should be run by a user with as little privileges as necessary to run your application. This user must have also the necessary permissions to read the WSGI script file. For security reasons, you should not make the WSGI script file writable or executable, though.

Configure Nginx

The relevant portion of the Nginx configuration can now look as follows:

server {
    listen 80;
    server_name myhost.com;

    charset utf-8;

    access_log /var/log/nginx/myapp.access.log;

    location /myapp {
        include uwsgi_params;
        uwsgi_pass unix:/tmp/uwsgi.socket;
    }
}

The above configuration assumes that you want your application to appear under the URL prefix /myapp/. In this case, you should also set server.webpath = '/myapp' in your TurboGears configuration file. If you want your application to appear with no URL prefix, then replace location /myapp with location / in the configuration above.

The advantage of using Nginx in front of uWSGI is that you can also configure it to serve as a load balancer connecting to more than one uWSGI instance.

Configure TurboGears

In your prod.cfg or default.cfg file that will be loaded when the WSGI script file is starting the application, change the environment setting to ‘embedded’:

environment = 'embedded'

If you want to use the URL prefix /myapp/ for your application, you should also add the following setting:

server.webpath = '/myapp'

Using a virtual environment

If you installed your TurboGears application in a virtual environment (as recommended), you must specify the path to your virtual environment in the virtualenv setting of the /etc/uwsgi.ini file:

virtualenv = /home/myapp/venv

Servig static pages with Nginx

To improve performance even more, you should let Nginx serve the static files directly instead of serving them through the application via the uWSGI server.

A simple solution is to add a symbolic link to the static directory of your TurboGears project somewhere where it can be easily accessed by Nginx, and then add this to your Nginx configuration:

location /myapp/static {
    root /srv/www/htdocs/myapp/static/;
}
location = /myapp/robots.txt {
    root /srv/www/htdocs/myapp/static/;
}
location = /myapp/favicon.ico {
    root /srv/www/htdocs/myapp/static/;
}

Here we assumed again that you want your application to appear under the URL prefix /myapp/. Change the configuration appropriately if you want to use a different prefix or no prefix at all.