Hosting WordPress on a Nginx + uWSGI + Django Site

August 14, 2011 at 6:45 pm
filed under Programming
Tagged , , ,

Nginx and uWSGI provide a very nice system for efficiently hosting Django applications. Adding a WordPress blog to the mix is not difficult, but it requires some slightly non-obvious (though still straight-forward) Nginx configuration.

To set everything up, lets first think about the site structure and what Nginx actually needs to do. At worldofsam.com, everything is handled by a Django application except for /blog , which is handled by WordPress. Therefore, Nginx needs to do the following:

  1. If the URI is below /media, serve up a static file or 404
  2. If the URI is below /blog and maps to a real, non-PHP file, serve it up directly
  3. If the URI is below /blog and maps to a PHP file, pass it on to FastCGI
  4. If the URI is below /blog, but doesn’t map to a real file, then pass it onto an appropriate index.php WordPress handler
  5. Otherwise, pass the request on to uWSGI and Django

The server is organised so that the Django application and WordPress installation reside in the same directory:

/www/
    wsgi-handlers/ (uWSGI is configured to look here for WSGI handler scripts)
        worldofsam.py
    worldofsam.com/
        worldofsam_site/ (contains the Django site)
            site_media/
        blog/ (contains the WordPress installation)

And Nginx is configured like so:

server {
    listen 80;
    server_name worldofsam.com;
 
    root /www/worldofsam.com/worldofsam_site/site_media;
 
    location / {
        uwsgi_pass unix:/var/tmp/uwsgi.sock;
        include uwsgi_params;
        uwsgi_param UWSGI_SCRIPT worldofsam;
    }
 
    location /media {
        alias /www/worldofsam.com/worldofsam_site/site_media;
    }
 
    location /blog {
        root /www/worldofsam.com;
        index index.php /blog/index.php;
        try_files $uri $uri/ /blog/index.php?q=$uri?$args;
    }
 
    location ~ /blog/.+\.php$ {
        root /www/worldofsam.com;
        include fastcgi.conf;
        fastcgi_pass localhost:8820;
    }
}

The most tightly binding block is the location ~ /blog/.+\.php$ block, which will pass any request for a PHP file below /blog on to FastCGI (satisfying requirement #3 from earlier). The document root is set one directory above the WordPress installation, since any URI matched by this block will already contain the /blog path component (and so will the FCGI script name). WordPress must therefore be installed in a directory with the same name as the directory it appears under on the site.

The location /blog block sets the root to /www/worldofsam.com for the same reason, and uses an index directive to process the request using a file named index.php if the URI is for a directory, or WordPress’s primary index.php file if none exists.

The try_files directive then tries to handle the request as a static file, as a directory (which should contain an index.php file) or by passing the URI on to WordPress’s primary index.php handler if the first two fail. This last part is required for pretty permalinks to work.

That satisfies requirements #2 and #4 from earlier, which just leaves us with #1 and #5. Satisfying requirement #1 is easy – just use an alias directive like shown in the location /media block, and requirement #5 is satisfied by the location / block which passes the request on to uWSGI.

Assuming you have correctly configured uWSGI, FastCGI and WordPress, you should now be able to load yoursite.com/blog and see WordPress come up.

no comments

RSS / trackback

respond