I’m currently investigating ways to replace Apache httpd with nginx on srcbox.net.
One of the services that runs on the srcbox.net is Trac for hosting a wiki-based website and bug tracking for software projects. Because I’m already using Phusion Passenger for hosting Ruby on Rails projects, I decided to also give it a try to host WSGI applications together with Nginx.
Please note that this post is quite similar to the one written by Graham Edgecombe about the same subject. I found a few things missing and notable so I decided to do my own little writeup on what I had to do to get things working.
As the actual Trac setup is already present on my server and I just wanted to replicate a similar setup in my testing VM, I setup Trac like this:
- Installed package
trac, I used version 0.12.x which is available via Debian Backports
- Added a system user that owns all trac project files and is used to run the WSGI webserver processes: adduser –system –home /var/lib/trac –group –disabled-password –disabled-login trac
- Initialized a trac environment below trac home: trac-admin /var/lib/trac/project initenv
- Deployed the webserver files using: trac-admin /var/lib/trac/project deploy /var/www/trac/
- Added symlinks to make Phusion Passenger accept Trac as a WSGI application: ln -s /var/www/trac/htdocs /var/www/trac/public ln -s /var/www/trac/cgi-bin/trac.wsgi /var/www/trac/passenger_wsgi.py
Nginx installation is quite a bit of work if you’re used to a single
aptitude install package, all features/modules have to be enabled/added at build-time which means rebuilding Nginx if you want to use Phusion Passenger. Because I plan to move authentication to a central place soon I also added Nginx HTTP Auth PAM to the mix. Furthermore I’m also tinkering with the idea to give owncloud a spin so WebDAV support is probably helpful too.
The installation basically went like this (rough steps, this is not a place for step-by-step tutorials):
- Downloaded latest stable Nginx release
- Downloaded latest ngx_http_auth_pam_module release
- Unpacked both in a convenient place
- Installed Phusion Passenger via rubygems (I used ruby and gem from
ruby1.9.1in Debian Squeeze)
2. No: I want to customize my Nginx installation.
- Told the installer where to find unpacked Nginx sources
- Added additional configure arguments. For Auth PAM and optionally needed WebDAV support I used: –add-module=/path/to/unpacked/ngx_http_auth_pam_module –with-http_dav_module
- Grabbed an Espresso until the build was finished (didn’t really take long)
On Debian it’s probably helpful to install a fake webserver package to satisfy dependencies for other packages that depend on
http-server. I used equivs to generate myself an nginx-dummy package.
For starting up Nginx I simply grabbed the init-script from the Debian source package of nginx, , put it into
/etc/init.d/, adapted the paths to my Nginx install in
/opt/nginx and installed it in the default runlevels using
Adding a virtual host to Nginx that serves Ruby on Rails or a WSGI application is usually very easy, for Trac however a tiny bit more care had to be taken…
Pitfall 1: HTTP Auth
With Trac there’s one catch: HTTP Authentication. It took me quite some time to find out why HTTP-Auth worked fine according to the Nginx
access.log but Trac still thought I wasn’t logged in: Nginx needs to forward the user name to the WSGI application. For Phusion Passenger this can be done using the following line: passenger_set_cgi_param REMOTE_USER $remote_user;
Pitfall 2: Location Blocks
Nginx uses location blocks for different behavior depending on the url. For Trac the
/login path should trigger HTTP authentication. Together with Phusion Passenger all I got after successful login however was a simple “404 Not Found” page.
It turned out that for location blocks one has to enable Phusion Passenger again, a prior
passenger_enabled on; line in the parent block does not apply to the inner location block.
Final Nginx Config
The complete host configuration for my test setup that contains all needed things to avoid the above pitfalls looks like this:
This setup is probably still far from complete. Most notable things that I did not setup or test yet include:
- Paths for a manual Nginx install do not obey the FHS at all, logs and temporary files end up on the wrong partition which is a bad idea security wise.
- Log rotation is missing. I can probably grab parts from the Debian Nginx package again.
- Serve multiple projects/environments with the above webserver setup
- Replace the rather ugly HTTP Authentication with Trac Account Manager plugin
- Use TLS and enforce login to happen encrypted only
Of course Trac is by far not the only web-application, I’m probably going to document a few other things I have installed as part of my new Nginx test installation :)