Setting up SSL with Amazon ELB, Nginx and Django

There’s no question any site you run should be served over HTTPS. It’s one of the most essential ways of making user data more secure. With initiatives like Let’s Encrypt , barriers of entry like certificate price should soon be a thing of the past. In this post I’d like to explain how to set up SSL on an AWS Elastic Load Balancer, which is compatible with the popular Django + Nginx stack.

ELB Setup

If you require a full walkthrough, I’d recommend using this step-by-step guide from Amazon. The most significant difference in setup is having listener ports (80 and 443) forward to port 80, as illustrated here:

SSL configuration

The server will now communicate with ELB over http, so you should configure the AWS to only accept connections from the Load Balancer.

Nginx setup

This bit of configuration will redirect users trying to access the site over http to https, which is done by checking the X-Forwarded-Proto header set by the Load Balancer when forwarding the connection. This line must be added to the configuration file to perform the redirect:

if ($http_x_forwarded_proto != 'https') { 
  return 301 https://$host$request_uri;
}

Django setup

The last part of the configuration is making Django recognize those connections as secure. Fortunately this is accomplished by configuring one setting: SECURE_PROXY_SSL_HEADER. In this particular case, it would look exactly as it does in the docs:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

And that’s all. Hope this short guide saved you some googling time!