Passenger with nginx on Mac OS X

Update: This is a more up-to-date guide here: Passenger with nginx on Mac OS X (2nd edition)

Setting up nginx with Passenger support turns out to be fairly easy.

Start by making sure you have the most recent version of Passenger, then install the nginx module. This will actually install and compile nginx with the Passenger module enabled, which is handy. Choose the recommended/default options when the installer prompts you.

sudo gem update passenger
sudo passenger-install-nginx-module

Then, open up the nginx config file:

mate /opt/nginx/conf/nginx.conf

Add the following line to the top of the file:

daemon off;

This will prevent the “502 Bad Gateway” error you may see otherwise. I’m not sure why this is necessary, but I read about it here, and it seems to do the trick. nginx specifies that this should only be used for development, though.

Next, find the http { block, which should start around line 15 or so. You’ll want to add a server { block within the http { block for each of your Rails/Rack applications, like so:

server {
   listen 80;
   server_name eldorado.local;
   root /Users/trevorturk/Code/eldorado/public;
   passenger_enabled on;
   rails_env development;
}

You’ll need an entry in your hosts file if you don’t already have one. Simply open up the file:

mate /etc/hosts

…and add lines for each of the apps you plan to run, like so:

127.0.0.1 eldorado.local 

Now, we can set up a launchd item, so that nginx will start up automatically after a system reboot. Create a new plist file by opening it up in TextMate:

mate /System/Library/LaunchDaemons/nginx.plist

…and paste the following code in, which was kindly provided for us by this helpful person:

http://gist.github.com/188167

Then, run the following command to load it:

launchctl load /System/Library/LaunchDaemons/nginx.plist

Now, you can reboot your system and make sure it’s all working as expected by visiting http://eldorado.local, or whatever address you’ve configured your application to be on.

I believe this nginx installation will override the existing Apache installation you may have running. This doesn’t bother me, so I opened up my System Preferences -> Sharing prefpane and unchecked the Web Sharing box, so Apache is no longer running. If you have any ideas about how to keep both services running cooperatively, please do let me know.

Update: Here are some additionally configuration options I’m using, which I cobbled together from various sources after Googling for things like “nginx, rails, gzip, expires” and such. Their powers combined, and I seem to have a YSlow-approved setup.

Just above your server { block, around line 40, add the following:

gzip on;
gzip_buffers 16 8k;
gzip_disable "MSIE [1-6].";
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

That should cover gzip well enough.

Then, amend the aforementioned server { block to include some far future expires goodness that takes advantage of the Rails asset_tag helpers:

server {
  listen 80;
  server_name eldorado.local;
  root /Users/trevorturk/Code/eldorado/public;
  passenger_enabled on;
  rails_env development;
  location ~* .(ico|css|js|gif|jp?g|png)(?[0-9]+)?$ {
      expires max;
      break;
  }
}

These two configuartion tweeks are, I believe, the rough equivalent of the technique previously discussed on this blog for Apache.

Of course, any additional suggestions, comments, or insights you may have would be most welcome. I’m new to this whole nginx thing, but I’m enjoying it so far.

Update: Here’s an easy way to reload nginx, if you need to make a change to your conf. Make sure to have the following in your /opt/nginx/conf/nginx.conf file:

pid /var/run/nginx.pid;

Then, you can make an alias for the reload task in your ~/.bash_profile:

alias nr='sudo kill -HUP `cat /var/run/nginx.pid`'

In case you’re interested, you can check out my full nginx.conf file for local development here:

http://gist.github.com/191331

Published by

Trevor Turk

A chess-playing machine of the late 18th century, promoted as an automaton but later proved a hoax.

11 thoughts on “Passenger with nginx on Mac OS X”

  1. The 'daemon off' shouldn't be necessary. We have a production system running on Nginx with 'daemon on'. Do you see any errors in your error_log if 'daemon on' is set?

  2. Oh, after reading the ruby-forum post I think the 'daemon off' is only necessary when you're using it in combination with launchd. launchd probably monitors the process until it exits; if Nginx daemonizes then launchd thinks it exited, and tries to restart it. But the old Nginx was still running in the background so the new one fails to start.

  3. Is there a way to get Passenger/NGINX to reload automatically when a controller or view is changed?

    Passenger/Apache does this fine, but have not had any luck with NGINX. Best I can find is to touch the reload text file, which is a real pain.

  4. Hongli, thanks for the clarification. I wasn't sure why it was needed, but it didn't work without it for me🙂

    jason, I'm not sure. Maybe somebody else will come along and let us both know. I haven't done much development work with nginx, but maybe I'll run into the same problem, too.

  5. Jason, your problem is not caused by Phusion Passenger, but by Rails. As of version 2.2 or something, Rails caches view templates when run in production mode, for increased performance. If you don't want the view templates to be cached then you need to turn off view template caching; there's an option for that somewhere.

  6. ok, so i've loaded nginx successfully and updated conf file, etc. doubled checked my path settings, and when i run sudo nginx i get a command not found error message…

    any thoughts on what i am missing?

  7. You shouldn't put the nginx.plist file into the /System/Library/LaunchDaemons/ directory. It's reserved for Apple's OS-level service stuff.

    Instead put your plists into /Library/LaunchDaemons/

Comments are closed.