At Firmhouse, we are working on a new web service and we’re releasing an in-development demo to everyone who is interested. Normally, in demo apps security is less the case and there is always some disclaimer that says you shouldn’t use real production data like passwords and API keys. In my opinion, this sucks because you allways want to use your real-life data to test a demo and see if it’s useful for you specifically. That’s why, the best way to have some security in your demo app is by using a self-signed SSL certificate to secure passwords and other sensitive account information your demo users will be adding.
For our web app, we use Ruby on Rails running on Phusion Passenger, served by Nginx.
This blog post will guide you trough the process of adding a self-signed SSL certificate to your Rails app, running on Phusion Passenger and Nginx by following these steps:
- Generating the required SSL key and certificate files for use with nginx.
- Recompiling the nginx server through the passenger-install-nginx-module command.
- Configuring your web app in nginx to redirect non-secure connections to the secure address of the app with https:// and make sure www. will get redirected on both versions as well.
I use a few other blog posts in this article, so I would like to thank the authors for providing the information publicly and freely.
Ok, now let’s start:
1. Generating the required SSL key and certificate files
This step is largely taken from the Slicehost Articles: http://articles.slicehost.com/2007/12/19/ubuntu-gutsy-self-signed-ssl-certificates-and-nginx.
First of all, generate an SSL private key to sign your certificate with:
openssl genrsa -des3 -out myssl.key 1024
And enter a passphrase for the key which we will remove later on.
Now, we need to generate a Certificate Signing Request:
openssl req -new -key myssl.key -out myssl.csr
This command will ask you various questions. Fill them as you see fit. You can skip the extra attributes by just pressing enter when asked.
Now, we are going to remove the passphrase from your key by making a copy and then generating it back to the original file without entering a passphrase. You can do this with the following commands:
cp myssl.key myssl.key.org
openssl rsa -in myssl.key.org -out myssl.key
rm myssl.key.org
We now have a key file, and a csr file. We can use these to generate the actual SSL certificate with the following command:
openssl x509 -req -days 365 -in myssl.csr -signkey myssl.key -out myssl.crt
We should now move these files to the SSL configuration directory on your host. On Ubuntu, this is /etc/ssl/certs and /etc/ssl/private. Do this with the following commands (assuming you use sudo):
sudo cp myssl.crt /etc/ssl/certs/
sudo cp myssl.key /etc/ssl/private/
All required SSL key and certificate files are in place so we can continue with the next section: preparing nginx to be SSL-enabled with the passenger-install-nginx-module command.
2. Recompiling the nginx server with the passenger-install-nginx-module command
By default, the passenger-install-nginx-module command does not enable the SSL compile option in the default installation steps. Here’s how to use the custom build step to configure nginx with SSL.
First of all, be sure you already have nginx installed with the passenger-install-nginx-module command because this will have downloaded the nginx source code in /tmp, which you will need to enter in the custom build steps. If you haven’t already done this, run:
sudo passenger-install-nginx-module
Press enter after you’ve read the introduction message and choose step one “Yes: download, compile and install Nginx for me” by pressing `1′. (recommended) when the installer asks for the install options.
After nginx has been compiled and installed you can now run the
sudo passenger-install-nginx-module
command again. Press enter after you’ve read the introduction message and choose step two “No: I want to customize my Nginx installation. (for advanced users)” by pressing `2′.
You are now asked for the directory of the Nginx source code. The recommended installer step should have downloaded and extracted the source code in /tmp/nginx-x.x.xx. At the time of writing, this was /tmp/nginx-0.7.64. So enter:
Where is your Nginx source code located?
Please specify the directory: /tmp/nginx-0.7.64
And press `Enter’.
The next question will ask you where you want to install Nginx to. The default is /opt/nginx. To leave it this way (I recommend this), just press `Enter’ again.
Now the installer will ask your for extra Nginx configure options as shown in the following screenshot.
Here you should add the --with-http_ssl_module argument which will make sure the configure script will enable the Nginx HTTP SSL module for compilation.
Extra arguments to pass to configure script: --with-http_ssl_module
The script will ask you for a confirmation if you really would like to modify the configure arguments. And yes, you would like to so press `Enter’ to confirm.
The script will now start to configure, compile and install Nginx in /opt/nginx.
Wait a few seconds or minutes for it to finish and continue to the next section: configuring Nginx to use the SSL certificate and create a secure connection for your Rails application.
3. Configure your Nginx to use the SSL certificate to secure the connection to your application
First of all, we will need to add a server block to the Nginx configuration so your application will listen on port 443 and use Phusion Passenger for serving your app. Open /opt/nginx/conf/nginx.conf and add the following block below everything else:
server {
listen 443;
ssl on;
ssl_certificate /etc/ssl/certs/myssl.crt;
ssl_certificate_key /etc/ssl/private/myssl.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
server_name yourdomain.com;
root /srv/apps/qloudwatch/current/public;
passenger_enabled on;
passenger_use_global_queue on;
}
Make sure you use yourdomain.com or www.yourdomain.com here (not both) for nice HTTP redirection to the correct domain name.
Now we need to configure that all non-secure request are redirected to the secure address of the web app. For example: all requests to http://yourdomain.com/ and http://www.yourdomain.com/ should be redirected to https://yourdomain.com.
To do this, add the following before the server section we just added:
server {
listen 80;
server_name www.yourdomain.com yourdomain.com;
rewrite ^(.*) https://yourdomain.com$ permanent;
}
Now, restart your Nginx server by calling `sudo killall nginx -HUP’. Wait a few moments for Nginx to launch and try http://yourdomain.com/ to see if everything works.
And that’s all! You have just generated a self-signed SSL certificate, installed Nginx with the SSL-module enabled and configured the domain with your web application to be reached trough SSL.
I understand this can be quite something to take in if you’re new to SSL and Nginx so if you have any questions, any questions at all about this or other web app deployment strategies please post a comment, contact me on Twitter (@michiels is my account) or send me an e-mail.








{ 2 trackbacks }
{ 6 comments… read them below or add one }
Hey… self signed certs really just mean the data line is encrypted… but you still can’t trust the server you’re sending your sensitive information to. Trusting the remote server means do you trust the communication channel between you and the server. If you can’t trust the communication channel between you and your server…. then you can’t trust you’re talking to the same server… so why encrypt?
Great article well written and the examples should be very helpful to anyone setting up a secure site. I just wanted to make sure people understand they’re really no safer with a self signed cert then without… and although it sucks – a few hundred bucks for a demo that warrants production data isn’t that bad right?
Hi taf2. I totally agree with you on that point. Self-signing your application is not the right move on production environment. If you want a trustworthy web app in terms of security you need to have a signed certificate by a CA.
However, when you want do demo your app and have sensitive information on it it is at least somewhat better to have a self-signed SSL encrypted connection to prevent network sniffers and the like which can be active both on the client’s side as on the server side. Getting a signed certificate by a CA can take some time and I haven’t had any success with the free alternatives yet.
So, if you want to have your information-sensitive demo up and running as quickly as possible adding a self-signed certificate is better than just leaving it open.
@taf2 (second comment): Agreed, maybe I will write up an article with the same content after I have tested with better demoable alternatives for signed certificates.
And: much thanks for your comments. I rather have smart critical ones than none at all
If you have any tips or other suggestions, please drop a line!
I had the same issue at http://onexenvps.com but I figured out it with your tutorial THANKS!
Hi Mohamed1. That’s great news. I’m happy I could help. If you have any other questions about using SSL with Rails or nginx. Please let me know.