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:
|
1 2 |
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:
|
1 2 3 4 5 6 |
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:
|
1 2 |
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
|
1 |
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:
12345678sudo mkdir -p /usr/local/srccd /usr/local/srcsudo wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.12.tar.gztar xvfz pcre-8.12.tar.gzcd pcre-8.12./configure --prefix=/usr/localmakesudo make install
- Install NginxInstalling Nginx is a matter of downloading the source, building and installing it. I followed the following steps:
1234567cd /usr/local/srcsudo wget http://nginx.org/download/nginx-1.0.4.tar.gztar xvfz nginx-1.0.4.tar.gzcd nginx-1.0.4./configure --prefix=/usr/local --with-http_ssl_modulemakesudo 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:
|
1 2 3 4 |
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
|
1 |
/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.
[text]
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;
}
}
[/text]
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.conf resides 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.


Well… it’s amazing how fast things move on in the Ruby community. I haven’t been doing much Ruby work until recently and discovered my Ruby interpreter was out of date. Looks like the latest 1.8.7 is p302.
Have you ever wondered what the cmd equivalent for the unix command pwd?
Great, you just bought a new mac to replace your old, sluggish machine that keeps running out of space. Now comes the joy of migrating to a brand new spanking machine. These are the key steps that I took to migrate. In the midst of my journey, I didn’t find one consistent spot which had all the information I needed. So, to help those that may be doing what I did, here are my steps to get my tool stack back up and running….
