nginx + SSL reverse proxy tutorial

If you have an existing HTTP application that you want to enable SSL for, nginx provides a convenient reverse proxy mode. In this mode, nginx is just responsible for providing SSL encryption; the actual HTTP content is still being served from your existing web server or load balancer.

First, you need to install nginx. On Ubuntu 11.10, you can install it directly from the Ubuntu repositories.

sudo apt-get install nginx

On older Ubuntu distributions, you will need to add a custom PPA.

sudo -s
nginx=stable # use nginx=development for latest development version
echo "deb$nginx/ubuntu lucid main" > /etc/apt/sources.list.d/nginx-$nginx-lucid.list
apt-key adv --keyserver --recv-keys C300EE8C
apt-get update
apt-get install nginx

Next, you need to generate a Certificate Signing Request and a secret key file. I created mine directly inside a new directory that we will point nginx to.

sudo mkdir /usr/local/nginx
sudo mkdir /usr/local/nginx/conf
cd /usr/local/nginx/conf
sudo openssl genrsa -des3 -out server.key 2048
sudo openssl req -new -key server.key -out server.csr

You will be asked a bunch of questions about the SSL certificate. This is semi-official information, so you want it to be accurate. The certificate authority may actually call/email people to verify some of the information. Technically, the only important field is the Common Name, which is the domain name you want the certificate for. You should look up some SSL creation tutorials to make sure you have the correct values.

In my case, I wanted a wildcard certificate, which can be used for all subdomains on the domain in question, so I entered * for the common name.

Now you get out your credit card. You need to purchase a certificate based on this .csr file. I chose Digicert. A wildcard certificate cost about $1300 for three years.

They will ask you for the csr file. You can also paste in the text of the file, which looks something like this.


The certificate authority vendor will produce a .pem file, which has both your new certificate and the vendor's certificate bundled together. Once you get the certificate via email, you can proceed to setup a reverse proxy in nginx. First, remove the passphrase from the .key file. Otherwise, nginx will prompt for it interactively every time the service starts.

sudo cp server.key
sudo openssl rsa -in -out server.key

Then you have to configure nginx to use the .pem file from the certificate authority, as well as your secret .key file. There is an excellent wiki for other configurations that nginx supports.

server {

    listen 443 default_server;

    ssl on;
    ssl_certificate /usr/local/nginx/conf/server.pem;
    ssl_certificate_key /usr/local/nginx/conf/server.key;
    ssl_session_cache shared:SSL:10m;

    location / {

        proxy_pass http://localhost:8000; # my existing apache instance
        proxy_set_header Host $host;

        # re-write redirects to http as to https, example: /home
        proxy_redirect http:// https://;

Note the proxy_redirect directive. I noticed that when my application performed a redirect internally, it was using the global URL, ie To keep the user on the SSL version w/o having to make my application SSL aware, or change to protocol relative redirects, I simply told nginx to re-write the redirect on the fly. Since I am only asking nginx to handle SSL traffic, it can safely use https for all redirects, given that I'm not redirecting to other sites.

That's it. You just need to start the server with "service nginx start". You can test that it's working in a browser, or "openssl s_client -connect localhost:443" for a more verbose test.

I'm currently working at NerdWallet, a startup in San Francisco trying to bring clarity to all of life's financial decisions. We're hiring like crazy. Hit me up on Twitter, I would love to talk.

Follow @chase_seibert on Twitter