// Tutorial //

Using mod_wsgi to Serve Applications on Ubuntu 12.04

Published on July 18, 2012
Default avatar
By Etel Sverdlov
Developer and author at DigitalOcean.
Using mod_wsgi to Serve Applications on Ubuntu 12.04

Status: Deprecated

This article covers a version of Ubuntu that is no longer supported. If you are currently operate a server running Ubuntu 12.04, we highly recommend upgrading or migrating to a supported version of Ubuntu:

Reason: Ubuntu 12.04 reached end of life (EOL) on April 28, 2017 and no longer receives security patches or updates. This guide is no longer maintained.

See Instead:
This guide might still be useful as a reference, but may not work on other Ubuntu releases. If available, we strongly recommend using a guide written for the version of Ubuntu you are using. You can use the search functionality at the top of the page to find a more recent version.

Prerequisites

Before starting on this article, be sure that you have gone through the previous 2 in this series. You can find them here:

Installing Django on Ubuntu 12.04

Installing mod_wsgi on Ubuntu 12.04

Creating the Django Application:

First of all, we will navigate to the home directory. Create a new directory and switch into it:

mkdir  -p ~/public_html/domain1.com
cd ~/public_html/domain1.com

After that, go ahead and create a project with the help of the django-admin.py tool.

django-admin.py startproject MyTestProject

Creating the Virtual host & WSGI file:

To serve a Django app properly, it is important for Apache to know that it is supposed to forward certain types of requests to mod_wsgi. It is also important to create wsgi file that tells mod_wsgi how to handle these requests. We will setup a virtual host to accomplish these tasks. It will tell Apache the location of wsgi file and setup the file accordingly.

Open up the new virtual host file.

sudo nano /etc/apache2/sites-available/domain1.com

Next, enter below definition for the virtual host:

<VirtualHost *:80>
        ServerName domain1.com
        ServerAlias www.domain1.com
        WSGIScriptAlias / /home/username/public_html/domain1.com/MyTestProject.wsgi
</VirtualHost>

Once we have instructed apache to use the wsgi file specified above and pass the receiving request to mod_wsgi, we will create the mod_wsgi file itself.

nano ~/public_html/domain1.com/MyTestProject.wsgi

Type in the following configuration:

import os
import sys	
sys.path.append('~/public_html/domain1.com/')
os.environ['DJANGO_SETTINGS_MODULE'] = 'MyTestProject.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

This definition ensures that the necessary modules will be imported. Moreover, it appends the Django project’s path to Python’s path and sets up a number of variables that helps mod_wsgi to work. Once you are done with it, you will need to enable the virtual host and restart Apache.

sudo a2ensite domain1.com
sudo /etc/init.d/apache2 reload

If everything goes as expected, you will be able to see your domain (droplet IP) in the browser, and get the newly created application. Reload Apache in case you receive any NameVirtualHost or port errors.

Static Content

There is a caveat to virtual host definitions. Static content is not supported. To serve the static content properly, you can update few settings in the file MyTestProject/settings.py and use following definition of virtual host.

<VirtualHost *:80>
        ServerName domain1.com
        ServerAlias www.domain1.com
        WSGIScriptAlias / /home/username/public_html/domain1.com/MyTestProject.wsgi
        Alias /static/ /home/username/public_html/domain1.com/static/
        <Location "/static/">
            Options -Indexes
        </Location>
</VirtualHost>

The Alias Directive lets Apache know that it should not allow Django or mod_wsgi to handle anything located under the /static/ directory of your domain. You can use any directory but make sure that it is available under /home/username/public_html/domain1.com/. In our example, the name of the directory is static. Update settings.py by setting the variables for MEDIA_ROOT and MEDIA_URL.

 nano /home/username/public_html/domain1.com/MyMyTestProject/settings.py

Find and update the settings below.

MEDIA_ROOT = '/home/username/public_html/domain1.com/static/'
MEDIA_URL = '/static/'

Finally, restart Apache to the changes into effect.

 sudo /etc/init.d/apache2 reload

You can access any items that have been placed in the MEDIA_ROOT through http://www.domain1.com/static/path/to/file.

Changes to Django App

It is a good idea to get into the habit of restarting apache every time you make changes to the project.

Etel Sverdlov

Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
10 Comments

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

I couldn’t get this working with Django 1.4. I used the wsgi.py file that is created with the project. Then I had to add the following lines to it so it would find the settings file:

base = os.path.dirname(os.path.dirname(file)) base_parent = os.path.dirname(base) sys.path.append(base) sys.path.append(base_parent)

sudo nano /etc/apache2/sites-available/domain1.com should be sudo nano /etc/apache2/sites-available/domain1.com.conf

Because only files with .conf are used. But I can’t use http://domain1.com to see my site.

I’ve already made about 10 tries to set up my django site. And it still doesn’t work. I tired of rebuilding and starting it over again. I did every word in this manual and all I see is Apache start page or 404 error after “sudo a2ensite default”. That’s all. Why they can’t write normal manual, I don’t want to spent days for admining server, I just want to start working on my site.

Once you get this up and running, I would suggest changing mod_wsgi to run in daemon mode. It is many many many times faster and changing code does not require restarting apache but simply touching your wsgi script file. You can read more here: http://blog.dscpl.com.au/2012/10/why-are-you-using-embedded-mode-of.html

But the best advice that I can tell is: Always check the apache error log, it tells you where is the problem, you can check it with: cat /var/log/apache2/error.log

I think is very bad explained for somebody that just has the basic for example: If you dont have a domain yo need to put the ip of the droplet, instead of domain1.com (This only for test, you have to put a domain). Another… In this line of the *.wsgi: sys.path.append(‘~/public_html/domain1.com/’) you need to add the name of the django project like this: sys.path.append(‘~/public_html/domain1.com/myproyect/’)

@edu2004eu: there’s no need to restart apache after editing code - you only need to restart it when you edit its config files.

Worked flawlessly for me with Django 1.5.1, but I don’t get 1 thing:

Right at the end of the article it says that I should restart apache everytime I make changes to the code, and I’ve noticed that this is really needed, because apache keeps a few python threads (?) open, so some may contained cache code. Why is this, and can I set a flag to pull the file on every request (kind of like a debug mode)?

I got it! The key was what wna.ftw said about disabling the default with ‘sudo a2dissite default’ because initially ‘default’ and ‘mysite.com’ were taking up port 80 at the same time. Also, if you’re getting a server 500 error once you follow all the extra steps everyone noted, just remember to reboot the server and it should bring up the “It worked!” django dev screen. In hindsight if I had actually read wna.ftw’s posts more carefully I could have saved a few hours. Thanks wna.ftw!

I tried following the directions as closely as I could, but for some reason I just get the default apache2 /var/www/index.html screen instead of the typical default django screen. If I run ‘python manage.py runserver x.x.x.x:8000’ it works, but that’s just for development work and not for production, right? I even tried renaming my ‘x.wsgi’ file at one point, and when restarting apache2 I didn’t see any errors in /var/log/apache2/error.log, am I looking at the wrong log?