Run Nginx and Pow on your Mac
Pow is a dead-simple Rack server for OS X. Easy setup, easy restarting, easy development.
Nginx is a lightweight HTTP proxy server. Easy on resources, and great at what it does.
Suppose you want to run Nginx to serve some static assets off your development machine, for demonstration purposes. But you also want to use Pow for your Rails and Rack work. If you have already tried to run both, you may have noticed that Pow takes port 80 using a ipfw rule, and no requests make it to Nginx. There’s a fairly easy solution.
What we are looking to have is:
http://localhost/
to Nginxhttp://myapp.dev/
to Powhttp://dev.example.com/
to development machine to Nginxhttp://myapp.dev.example.com/
to development machine to Pow
Those last two are only if you want external access to these services. They will require you to have your DNS setup properly to redirect dev.example.com
and *.dev.example.com
to your development machine (substituting your own domain of course).
From the Top
I’m going to assume you’re running Snow Leopard (10.6) or newer — Pow doesn’t run on older OS X versions. You should also have Nginx and Pow installed. I’m using Pow 0.3.2 and Nginx 1.0.14 on Mac OS 10.7.3.
Pow uses a resolver and an ipfw rule to redirect requests from *.dev
to your Rack app. Take a look:
$ cat /etc/resolver/dev
# Lovingly generated by Pow
nameserver 127.0.0.1
port 20560
$ sudo ipfw list
00100 0 0 fwd 127.0.0.1,20559 tcp from any to me dst-port 80
65535 allow ip from any to any
That first rule, 00100
, redirects any requests to port 80 to Pow at 127.0.0.1:20559
. We can’t just remove the rule, as Pow will re-add it with a Launch Daemon on startup. And we can’t just remove the Launch Daemon, as pow needs it to run. (I tried). Instead, let’s let Pow take over a port we don’t care about.
$ echo "export POW_DST_PORT=19999" >> ~/.powconfig
And reinstall pow to pick up the new configuration:
$ curl get.pow.cx | sh
With that gone, if you try to load http://localhost/
you should get Nginx’s welcome page (if it is running)! One caveat: we can’t access our Rack servers from the http://*.dev/
domain anymore. This is where Nginx’s config comes into play.
Step into Nginx
Open Nginx’s config (/usr/local/etc/nginx/nginx.conf
if you’re using Homebrew) in your favourite editor, and we will add some new server blocks.
Look for the existing server block, and adjust it’s server_name
to include your external address.
server {
listen 80;
server_name localhost dev.example.com;
#charset koi8-r;
...
If you save it and reload Nginx now (sudo nginx -s reload
), you should see the Nginx welcome page at your domain. Nice!
Back to the conf file, add two new server blocks above the existing server directive.
server {
listen 80;
server_name *.dev;
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;
}
}
server {
listen 80;
server_name myapp.dev.example.com;
location / {
proxy_set_header Host "myapp.dev"; # Host for Pow
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;
}
}
server {
listen 80;
server_name localhost dev.example.com;
...
Save and reload Nginx. localhost now goes to Nginx. myapp.dev now goes to Pow. And externally, dev.example.com
goes to Nginx, and myapp.dev.example.com
goes to Pow.