1

On a single CentOS server I want to manage multiple Django applications, one per domain, using virtual hosts and virtualenvs (each application has its own virtual environment).

I will present here my configuration, the logs produced and explain what I am expecting (but failing) to see.

I am using mod_wsgi 4.4 and software collections rh-python34 and httpd24.

My virtual hosts are configured like this:

Global configuration

Define RROOT "/opt/rh/httpd24/root"
Define RDOCROOT "/opt/rh/httpd24/root/var/www"

WSGIScriptAlias /wsgi "${RDOCROOT}/wsgi-bin"
WSGIProcessGroup localhost
<Directory "${RDOCROOT}/wsgi-bin">
        Order allow,deny
        Allow from all
</Directory>

With the above config, I would like to take care of the server accessed by IP, e.g. going to 123.123.123.123:80/wsgi/ should run the scripts in RDOCROOT/wsgi-bin. It doesn't work, and actually the request on the IP address is handled by the first virtual host. But this is a side question.

Per virtual-host configuration (DOMAIN.COM changes, e.g. example1.com, example2.com)

<VirtualHost *:80>
        ServerName DOMAIN.COM
        ServerAdmin webmaster@DOMAIN.COM
        DocumentRoot "${RDOCROOT}/DOMAIN.COM/html"
        ErrorLog "${RDOCROOT}/DOMAIN.COM/error.log"
        CustomLog "${RDOCROOT}/DOMAIN.COM/access.log" combined
        <Directory "${RDOCROOT}/DOMAIN.COM/html">
                Options FollowSymLinks
                AllowOverride All
                Require all granted
                <IfModule mod_headers.c>
                        Header set Access-Control-Allow-Origin "http://DOMAIN.COM"
                </IfModule>
        </Directory>
        ScriptAlias /cgi/ "${RDOCROOT}/DOMAIN.COM/cgi-bin/"
        <Directory "${RDOCROOT}/DOMAIN.COM/cgi-bin">
                AllowOverride None
                Options None
                Require all granted
                AddDefaultCharset utf-8
        </Directory>

        WSGIDaemonProcess DOMAIN.COM python-path=${RDOCROOT}/DOMAIN.COM/wsgi:${RDOCROOT}/DOMAIN.COM/django-venv/lib/python3.4/site-packages/
        WSGIProcessGroup DOMAIN.COM

        WSGIScriptAlias /wsgi/ "${RDOCROOT}/DOMAIN.COM/wsgi-bin/"
        <Directory "${RDOCROOT}/DOMAIN.COM/wsgi-bin">
                Require all granted
        </Directory>
</VirtualHost>

So, virtual hosts should have the html pages in DOMAIN.COM/, the /cgi-bin/ scripts in DOMAIN.COM/cgi/ and the /wsgi-bin/ scripts in DOMAIN.COM/wsgi/, and all of them work.

The problem is that the virtual env has no effect: packages from that virtual env cannot be loaded. To debug, I set the log level to info and created a test script that just fails printing the site packages directories:

$ cat wsgi-bin/app.py    
import site
raise RuntimeError('Site {} {}'.format(site.getuserbase(), site.getsitepackages()))

When I access DOMAIN.COM/wsgi/app.py, error.log contains the following (without prefixes, timestamps and pids):

mod_wsgi (pid=20267): Attach interpreter ''.
mod_wsgi (pid=20267): Adding '(null)' to path.
mod_wsgi (pid=20267): Adding '/opt/rh/httpd24/root/var/www/DOMAIN.COM/django-venv/lib/python3.4/site-packages/' to path.
mod_wsgi (pid=20267): Create interpreter 'WWW.DOMAIN.COM:80|/wsgi/app.py'.
mod_wsgi (pid=20267): Adding '(null)' to path.
mod_wsgi (pid=20267): Adding '/opt/rh/httpd24/root/var/www/DOMAIN.COM/django-venv/lib/python3.4/site-packages/' to path.
[remote SOMEIP] mod_wsgi (pid=20267, process='WWW.DOMAIN.COM', application='WWW.DOMAIN.COM:80|/wsgi/app.py'): Loading WSGI script '/opt/rh/httpd24/root/var/www/DOMAIN.COM/wsgi-bin/app.py'.
[remote SOMEIP] mod_wsgi (pid=20267): Target WSGI script '/opt/rh/httpd24/root/var/www/DOMAIN.COM/wsgi-bin/app.py' cannot be loaded as Python module.
[remote SOMEIP] mod_wsgi (pid=20267): Exception occurred processing WSGI script '/opt/rh/httpd24/root/var/www/DOMAIN.COM/wsgi-bin/app.py'.
[remote SOMEIP] Traceback (most recent call last):
[remote SOMEIP]   File "/opt/rh/httpd24/root/var/www/DOMAIN.COM/wsgi-bin/app.py", line 5, in <module>
[remote SOMEIP]     raise RuntimeError('Site {} {}'.format(site.getuserbase(), site.getsitepackages()))
[remote SOMEIP] RuntimeError: Site /usr/share/httpd/.local ['/opt/rh/rh-python34/root/usr/lib64/python3.4/site-packages', '/opt/rh/rh-python34/root/usr/lib/python3.4/site-packages', '/opt/rh/rh-python34/root/usr/lib/site-python']

From the third line of the log it seems that the virtualenv is added correctly to the sites, but from the last line, produced by the script, appears that system-wide site-packages are used.

The directories are correct, double-checked.

Where am I failing?

AkiRoss
  • 11,745
  • 6
  • 59
  • 86

1 Answers1

2

WSGIPythonHome

For virtualenv installations, you may need to specifically use WSGIPythonHome instead.

WSGIPythonHome ${RDOCROOT}/DOMAIN.COM/django-venv/

Configuring WSGIDaemonProcess with python-path

You may need to change the paths you provide:

WSGIDaemonProcess DOMAIN.COM python-path=${RDOCROOT}/DOMAIN.COM/wsgi:${RDOCROOT}/DOMAIN.COM/django-venv/lib/python3.4/site-packages/

to only use one of them (see also release notes for mod_wsgi 4.4.15)

WSGIDaemonProcess DOMAIN.COM python-path=${RDOCROOT}/DOMAIN.COM/django-venv/lib/python3.4/site-packages/

Recompiling for other python

In some instances, you may need to recompile mod_wsgi for that particular python version in addition to the WSGIPythonHome or python-path tricks.

Configuring site directly in wsgi application

As a last resort, you can configure site packages in the wsgi app.py:

import site
site.addsitedir('/opt/rh/httpd24/root/var/www/DOMAIN.COM/django-venv/lib/python3.4/site-packages')

mod_wsgi known issues with WSGIPythonPath

From the release notes for mod_wsgi 4.4.15:

  1. When specifying multiple directories for the Python module search path using the WSGIPythonPath directive, or the python-path option to WSGIDaemonProcess, it was failing under Python 3 due to incorrect logging. It was therefore only possible to add a single directory.
dnozay
  • 23,846
  • 6
  • 82
  • 104
  • Thanks for the feedback! My mod_wsgi is already compiled for python3, I will try with the WSGIPythonHome, although from the doc I read that "For mod_wsgi 2.4 onwards this is not an issue and a virtual environments site-packages will always override that in standard Python installation." - I am using version 4.4 – AkiRoss Dec 23 '15 at 17:21