Skip to content

Instantly share code, notes, and snippets.

@aj-justo
Created August 1, 2012 17:02
Show Gist options
  • Save aj-justo/3228782 to your computer and use it in GitHub Desktop.
Save aj-justo/3228782 to your computer and use it in GitHub Desktop.
SSL setup with Nginx + Gunicorn + Django 1.3 or 1.4

Configuring Nginx to serve SSL content is straight forward, once you have your certificate and key ready: server {    listen 443 default ssl;    root /path/to/source;    server_name mydomain;

   ssl_certificate      /path/to/cert;    ssl_certificate_key  /path/to/key;

   client_max_body_size 10M;    access_log /var/log/nginx/alog.log;    error_log /var/log/nginx/elog.log;

   location / {        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header Host $http_host;        proxy_redirect off;        proxy_pass  http://unix:/sourcepath/run/app.sock;    }

}

But you will find, as I did, that Django makes redirections from https to http URLs when you use an HttpResponseRedirect object.

When Django does a redirection, it composes an absolute URI based on the one in the request object. And the request object uses its method build_absolute_uri() to make this URI, which in turn calls another HttpRequest method, is_secure(), to check whether to use http or https.

OK, that was all an intro. The interesting bit I want to share is that this is_secure() method works differently under Django 1.3 or 1.4. Under 1.3 it only checks whether an environment variable named "https" exists and its value is "on":

def is_secure(self): return os.environ.get("HTTPS") == "on"

So if you want to make sure you serve secure URLs all the way, you need to setup that environment var.

But under 1.4 it does another check before doing that one. It looks for the HTTP header X-Forwarded-Protocol, and if it is present, it returns True (https request). This header has to be added to in the Ningx configuration for the secure server so it is passed to gunicorn: location / {        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header Host $http_host;        proxy_redirect off; proxy_set_header X-Forwarded-Protocol https;        proxy_pass  http://unix:/sourcepath/run/app.sock;    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment