The aim of this article is to explain how to deploy a Django site with Apache and WSGI on Linux (Ubuntu), considering that neither apache2 nor mod_wsgi have been previously installed in the system. I will use the deployment of my personal website as an example.

WSGI

WSGI (Web Server Gateway Interface) is the Python standard (PEP 3333) for web servers and applications. It is a specification that describes how web servers communicate with web applications.

There are many frameworks that support WSGI. Django and Flask are two of them.

HTTPD - Apache2 Web Server

Apache is the most commonly used Web Server on Linux. It can be installed using apt-get:

$ sudo apt-get install apache2

We can check the Apache version by doing:

$ /usr/sbin/apache2 -v
Server version: Apache/2.4.6 (Ubuntu)
Server built: Dec 5 2013 18:32:22

The Apache setup files will be placed in /etc/apache2/

mod_wsgi

mod_wsgi is an Apache module that can host any Python application which supports the Python WSGI interface.

mod_wsgi has two primary modes of operation:

  • Embedded mode
    • WSGI applications run within the actual Apache child processes.
    • WSGI applications share the same processes as other Apache hosted applications.
  • Daemon mode
    • Available with Apache 2.X on UNIX.
    • WSGI applications run in separate dedicated processes.
    • It is the recommended mode for running mod_wsgi.

The wsgi module can also be installed in Ubuntu using apt-get:

$ sudo apt-get install libapache2-mod-wsgi

Apache automatically enables mod_wsgi once the module is installed.

We can see that mod_wsgi is now enabled:

$ ls /etc/apache2/mods-enabled
…
wsgi.conf
wsgi.load
…

Apache VirtualHost

At this point, we need to create a new VirtualHost in Apache (we can use the default site as a template).

$ cd /etc/apache2/sites-available
$ sudo cp 000-default.conf juliotrigo.conf
$ vim juliotrigo.conf
<VirtualHost *:80>

  ServerName juliotrigo.com
  ServerAlias www.juliotrigo.com

  WSGIScriptAlias / /path/to/juliotrigo.com/juliotrigo/wsgi.py
  WSGIDaemonProcess juliotrigo.com user=myuser group=myuser processes=2 threads=15 python-path=/path/to/juliotrigo.com:/home/myuser/.virtualenvs/juliotrigo/lib/python2.7/site-packages
  WSGIProcessGroup juliotrigo.com

  <Directory /path/to/juliotrigo.com/juliotrigo>
    <Files wsgi.py>
      Order allow,deny
      Require all granted
    </Files>
  </Directory>

  Alias /favicon.ico /var/www/juliotrigo/static/img/favicon.ico
  Alias /static/ /var/www/juliotrigo/static/

  <Directory /var/www/juliotrigo/static>
    Options -Indexes
    AllowOverride None
    Order deny,allow
    Allow from all
  </Directory>

</VirtualHost>

Disable Apache´s default site.

$ sudo a2dissite 000-default.conf
Site 000-default disabled.
To activate the new configuration, you need to run:
service apache2 reload

Enable our site:

$ sudo a2ensite juliotrigo.conf
Enabling site juliotrigo.
To activate the new configuration, you need to run:
service apache2 reload

And restart Apache:

$ sudo /etc/init.d/apache2 stop
* Stopping web server apache2
*
$ sudo /etc/init.d/apache2 start
* Starting web server apache2
*

In our example, Apache will also serve static files. However, it is recommended to use a separate Web server for that.

We are using mod_wsgi in daemon mode. For that reason, we need to add the WSGIDaemonProcess and WSGIProcessGroup directives to create the daemon process, which will run the Django instance in it.

We are also using virtualenv in our project, that is why we need to add our environment’s site-packages directory to the python path using the WSGIDaemonProcess directive and supplying the python-path option.

Finally, to say that mod_wsgi can only be used with the version of Python (major.minor) that it was compiled for. If we need to specify a version of Python different than the default version in the system, we can use the WSGIPythonHome directive. This is a very interesting and complete article about how to use WSGIPythonHome / WSGIPythonPath.

Other ways of deploying Django

In a new post, I will talk about how to deploy Django using:

  • Nginx
  • Gunicorn / uWSGI

Resources

Some other resources can be found here:

Google code mod_wsgi installation instructions

Google code mod_wsgi quick configuration guide

Google code mod_wsgi configuration directives

Google code mod_wsgi integration with django

How to use Django with Apache and mod_wsgi