Nginx configuration for Django

Leave a comment
Howtos / System Administration

Django is a powerful framework for building websites. To run a production website, usually an application server is used. So nginx will do two basic things:

  • Serve your Django application from the application server port to the web port (Reverse Proxy)
  • Serve static and media files

The application server used in this example is gunicorn, the application server chosen by Instagram of the earlier days, but it can be anything running on port 9999. Change port number as required in the example.

The following nginx conf was adapted from this, with some additions and it contains:

  • a commented non www to www website redirect
  • gzip for javascript, json, css and proxy routes
  • media files with etag (1 year)
  • static files with etag (1 minute)
  • an host-based favicon distributor (reusable as is)
  • a commented basic auth to make a website private
  • reverse proxy to gunicorn
  • a simple block for a common type of malicious activity

It works fine with Django 1 and 2.

# uncomment for redirect
# server {
#    # redirect WITH www from example.com and example.net
#    listen 80;
#    server_name example.com example.net;
#    return 301 http://www.example.com$request_uri;
# }

server {
    listen	80;
    # the domain name it will serve for
    server_name www.example.com;
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;

    # enable gzip for proxy requests
    gzip on;
    gzip_proxied any;
    gzip_vary on;
    gzip_http_version 1.1;
    gzip_types application/javascript application/json text/css text/xml;
    gzip_comp_level 4;

    # @see http://uwsgi-docs.readthedocs.org/en/latest/tutorials/Django_and_nginx.html#configure-nginx-for-your-site

    # Django media
    location /media  {
        etag on;
        expires 365d;
        alias /path/to/media_root;  # your Django project's media files - amend as required
    }

    location /static {
        etag on;
        expires 1m;
        alias /path/to/static_root; # your Django project's static files - amend as required
    }

    location /favicon.ico {
        # all favicons inside /path/to/favicons/ this directory
        # notation: www.example.com.ico
       alias /path/to/favicons/$host.ico;
    }

    location / {
        # an HTTP header important enough to have its own Wikipedia entry:
        #   http://en.wikipedia.org/wiki/X-Forwarded-For
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # enable this if and only if you use HTTPS, this helps Rack
        # set the proper protocol for doing redirects:
        # proxy_set_header X-Forwarded-Proto https;

        # pass the Host: header from the client right along so redirects
        # can be set properly within the Rack application
        proxy_set_header Host $http_host;

        # we don't want nginx trying to do something clever with
        # redirects, we set the Host: header above already.
        proxy_redirect off;

        # set "proxy_buffering off" *only* for Rainbows! when doing
        # Comet/long-poll stuff.  It's also safe to set if you're
        # using only serving fast clients with Unicorn + nginx.
        # Otherwise you _want_ nginx to buffer responses to slow
        # clients, really.
        # proxy_buffering off;

        # Uncomment for maintenance
        ### auth_basic "Insert password here";
        ### auth_basic_user_file /path/to/.htpasswd;

        proxy_connect_timeout       30000;
        proxy_send_timeout          30000;
        proxy_read_timeout          30000;
        send_timeout                30000;

        # @see https://eng.eelcowesemann.nl/linux-unix-android/nginx/nginx-blocking/ and seositecheckup.com
        if ($http_user_agent ~ "libwww-perl") {
          return 403;
          break;
        }

        # Try to serve static files from nginx, no point in making an
        # *application* server like Unicorn/Rainbows! serve static files.
        if (!-f $request_filename) {
            proxy_pass http://localhost:9999;
            break;
        }
    }
}

Run nginx -t to check and then systemctl reload nginx to apply.

This is a http version, to configure the website for https follow this howto.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s