Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Secure Django Admin with SSL Client Certificate in Nginx

If you need a good way to secure your Django admin site (e.g., http://example.com/admin/), this is it.

Reference: https://gist.github.com/mtigas/952344

1. Creating self-signed certificates

Find a directory to put your certificates, e.g., /etc/nginx/certs/.

Generate server certificate:

openssl genrsa -out ca.key 4096
openssl req -new -x509 -subj "/C=NO/ST=Oslo/L=Oslo/O=Twined/CN=www.example.com" -days 3650 -key ca.key -out ca.crt

Generate client certificate:

openssl genrsa -out client.key 4096
openssl req -new -subj "/C=NO/ST=Oslo/L=Oslo/O=Twined/CN=www.example.com" -key client.key -out client.csr

# self-signed
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt

Convert client key to PKCS (for browsers):

openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

Make sure you enter an export password. Otherwise, you may be unable to import it to your browser.

2. Configure Nginx

/etc/nginx/sites-available/yoursite:

# the upstream component nginx needs to connect to
upstream django {
    #server 127.0.0.1:8000; # for a web port socket
    server unix:///tmp/uwsgi_yoursite.sock;
}

# configuration of the server
server {
    # the port your site will be served on
    listen      80;

    # the domain name it will serve for
    server_name .example.com; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    location /media  {
        alias /path/to/your/site/media;
    }

    location /static {
        alias /path/to/your/site/static;
    }

    location /favicon.ico {
        alias /path/to/your/site/static/img/favicon.ico;
    }

    # admin is served at port 443, return 404 on port 80
    location /admin {
        return 404;
    }

    # send all other requests to the Django server
    location / {
        include     /etc/nginx/uwsgi_params;
        uwsgi_pass  django;
    }

    # redirect error pages to Django, should provide Django views for these
    error_page 404 = /_error/404/;
    error_page 403 = /_error/403/;
    error_page 500 = /_error/500/;
    error_page 502 503 = /static/_503.html;
}

server {
    listen 443;
    ssl on;
    ssl_certificate /etc/nginx/certs/ca.crt;
    ssl_certificate_key /etc/nginx/certs/ca.key;
    ssl_client_certificate /etc/nginx/certs/client.crt;
    ssl_verify_client on;

    location /media  {
        alias /path/to/your/site/media;
    }

    location /static {
        alias /path/to/your/site/static;
    }

    location /admin {
        include     /etc/nginx/uwsgi_params;
        uwsgi_param HTTP_X_FORWARDED_PROTO $scheme;
        uwsgi_pass  django;
    }

    # redirect other requests to http
    location / {
        return 301 http://$host$request_uri;
    }
}

3. Import client certificate

OSX

  • Add client.p12 to Keychain access
  • Open Keychain Access
  • File -> Import items -> client.p12
  • Double click the certificate
  • Click the triangle next to Trust
  • Set "Secure Sockets Layer (SSL)" to "Always Trust".
  • Close window and enter password
  • Now add ca as a trusted root authority
  • File -> Import items -> ca.crt
  • Trust it
  • Restart browser and go to https://fqn/admin

WINDOWS

  • Go to Start | and run the command certmgr.msc.
  • Expand the tree to get to Trusted Root Certification Authorities | Certificates.
  • Go to All Tasks, choose Import and import the certificate in question.
  • Restart browser and go to https://fqn/admin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.