Anaconda + Django + Apache

In this tutorial, we describe how to set up a Django webserver running on Ubuntu 14.04 using the Apache webserver and Anaconda Python 3.

Table of Contents

Install the Apache webserver

Install apache development files:

sudo apt-get install apache2 apache2-bin apache2-dev

Install the Anaconda Python distribution

Download Anaconda with Python 3 and install it into the /opt/anaconda3 folder. Do not install anaconda into the /home/username/anaconda3 folder because the Python path will be hard-coded in your apache configuration files.

sudo bash Anaconda3-2.3.0-Linux-x86_64.sh -bfp /opt/anaconda3

Install required conda packages

Install Python packaged required by django and setup mod-wsgi:

# Login as superuser
sudo su

# Add conda to your path
export PATH=/opt/anaconda3/bin:$PATH

# Install python packages
conda install \
django django-analytical django-sendfile django-allauth mod_wsgi \
  flake8 nose mock coverage pygments lxml cssselect docutils \
  hovercraft rst2pdf pillow mysql-connector-python
# If conda is missing some of those packages, you should build them \
# yourself, or use pip:
# pip install django-analytical django-sendfile mod_wsgi ...

# Move the `mod_wsgi` library to the apache modules folder:
sudo mod_wsgi-express install-module

# ...which should give the following output:
LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi-py34.cpython-34m.so
WSGIPythonHome /home/username/anaconda3

Configure Apache

Configure the wsgi mod in apache (if your wsgi.conf and wsgi.load files do not exist, you have have to create them first).

In /etc/apache2/mods-available/wsgi.conf, add lines:

<IfModule mod_wsgi.c>
    WSGIPythonHome /opt/anaconda3
    WSGIPythonPath /opt/anaconda3/lib/python3.4/site-packages
</IfModule>

In /etc/apache2/mods-available/wsgi.load, add line:

LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi-py34.cpython-34m.so

Enable the wsgi mod:

sudo a2enmod wsgi

Create a /etc/apache2/sites-available/mysite.conf configuration file for your Django server. The file should look something like this.

<VirtualHost *:80>
    # Admin email, Server Name (domain name) and any aliases
    ServerAdmin squire@mysite.org
    ServerName mysite.org
    ServerAlias www.mysite.org

    WSGIDaemonProcess mysite display-name=%{GROUP} user={username} group={groupname} python-path=/home/username/mysite
    WSGIProcessGroup mysite

    WSGIScriptAlias / /var/www/mysite/wsgi.py

    <Directory "/var/www/mysite">
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>

    Alias /static/ /var/www/mysite/static/

    <Directory /var/www/mysite/static/>
        Require all granted
    </Directory>

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

</VirtualHost>

Configure Django

Move the wsgi.py file from your django webserver folder, to a folder accessible by apache:

sudo mkdir /var/www/mysite
sudo cp /home/username/mysite/mysite/wsgi.py /var/www/mysite/wsgi.py

The wsgi.py file should be something like this:

import os
import sys

path = '/home/username/mysite'
if path not in sys.path:
    sys.path.append(path)

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Add STATIC_ROOT and STATIC_URL to the Django settings.py file:

STATIC_ROOT = '/var/www/mydomain.com/static/'
STATIC_URL = '/static/'

Collect static files

sudo su
export PATH=/opt/anaconda3/bin:$PATH
python ./manage.py collectstatic

Add your side to hosts

Edit /etc/hosts to include mysite.org and www.mysite.org after 127.0.0.1 localhost. It should look something like this::

127.0.0.1       localhost        mysite.org        www.mysite.org

Final steps

Restart Apache and you are good to go.

sudo service apache2 restart

Navigate to mysite.org and you should see your Django webpage.

Troubleshooting

In some cases, apache may fail to run with mod_wsgi compiled for Python 3, giving the following error in the apache2 error log (/var/log/apache2/error.log):

Traceback (most recent call last):
    File "/usr/lib/python3.4/site.py", line 586, in <module>
        main()
    File "/usr/lib/python3.4/site.py", line 572, in main
        known_paths = addusersitepackages(known_paths)
    File "/usr/lib/python3.4/site.py", line 287, in addusersitepackages
        user_site = getusersitepackages()
    File "/usr/lib/python3.4/site.py", line 263, in getusersitepackages
        user_base = getuserbase() # this will also set USER_BASE
    File "/usr/lib/python3.4/site.py", line 253, in getuserbase
        USER_BASE = get_config_var('userbase')
    File "/usr/lib/python3.4/sysconfig.py", line 597, in get_config_var
        return get_config_vars().get(name)
    File "/usr/lib/python3.4/sysconfig.py", line 540, in get_config_vars
        _init_posix(_CONFIG_VARS)
    File "/usr/lib/python3.4/sysconfig.py", line 412, in _init_posix
        from _sysconfigdata import build_time_vars
    File "/usr/lib/python3.4/_sysconfigdata.py", line 6, in <module>
        from _sysconfigdata_m import *
ImportError: No module named '_sysconfigdata_m'
Failed to import the site module

This means that apache is using Python 2 instead of Python 3 to run a program that is designed for Python 3 only, and fails because Python 2 does not have the _sysconfigdata_m module. The solution is to add the following file to your apache envvar file (/etc/apache2/envvar):

export PATH=/opt/anaconda3/bin:$PATH

Apache will now use Anaconda’s Python 3 for everything.

Useful resources

Related

comments powered by Disqus