djangodeploymentgunicornwhitenoise

How to deploy a Django + Whitenoise application using gunicorn?


I am using Whitenoise to serve static files in my Django app. I am NOT using Nginx. I plan to use Whitenoise behind a CDN like Cloudfront in the future. See Whitenoise FAQs.

I have been looking for deployment instructions, which handle these questions:

  1. Since I am not using nginx, I plan to bind gunicorn directly to port 80. This results in an error - Permission Denied. I can run gunicorn as root, but that seems like a bad approach.

  2. How to handle SSL certificate stuff? Typically this is handled by servers like Nginx.

EDIT: I am deploying my application on a Ubuntu 18.04 VM on Google Cloud Compute Engine.

P.S.: Mine is not going to be a very high traffic website. Others have used this configuration to serve websites with a high traffic. See this Squeezing every drop of performance out of a Django app on Heroku.


Solution

  • TL;DR

    I used nginx as the http server. I removed the configuration associated with static files in nginx, so the static file requests are passed to the wsgi layer (gunicorn) and are handled by Whitenoise. So you can follow any 'nginx + gunicorn + django' deployment instructions/tutorials, which are easily available with a simple google search.

    This post cleared it up for me: Deploying your Django static files to AWS (Part 2).

    Long Answer

    As mentioned before there are many tutorials about deploying Django + Whitenoise applications on Heroku. As pointed out in the comments:

    Heroku, which has its own proxy layer in the front end, and is therefore not at all relevant.

    Without verifying this statement, I thought this must be true. gunicorn is not a full fledged webserver. In fact gunicorn creators strongly recommend using it behind a proxy server (Eg. Nginx). See docs.

    I was confused because I always thought of Nginx as just a reverse proxy. Functioning as a reverse proxy for static assets is just one of the functions of nginx. It provides a lot more features like buffering slow clients, which gunicorn does not, which helps prevent denial-of-service attacks.

    I knew this already. It would have been foolish to not use nginx or any other webserver.

    Whitenoise is just there to set proper caching headers for static files and enable compression using gzip/brotli. When used with whitenoise.storage.CompressedManifestStaticFilesStorage, it will automatically generate versioned static files. Eg. /static/js/app.49ec9402.js if you have put your file in the template as {%statis%} 'js/app.js'. A versioned file will have max-age set to 10 years i.e. cached forever.

    If you are not deploying on Heroku you will still need a web server like Nginx. So you can follow any 'nginx + gunicorn + django' deployment instructions/tutorials, which are easily available with a simple google search. One of which is Deploying your Django static files to AWS (Part 2), which helped me get this issue sorted out.