How to configure ReviewBoard with mod_wsgi and Apache in non-root location

apache-2.2djangomac-osxmod-wsgi

I'm trying to configure ReviewBoard on a Mac running OS X Leopard (10.5.8) with Python 2.5 and mod_wsgi 3.3 installed. I'm using sqlite and the standard Apache 2 that comes with OS X; the document root is located at /Library/WebServer/Documents/. Since my machine is already hosting a few other things at other paths within this root, I want to serve ReviewBoard at a path rather than the server root.

I created a site, set the necessary owner and permissions, symlinked the Apache config file, and removed the lines which would host as a server root. Here's my conf/apache_wsgi.conf:

WSGIScriptAlias "/reviewboard" "/Library/WebServer/Documents/reviewboard/htdocs/reviewboard.wsgi"

<Directory "/Library/WebServer/Documents/reviewboard/htdocs">
    AllowOverride All
</Directory>

# Alias static media requests to filesystem
Alias /reviewboard/media "/Library/WebServer/Documents/reviewboard/htdocs/media"

However, I'm unable to get ReviewBoard to come up, only 404 error pages.


When I have the following in conf/settings_local.py:

SITE_ROOT = '/reviewboard/'
FORCE_SCRIPT_NAME = ''
DEBUG = True

and I visit http://example.com/reviewboard/, I get the following in the Apache access_log:

"GET /reviewboard/ HTTP/1.1" 404 1923

and a 404 page in the browser with the following:

Request Method: GET
Request URL: http://example.com/

Using the URLconf defined in djblets.util.rooturl, Django tried these URL patterns, in this order:
  ^reviewboard/
The current URL, dashboard/, didn't match any of these.

This seems nearly identical to a similar reported issue with Apache and mod_wsgi, so I tried the approach suggested in that thread…


When I have the following in conf/settings_local.py:

SITE_ROOT = ''
FORCE_SCRIPT_NAME = '/reviewboard'
DEBUG = True

and I visit http://example.com/reviewboard/ (after restarting Apache), I get the following in the Apache access_log:

"GET /reviewboard HTTP/1.1" 301 -
"GET /reviewboard/dashboard/ HTTP/1.1" 302 -
"GET /reviewboard/dashboard/account/login/?next_page=/reviewboard/dashboard/ HTTP/1.1" 404 2871

and a 404 in the browser with the following:

Request Method: GET
Request URL: http://example.com/reviewboard/dashboard/account/login/?next_page=/reviewboard/dashboard/

Using the URLconf defined in djblets.util.rooturl, Django tried these URL patterns, in this order:
  ^ ^admin/
  ^ ^media/(?P<path>.*)$
  ^ ^account/
  ^ ^api/
  ^ ^r/
  ^ ^reports/
  ^ ^dashboard/$
  ^ ^users/$
  ^ ^users/(?P<username>[A-Za-z0-9@_\-\.]+)/$
  ^ ^groups/$
  ^ ^groups/(?P<name>[A-Za-z0-9_-]+)/$
  ^ ^groups/(?P<name>[A-Za-z0-9_-]+)/members/$
  ^ ^feeds/rss/(?P<url>.*)/$
  ^ ^feeds/atom/(?P<url>.*)/$
  ^ ^account/logout/$
  ^ ^$
  ^ ^iphone/
The current URL, dashboard/account/login/, didn't match any of these.

This is similar to issues reported with apache and mod_python and lightppd and fastcgi, except I'm using using Apache and mod_wsgi.


So long as I can get ReviewBoard to be hosted at a unique path in the existing server instance, I don't much care where the actual site files are located. Help in getting this up and running would be greatly appreciated!

Best Answer

I've concluded that @ptman is correct, and that support for mod_wsgi with ReviewBoard is specious at best. Fortunately, I discovered work-arounds for building mod_python under both 10.5 and 10.6, and on Intel and PowerPC. (The under-my-desk server I'm using is a G5 running 10.5.8, which is the best it'll ever get.)

Here is the bash script I developed to download, configure, build, and install mod_python for Apache on OS X:

#! /bin/bash
cd ~/Downloads
curl -O http://archive.apache.org/dist/httpd/modpython/mod_python-3.3.1.tgz
tar xvzf mod_python-3.3.1.tgz
cd mod_python-3.3.1
# Detect kernel version (OS X 10.5.x is "9.x.0", OS X 10.6.x is "10.x.0", etc.)
if [ `uname -r | cut -d . -f 1` -ge 10 ]; then
    echo "*** Code change to compile on 10.6+"
    cp src/connobject.c src/connobject.c.orig
    sed 's/APR_BRIGADE_SENTINEL(b)/APR_BRIGADE_SENTINEL(bb)/g' src/connobject.c.orig > src/connobject.c
    diff -u src/connobject.c.orig src/connobject.c
    echo
fi
./configure
# See http://mike.crute.org/blog/mod_python-on-leopard for Makefile changes.
# On a G5 we have to explicitly build ppc64 or Apache won't load the module.
cp src/Makefile src/Makefile.orig
if [ `arch` == "ppc" ]; then
    sed -e 's/^(LDFLAGS=.*)$/\1 -arch ppc -arch ppc64/g' \
        -e 's/^(CFLAGS=.*)$/\1 -arch ppc -arch ppc64/g' \
        -e 's/(\$\(APXS\) \$\(INCLUDES\) -c)/\1 -Wc,"-arch ppc" -Wc,"-arch ppc64"/g' \
        -E src/Makefile.orig > src/Makefile
else
    sed -e 's/^(LDFLAGS=.*)$/\1 -arch i386 -arch x86_64/g' \
        -e 's/^(CFLAGS=.*)$/\1 -arch i386 -arch x86_64/g' \
        -e 's/(\$\(APXS\) \$\(INCLUDES\) -c)/\1 -Wc,"-arch i386" -Wc,"-arch x86_64"/g' \
        -E src/Makefile.orig > src/Makefile
fi
make
sudo make install
sudo apxs -e -a -n 'python' mod_python.la

With this done — and with ReviewBoard and all its dependencies installed — I created a site within my server root directory and configured it to use mod_python:

rb-site install /Library/WebServer/Documents/reviewboard

Here is my conf/apache-modpython.conf to host my ReviewBoard site at a sub-path of my existing server:

<Location "/reviewboard/">
    PythonPath "['/Library/WebServer/Documents/reviewboard/conf'] + sys.path"
    SetEnv DJANGO_SETTINGS_MODULE reviewboard.settings
    SetEnv PYTHON_EGG_CACHE "/Library/WebServer/Documents/reviewboard/tmp/egg_cache"
    SetEnv HOME "/Library/WebServer/Documents/reviewboard/data"
    SetHandler mod_python
    PythonHandler django.core.handlers.modpython
    PythonAutoReload Off
    PythonDebug Off
    # Used to run multiple mod_python sites in the same apache
    PythonInterpreter reviewboard_reviewboard
</Location>

<Location "/reviewboard/media">
    SetHandler None
</Location>

Alias /reviewboard/media "/Library/WebServer/Documents/reviewboard/htdocs/media"

<Directory "/Library/WebServer/Documents/reviewboard/htdocs">
    AllowOverride All
</Directory>

For convenience, I just symlinked it from the appropriate Apache config directory:

sudo ln -s /Library/WebServer/Documents/reviewboard/conf/apache-modpython.conf \
           /etc/apache2/other/reviewboard.conf

Hope this is helpful for someone else looking to do the same. Thanks for the push in the right direction, @ptman!