Security. We’ve all heard and read about it. But many of us forget to do something about it, until something nasty happens. In Oct 2010, the blogosphere erupted with the demonstration of Firesheep pointing out that one of the most basic things any web developer can do to improve their application security is to use HTTPS.
For a Rails developer, isn’t this just a matter of adding a gem to your Gemfile, and running bundler?
If only it were that simple.
For this post, I’ll go through some of the steps that I took to get HTTPS going on a Rails application running locally under POW. Hopefully, it’ll be of use to somebody.
What’s POW?
So you have a rails application, which you typically fire up using:
rails s open http://localhost:3000
What happens if you have multiple rails applications? Or for that matter sinatra, merb or any other Rack-based application? Do you fire them all up with separate ports?
Here’s where POW comes in really handy. POW! is a zero-config rack server for Mac OS X. It’s dead easy to install and get running, and makes it possible to host multiple Ruby Rack applications without each Rack application having to run in a separate web server on a separate port.
POWer me up!
To install POW, run the following in the terminal:
echo "export POW_DOMAINS=dev,local" > ~/.powconfig curl get.pow.cx | sh cd ~/.pow ln -s /path/to/myapp myapp open http://myapp.dev
Here’s a trap that I found. The documentation for POW typically tell you to download and install POW with one command, namely; curl piped to sh. However, in my experience, this did not (for some reason) configure OS X’s system resolver properly so requests were not being forwarded to POW. I had to specify the Top Level Domains (TLD) in a config file and reinstall POW. So, save yourself the trouble and set it first with the POW_DOMAINS variable in the .powconfig file before you install.
Keep the POWer on
When you start using POW, you may notice that some refreshes take a really long time to come back. This happens because POW tends to spin down the rails instance after a timeout, making it painful when you refresh your page as this causes POW to reinitialise the rails application from scratch (and we all know how long rails 3 takes to initialise). To fix this, edit your ~/.powconfig to include the following:
export POW_TIMEOUT=30000 export POW_WORKERS=3
The POW_TIMEOUT sets POW to keep the process running for a long time, which is typically what you want, given that in development, rails will automatically reload (mostly) the altered files.
So now, you can throw away the rails s command as POW will fire up the instance when you need it.
How Do I Bolt On HTTPS To POW?

AFAIK – you can’t. I looked, and I couldn’t find any way to install a certificate to get HTTPS going. So, the easiest way to bolt on HTTPS is to setup Nginx as a reverse proxy. And although it sounds hard, it isn’t.
Nginx is fast HTTP server. And like any capable HTTP server, it is able to accept HTTPS connections and can be configured to proxy requests through to POW.
Bolt In Nginx
To install Nginx on OS X, you have two choices:
- Install it via Brew
- Install it the old fashion way
Brew me an Nginx
The easy way is to use Brew. Just run
brew install nginx
Done.
I Don’t Have Brew
If you’re like me, and you’re already using MacPorts and haven’t made the switch to brew, then you have to do things the hard way. I followed instructions on Kevin Worthington’s Blog but specifically, I had to do the following:
- Install XCode(I already had XCode installed previously so I didn’t have to do anything). Installing XCode is a matter of downloading it and installing it. In fact, if you’re running Snow Leopard or Lion, you can download it and install it directly via the Mac App Store.
- Install PCREThis required me to download the source and install it manually. The steps I took were as follows:
sudo mkdir -p /usr/local/src cd /usr/local/src sudo wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.12.tar.gz tar xvfz pcre-8.12.tar.gz cd pcre-8.12 ./configure --prefix=/usr/local make sudo make install
- Install NginxInstalling Nginx is a matter of downloading the source, building and installing it. I followed the following steps:
cd /usr/local/src sudo wget http://nginx.org/download/nginx-1.0.4.tar.gz tar xvfz nginx-1.0.4.tar.gz cd nginx-1.0.4 ./configure --prefix=/usr/local --with-http_ssl_module make sudo make install
Intermission. Time For Certificates.
Ok. Time for a break. Time to break out openssl to generate some certificates.
HTTPS sits on top of Secure Sockets Layer (SSL). For this to work, the encrypted communication requires certificates to be installed at the web server end. In production, you would purchase the certificate from a Certificate Authority (CA) like Verisign or Digicert. The CA’s role is to issue you with a certificate that verifies the identity of the entity the certificate is for (e.g. the domain name owner).
But for development, you don’t need a certificate from a CA. All you need is openssl to generate a certificate which is self-signed. There are countless articles on the web describing this process in detail. www.akadia.com’s article seems to be pretty self explanatory.
Once you’re done generating the certificates, you will need to either copy or symlink them to the appropriate Nginx location so that Nginx can find them. To do this, I did the following:
cd /usr/local/conf mkdir ssl cp server.crt ./ssl cp server.key ./ssl
I Have Nginx. Now to configure it.
If you followed my install instructions above, then Nginx’s conf file is located in
/usr/local/conf/nginx.conf
You will need to edit the nginx.conf file to configure Nginx to:
- Use the certificates you generated
- Listen to port 443 to handle the HTTPS protocol
Here’s what I added to the nginx.conf file to configure Nginx as a reverse proxy.
server {
listen 443 ssl;
server_name myapp.dev;
ssl on;
ssl_certificate ssl/server.crt;
ssl_certificate_key ssl/server.key;
keepalive_timeout 60;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1;
### force timeouts if one of backend is died ##
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
### Set headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
### Most PHP, Python, Rails, Java Apps can use this header
proxy_set_header X-Forwarded-Proto https;
### By default we don't want to redirect it
proxy_redirect off;
}
}
The things that you may need to alter are:
server_name– enter the domain that matches what you would enter to hit POWssl_certificate– enter the location of your server.crt file. If you copied the certificates
to/usr/local/conf/ssl, then enterssl/server.crtsince the
nginx.confresides in/usr/local/confssl_certificate_key– enter the location of your server.key file. This should be similar
to that forssl_certificate
The rest of the configuration tells Nginx to proxy the request to localhost on port 80, which is where POW will
kick in and handle the request for you.
Configured!
Once you’re done, fire up Nginx using /usr/local/sbin/nginx and test it by navigating to https://myapp.dev.
“You gotta blog about this man…” cried Alan after I checked in. In acknowledgement, I nodded. Fast forward four weeks later, after CrowdHired has launched… I now have some breathing space to really blog about it. So hopefully this has been of help to you and saved you some time along the way.


Indirectly, why POW over, say foreman (http://ddollar.github.com/foreman/)?
If you’re talking about https://github.com/ddollar/foreman then POW and foreman are two different things and serve two different purposes.
Foreman is a gem to interpret a Procfile and start up the various processes. So, effectively it is a way to easily manage multiple processes for your application. In fact @rbates asked the following question on twitter recently:
"I have a Rails app where I need to start about 5 servers/daemons to get it working in development. Any suggestions for making that easier?" ~ @rbates
To which, he discovered foreman:
" Thank you all who suggested Foreman, looks like that does what I need! http://blog.daviddollar.org/2011/05/06/introducing-foreman.html " ~ @rbates
And subsequently did a screencast on it.
POW isn’t geared for this. POW’s real purpose is to make it super easy to host multiple Rack applications on your development machine. It hooks into OS X’s DNS resolver to route specific domain names (eg. myapp.dev) to your app. POW does nothing to help you fire up background workers or your own custom daemons/processes/dependencies that your application may require.
Hope this helps clarify your question.