How to install nginx over Pow in OS X

January 20, 2012 ipfw nginx OS X Pow Rack Ruby on Rails

Pow is a nice starter level server which is useful as long as all you want is develop Rack apps. But what if you need to run a PHP app on the same development machine? Or a Node.js app? Then you’re out of luck (or, directed to some arcane techniques to run them inside Rack, which is just backwards in my opinion).

Anyways, here’s how. You install nginx and let it handle the routing.

Switch off pow port forwarding

If you have pow installed, it holds the 80 port for itself. To check that, you can run

sudo ipfw list

and look for

fwd 127.0.0.1,20559 tcp from any to me dst-port 80

So, Pow runs on port 20559 and proxies all requests from port 80 to port 20559 via ipfw, to be able to run under a regular user.

Since Pow (as of version 0.3.2) does not support disabling this forwarding completely, we will reassign it to a completely arbitrary port. Run

echo "export POW_DST_PORT=44444" >>~/.powconfig

Now, to pick up this change, reinstall Pow (this isn’t a big deal)

curl get.pow.cx | sh
launchctl unload /Library/LaunchDaemons/cx.pow.firewall.plist
launchctl load /Library/LaunchDaemons/cx.pow.firewall.plist

Run sudo ipfw list again and verify that the port has changed.

Install nginx

If you haven’t done it yet, install nginx. I suggest using Homebrew, but any installation will do as long as you can locate the binary and the config file.

brew install nginx

Now you need to make it a daemon (or not, if you’re OK with starting it manually). As userland daemons can’t listen on the HTTP 80 port, you have to either a) proxy requests from the 80 port to the nginx port with ipfw, as pow does, or b) install it system-wide.

I chose the latter approach.

First off, create /Library/LaunchDaemons/nginx.plist:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>nginx</string>
    <key>Program</key>
    <string>/usr/local/sbin/nginx</string>
    <key>KeepAlive</key>
    <true/>
    <key>NetworkState</key>
    <true/>
    <key>LaunchOnlyOnce</key>
    <true/>
  </dict>
</plist>

(replace /usr/local/sbin/nginx with the path to your nginx binary)

Now, set up forwarding from Nginx to Pow; this should be the last server clause in the configuration file (/usr/local/etc/nginx/nginx.conf or other):

server {
  listen  80;
  server_name *.dev *.local;
  location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_redirect off;
    proxy_pass http://localhost:20559;
  }
}

Finally, register nginx as a daemon.

sudo chown root /Library/LaunchDaemons/nginx.plist
sudo launchctl load /Library/LaunchDaemons/nginx.plist

…and done!

Check that http://localhost displays the Nginx welcome page, not the Pow welcome page.

Rack requests are still handled by Pow, as well as the DNS redirection, and you’re free to bind whatever you want (literally, whatever) to Nginx.

Buy Me a Coffee at ko-fi.com