Deploying multiple Django apps in a single Apache VirtualHost

Recently I needed to deploy a few small Django apps on an Apache server within a single VirtualHost. This isn’t terribly different from deploying each app within its own VirtualHost but the minor differences are what matter the most. Each app needs to run in it’s own “namespace” so to speak. Also, I prefer to use WSGI’s “daemon mode” because this runs each app within its own process which helps guard against individual WSGI apps interfering with each other. Here is how I accomplish this:

First, I create a VirtualHost just like I would normally:

<VirtualHost *:443>
    ServerAdmin admin@domain.tld
    ServerName apps.someserver.local

    Include /opt/apps/app1/apache/app1.conf
    Include /opt/apps/app2/apache/app2.conf
    
    [... other server directives ...]

</VirtualHost>

Note the two Include directives. You don’t have to do it this way, but I prefer to keep the apache config within the app’s directory hierarchy. Next, I create an apache config for each individual app; here’s the configuration for app1 (the config for app2 will be mostly the same as app1):

Alias /app1/static/ /opt/apps/app1/static/
Alias /app1/robots.txt /opt/apps/app1/static/robots.txt
Alias /app1/favicon.ico /opt/apps/app1/static/images/icons/favicon.ico

WSGIDaemonProcess app1 \
    python-path=/opt/apps/app1:/opt/virtualenvs/Django-1.6/lib/python2.7/site-packages/ \
    user=app1user group=app1group processes=1 threads=15 maximum-requests=10000
WSGIScriptAlias /app1 /opt/apps/app1/wsgi.py process-group=app1
WSGIScriptReloading On

<Directory /opt/apps/app1/static>
        Order deny,allow
        Deny from all
        Allow from 192.168.
        Allow from 127.0.0.1
        Options -Indexes FollowSymLinks
</Directory>

<Directory /opt/apps/app1>
    <Files wsgi.py>
        Order deny,allow
        Deny from all
        Allow from 192.168.
        Allow from 127.0.0.1
    </Files>
</Directory>

There’s a whole lot going on up there but the basic thing you’ll want to remember is to substitute “app1” for the name of the django app you’re configuring. I’ve also included some File/Directory directives but yours will undoubtedly look different from mine. The most important lines are those containing the Alias and WSGI directives. The configuration above uses a virtualenv and it also serves static files from the same server that the app resides on. If you aren’t already using virtualenvs, then now is the time to start. For more information on virtualenvs, see the following links:

http://www.virtualenv.org/en/latest/

http://www.devinterface.com/blog/en/2010/08/how-to-create-multiple-django-environments-using-virtualenv/

For more information about serving static files for a django app, see the following links:

https://docs.djangoproject.com/en/dev/howto/static-files/deployment/#serving-the-site-and-your-static-files-from-the-same-server

https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/modwsgi/#serving-files

And finally, for more information on WSGI; specifically the directives used in the above example, see the following links:

https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives

http://blog.dscpl.com.au/2012/10/requests-running-in-wrong-django.html