David.dev 🎪

about ~ apps

2020-01-21 Django, Python

Deploying Django 3 with Apache and mod_wsgi

I have recently decided to move my django deployment from Nginx + Gunicorn to Apache and mod_wsgi. There are a few reasons for this but, primarily, is about easy to setup and maintain several django instances on the same dedicated server.

With Nginx and Gunicorn you have to run a reverse proxy, assign a port or socket to the django process and then use screen (or something similar) to keep the Gunicorn process running. In alternative you can probably setup Gunicorn as a service and configure it but, frankly it seems less straightforward to Apache. According to the Django Manual Apache + mod_wsgi is a tried and tested way to deploy, so why not ?

The benefit is that once you configure your VirtualHost you don't have to do anything else to keep the process running. As a bonus my background with 5 processes makes it much faster than the Nginx + Gunicorn setup (also with 5 workers) so that is even better.

I had to enlist the help of an experienced system administrator to to set this up without using a virtualenv. I couldn't find anything available on the net with this setup so I am happy to share the config file here with the home that it might be helpful to others (this implies that you already have apache and mod_wsgi properly installed):

<VirtualHost *:80>
ServerName YOURDOMAIN.com
ServerAlias WWW.YOURDOMAIN.com
ServerAdmin webmaster@localhost
DocumentRoot /home/yourusername/yourDjangoProjectRoot
# here the static folder config
Alias /static /home/yourusername/yourDjangoProjectRoot/static
<Directory /home/yourusername/yourDjangoProjectRoot/static >
Require all granted
</Directory>
<Directory /home/Yourusername/YourDjangoProjectRoot/yourproject >
Require all granted
</Directory>
# This *has* to be commented out if you plan to use certbot to create an SSL certificate
# WSGIDaemonProcess YourAppName python-path=/home/yourusername/yourDjangoProjectRoot:/home/YourUsername/.local/lib/python3.7/site-packages processes=5
# WSGIProcessGroup YourAppName
# WSGIScriptAlias / /home/yourusername/yourDjangoProjectRoot/DjangoProject/wsgi.py
ErrorLog ${APACHE_LOG_DIR}/stocks_fashion.log
CustomLog ${APACHE_LOG_DIR}/stocks_fashion-access.log combined
</VirtualHost>

Now a few things to consider here: first the 3 WSGI lines have to be commented out if you plan to use certbot apache. Not commenting them will result in not creating the proper YourDomain-le-ssl.conf that is needed to serve the SSL. (Apache will complain about a duplicate WSGI directive because it would be both in the non SSL and SSL VirtualHost). So the workaround is to comment them out, run certbot apache and then uncomment them in the freshly generated -le-ssl.conf file.

The processes=5 will ensure 5 processes running making the whole Django app much faster. You can change it according to your needs and resources.

With this config you can run Django 3 with Apache 2 and mod_wsgi and SSL certificate provided by certbot. After having used Nginx + Gunicorn for a while I can recommend this is a very robust and functional alternative.The Django app will be running in deamon mode so it will also reload upon file changes (if you want to force reload you can just use touch /home/yourusername/DjangoProject/Project/wsgi.py).