Deploying Django App with Apache2 on Ubuntu 18.04

thumbnail

So, you have developed an awesome web app using Django. Now you want to deploy it on a Linux server, may be running Ubuntu 18.04. Let's do it together.

Here is our system config:

  1. Apache 2.4
  2. Ubuntu 18.04
  3. MySQL 5.7
  4. Django 3.0.2
  5. Python 3.6

I am using a basic AWS Lightsail Linux server with preinstalled Ubuntu 18.04. However, you have to install the other necessary software in your stack, for example, Apache, MySQL, Python and several other dependent software. I am guessing that, you have already acquired a Lightsail or similar server and installed the typical software necessary for a working LAMP stack. If you don't know how to do it, there are plenty of tutorials on internet about those.

First of all, deploying Django web app using Apache is tricky because it uses WSGI (Web Server Gateway Interface) to communicate to the web server. It is not as straight forward like deploying a PHP app, just throwing you source file in a DocumentRoot folder and Apache takes care of them. As you are already developed a complete app using Django, so you probably already know about those things or at least have some idea.

Create a Python virtual env

Create a Python virtual env by running the following command in terminal:

python -m venv /path/to/virtual/env

Install Python WSGI module

Install the python wsgi module for Apache by running the following command on terminal. Then enable the module by running the second command.

sudo apt-get install libapache2-mod-wsgi-py3
sudo a2enmod wsgi

Create virtual host config

If you are deploying as standalone app on a domain, then you have to do this in /etc/apache2/sites-available/mysite.com.conf. If you are deploying on a sub-domain, then you have to do it in /etc/apache2/sites-available/subdomain.mysite.com.conf, where mysite.com is your domain name and subdomain is your sub-domain name.

<VirtualHost *:80>
    ServerAdmin webmaster@mysite.com
    ServerName subdomain.mysite.com
    ServerAlias subdomain.mysite.com

    ErrorLog ${APACHE_LOG_DIR}/mysite_error.log
    CustomLog ${APACHE_LOG_DIR}/mysite_access.log combined

    Alias /static /path/to/static/folder
    Alias /media /path/to/media/folder

    <Directory /path/to/media/folder>
        Require all granted
    </Directory>

    WSGIDaemonProcess a_system_wide_unique_name processes=2 threads=15 python-home=/path/to/venv python-path=/path/to/django/project/dir
    WSGIProcessGroup a_system_wide_unique_name
    WSGIScriptAlias / /path/to/django/project/folder/wsgi.py
</VirtualHost>
WSGIDaemonProcess a_system_wide_unique_name processes=2 threads=15 python-home=/path/to/venv python-path=/path/to/django/project/dir

a_system_wide_unique_name: A system-wide WSGI daemon process name. If multiple python web apps using same name, there will be some conflicts and your apps wont' work properly. If you are serving pages over https, and have separate configuration for http and https, then you also need to separate name in those settings.

  • python-home=/path/to/venv:
    Root path to your virtual environment
  • python-path=/path/to/django/project/dir:
    Root path to your django project dir.
  • WSGIScriptAlias / /path/to/your/wsgi.py:
    The path to your django app's wsgi script path, typically it is something like /path/to/django/project/dir/wsgi.py

Make sure that your WSGIDaemonProcess and WSGIProcessGroup must be same, otherwise you will get error messages like

No WSGI daemon process called 'whatever-name-it-s' has been configured

Now update your wsgi.py file which will look like this after the change:

"""
WSGI config for core project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
"""

import os
import time
import traceback
import signal
import sys

from django.core.wsgi import get_wsgi_application

sys.path.append('/path/to/your/django/project/root/folder')
sys.path.append('/path/to/your/venv/lib/python3.X/site-packages')

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'APP_NAME.settings')
os.environ['DJANGO_SETTINGS_MODULE'] = 'APP_NAME.settings'

try: 
    application = get_wsgi_application()
except Exception:
    # Error loading applications
    if 'mod_wsgi' in sys.modules:
        traceback.print_exc()
        os.kill(os.getpid(), signal.SIGINT)
        time.sleep(2.5)

We have added your django project root directory and your venv site packages directory to the system path so that your project and virtual env's python modules can be loaded and used as necessary. Then we also added the django app's settings module in the environment for it to work properly.

That's all! Now visit to your site url and enjoy your new django app.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Back To Top