I wondered what's happening in pow, so I tried to trace
what it is doing. My conclusion is, how could this be
even more wrong?
Please follow me to see what's happening...
So on it's website, it's telling the users to install it via:
Aside from the point that you should never do this (please
curl get.pow.cx | sh
download the shell script and take a look before running it),
it is basically install.sh, which is trying to download a
tarball for the specific version of pow and untar it,
and run the pow command to install the whole thing.
It would do a number of things. Let's only look at the
important ones, or there would be too much to look at.
So the pow command would pick the system installer,
it would then install a firewall plist, a number of
resolver configs, and a plist for pow itself in its
After that, the installer would load the firewall with sudo,
and start pow via pow plist.
Note that since they are doing this in
/Library/LaunchDaemons, they would be running when
Mac OSX starts.
And what are they doing? There are a number of files
we should be looking at. Let's go through them one by one.
The firewall is probably cx.pow.firewall.plist.eco.
It is trying to forward port 80 to port 20559 by default.
That means, whenever you're hitting http://pow.dev:80 it
would be forwarded to http://127.0.0.1:20559.
Let's look into the DNS resolver, which I believe it's
resolver.eco, which would be installed into
According to Mac's resolver man page, this means only
domains ending with dev (or whatever it's configured) would
use this pow DNS server, listening on 20560 by default.
Lastly, the pow plist itself, which I think is cx.pow.powd.plist.eco,
which is simply trying to launch Node to run pow command.
So by installing pow, it would then install a pow daemon,
which itself is both a DNS server and an HTTP server. We'll
talk about this later. It would also install a special DNS
resolver for domains ending with
.dev, and a firewall rule
for forwarding port
In the end, what does pow really do for serving a request?
Mac would first look at
/etc/resolver/devand realize that
it needs a special DNS server located on
which is a pow DNS server, resolving the IP of the domain to
127.0.0.1, and the browser would then try to make a request
127.0.0.1:80, with header
Host: whatever.dev, which
then the firewall would forward the request from
127.0.0.1:20559, which is the pow HTTP server, which would
try to look at
~/.pow/whatever, locating the
nack_workerprocess, which is a Ruby server, listening on a
UNIX domain socket, and in the mean time, converting the request
object into a netstring embedding a JSON, writing into the UNIX
domain socket, and the
nack_workerwould parse the netstring,
extracting the JSON, parsing the JSON, and builds the Rack
object based on the JSON it reads, finally calling the Rack app,
passing the response back to pow, and back to the browser.
Oh wait, it might not really pass the request along to the Rack app.
It could be intercepted by pow if the requested path matches a file
located in the particular Rack app's public directory.
Seriously? Sorry that I am too lazy to link the source line by line.
This is simply too much. It also needs to handle RVM stuffs, yet
another pile of stuffs.
I would much prefer a simple command to launch a server.
If you're developing a number of applications, and need to run them
at the same time, then I believe you must have the ability to solve
this in a more elegant way.
Maybe write a pow equivalent in Ruby, then all the conversions
could be omitted. We could simply spawn Ruby processes. I don't
see what's the point of using Node to run Ruby.