Many people seem to think that it’s either Apache+mod_wsgi or nginx+Gunicorn. However, Apache+gunicorn makes a great combination, and it’s usually much easier to configure than mod_wsgi.
All you need is to setup Gunicorn as explained in the Django documentation, enable Apache’s proxying with
a2enmod proxy_http, and add this to your Apache
ProxyPass /static/ ! ProxyPass /media/ ! ProxyPass / http://localhost:8000/
(You still need to specify
> for the static and media files, in addition to the above.)
Apparently people are worried because of this warning in the Gunicorn documentation:
Although there are many HTTP proxies available, we strongly advise that you use Nginx. If you choose another proxy server you need to make sure that it buffers slow clients when you use default Gunicorn workers. Without this buffering Gunicorn will be easily susceptible to denial-of-service attacks.
This is not a problem with Apache; like nginx, it buffers slow clients alright.
In simplicity terms, the only upside of mod_wsgi is that Apache itself starts the WSGI server, whereas with Gunicorn you need to do this yourself. However, I find it easier to set up systemd or supervisor to automatically start Gunicorn than to configure mod_wsgi.