Nginx Config file examples for serving django/gunicorn

Basic barebones setup file talking to gunicorn socket

On the following snippet:

  • webapp is the identifier we use to call our app
  • our app django project is located in ~/youruser/apps/webapp directory
  • my Ubuntu user for this example would be youruser
  • the app is running using gunicorn, binded on a unix socket located at /run/webap.sock
  • 2 other directories named ~/youruser/apps/webapp_static and ~/youruser/apps/webapp_media were created outside of the webapp code directory to hold static/media files
server {
    listen 80 deferred;
    client_max_body_size 4G;

    # set the correct host(s) for your site
    server_name webapp.com www.webapp.com;

    keepalive_timeout 5;

    # path for static files or as a fallback in case none of our locations matches
    root /home/youruser/apps/webapp/static;

    location / {
      # checks for static file, if not found proxy to app
      try_files $uri @proxy_to_app;
    }

    location /static/ {
       autoindex off;
       alias /home/youruser/apps/webapp_static/;
    }

    location /media/ {
       autoindex off;
       alias /home/youruser/apps/webapp_media/;
    }

    location @proxy_to_app {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      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;
      proxy_pass http://unix:/run/webapp.sock;
    }
}

Some important notes:

  • Our proxy_pass is using the syntax http://unix:/run/yoursocketfile where yoursocketfile matches the socket we defined during the systemd setup. Our conventions dictated the naming of webapp.soc in the /run/ folder hence the value here
  • We deploy static/media files to their own folders (instead of a subfolder somewhere inside the django app). The reason is security. If something goes wrong in our nginx setup, we don't want people to be able to 'download' our python code files like they do with images and js/css files. That would be catastrophic as they would get access to all sorts of passwords and keys. So if we are gonna be doing file serving, we wanna do it from a place where only files that we want to be serveable exist. Always better safe than sorry :)
  • For serving the static/media folders, we've set autoindex as off. Numerous articles on the web show this to be on, but from a security perspective, it's not very wise. Autoindex=on makes nginx show an 'explorer' like preview of files and folders allowing somebody to navigate the folders being served directly from the web browser. Our users shouldn't need to do that, and in the media files case that might even be dangerous as it will expose other peoples uploaded data (if your users can upload stuff). So autoindex off!

For static content serving, taken from: Serving Static Content | NGINX Documentation