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 http://ppa.launchpad.net/nginx/$nginx/ubuntu lucid main" > /etc/apt/sources.list.d/nginx-$nginx-lucid.list apt-key adv --keyserver keyserver.ubuntu.com --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 *.example.com 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.
-----BEGIN CERTIFICATE REQUEST----- MIIC3zCCAccCAQAwgZkxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNQTEPMA0GA1UE BxMGQm9zdG9uMRcwFQYDVQQKEw5CdWxsaG9ybiwgSW5jLjEOMAwGA1UECxMFUmVh Y2gxHDAaBgNVBAMUEyouYnVsbGhvcm5yZWFjaC5jb20xJTAjBgkqhkiG9w0BCQEW FnJlYWNoYmV0YUBidWxsaG9ybi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQCqayVplOo/PJhoufXSaFD7q66pmIfveWW3dlRNxltgk7l2jhusnsVz 37P9F/qwxUjn6ijgZnopXNMQn2UEPKr8J65DgdSyLEFYFIO1DtLEYxS4myL2Bjc+ mDEPirC05jDLOMMP7tr+607jWxOaM9p5G+kNjUc+gFCN4T7BSYKn1gnpmUPJDdYO FOD0sZ4G0SWrEDWNhzp5fNAqtviApDWfFWcDL2FJIiYKethp3moLsu5eAycji3PE hLqDZPXO3AQ+eaFAmRbkjB0imlbYgLn4MHWQWZHuPjvTV1puJfbnb4auMmu1xBCE wKgTS7ZgHp/9RbR19W5aDNBkiM+WkdMhAgMBAAGgADANBgkqhkiG9w0BAQUFAAOC AQEAkfuZ5GU7f1sxECH3hP2TOVRCvPay4R6J3Ql2782DaGjmqix8KsJMXNymVE8B 9+09NFKo9Mv+Rwb/bZCjwviEADLXeMCjm503UMgWjyH+ONY4bNOs6k6hZYM7rmVb WnRgk2FXi9Kxgp5YMDQrTV1o2o6eykObqAfnWlG8Awka7w9aPNnp+HiFNtygB78R oFP/8v4KGVbSOGsvXRNPGs7y6dYCBnPxd5OxoXlc06j7gnuPbHKh69Bo7e2gTRYp T2g6GC3fgglMmq7pku775adR30E3CnS/Huc+MmBWC/TYYZv1Uv+8+sLnBZUDHgrH oeMl/QXd6Nnev+IVx0am4moU0Q== -----END CERTIFICATE REQUEST-----
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 server.key.org sudo openssl rsa -in server.key.org -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; server_name www.example.com; 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 http://www.example.com. 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.