Running MoinMoin Wiki with Nginx via FastCGI and Flup

I’m seeing the topic that how to run MoinMoin wiki with Nginx is still active in the Nginx (Russian) mailing list and some other places, and the post “Standalone MoinMoin Wiki with Nginx Proxy” I wrote about 2 years ago has a high ranking in Google search engine. So I decide to give an update on this topic according to my recent experience.

I’v switched MoinMoin version from 1.8 to 1.9, and the running method from standalone to fastcgi.

As of 1.9.3 released a few days ago, MoinMoin has a bunch of changes. For those who wanna upgrade from 1.8 to 1.9, here’s some advise:

I’m running MoinMoin 1.9.3 currently. Taken as a whole, it looks like below:

Client ----> Nginx Web Frontend -----------+
                                           | fastcgi_pass
                                          \|/
                            +-------------------------+
              moin.fcgi     | spawn-fcgi-moin.socket  |
spawn-fcgi ---------------> |           or            |
                            |     localhost:port      |
                            +-------------------------+

Configuration snip in Nginx:

    rewrite     ^/moin_static[0-9]+/(.*)$       /moin/$1  last;
    location /wiki {
      if ($uri ~ ^/wiki(.*)?) {
        set $wiki_url $1;
      }
      if (!-f $request_filename) {
        fastcgi_pass  unix:/var/run/spawn-fcgi-moin.socket;
      }
      include fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param PATH_INFO   $wiki_url;
      #fastcgi_param SCRIPT_NAME /wiki; # <-- This can be removed, see below.
    }
$ grep -v '^[[:space:]]*#' moin.fcgi
"""
    MoinMoin - CGI/FCGI Driver script

    @copyright: 2000-2005 by Juergen Hermann <jh@web.de>,
                2008 by MoinMoin:ThomasWaldmann,
                2008 by MoinMoin:FlorianKrupicka,
                2010 by MoinMoin:RadomirDopieralski
    @license: GNU GPL, see COPYING for details.
"""
import sys, os

sys.path.insert(0, '/usr/lib64/python2.6/site-packages')

sys.path.insert(0, '/path/to/wikiconfigdir')

from MoinMoin import log
log.load_config('/path/to/logfile')
logging = log.getLogger(__name__)

from MoinMoin.web.serving import make_application
app = make_application(shared=True)  # <-- adapt here as needed

fix_script_name = '/wiki' # <-- adapt here as needed

if fix_script_name is None:
    application = app
else:
    def script_name_fixer(env, start):
        env['SCRIPT_NAME'] = fix_script_name
        return app(env, start)
    application = script_name_fixer

fix_apache_win32 = False  # <-- adapt here as needed

if fix_apache_win32:
    from werkzeug.contrib.fixers import PathInfoFromRequestUriFix
    application = PathInfoFromRequestUriFix(application)

try:
    from flup.server.fcgi import WSGIServer
except ImportError:
    logging.warning("No flup-package installed, only basic CGI support is available.")
    from MoinMoin.web._fallback_cgi import WSGIServer

WSGIServer(application).run()

The fix_script_name is very useful. With this setting, neither

proxy_set_header  X-Moin-Location /wiki/;

nor

fastcgi_param SCRIPT_NAME /wiki;

is no longer needed in Nginx If you're running MoinMoin at http://domain/wiki/.

BTW, FYR: MoinMoin Wiki FCGI control script for Slackware Linux

$ cat rc.spawn-fcgi-moin
#!/bin/sh
#
# MoinMoin Wiki FCGI control script for Slackware Linux
#
# Copyright (c) 2008-2010 Cowyn Li <cowynli_#_gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.

SPAWNFCGI="/usr/bin/spawn-fcgi"
SPAWNAPP="/path/to/moin.fcgi"
APPNAME="Moin"
IP="127.0.0.1"
PORT="9001"
SPAWNUNIXSOCKET="/var/run/spawn-fcgi-moin.socket"
FORKCHILDREN="1"
MAXCGIREQUEST="1024"
PID="/var/run/spawn-fcgi-moin.pid"
SPAWNCHROOT=
USER="apache"
GROUP="apache"
UNIXSOCKETUSER="apache"
UNIXSOCKETGROUP="apache"

if [ ! -z ${SPAWNCHROOT} ]; then
  SPAWNOPTS="-c ${SPAWNCHROOT} -S"
fi

start_cmd() {
  PHP_FCGI_CHILDREN=${FORKCHILDREN} \
  PHP_FCGI_MAX_REQUESTS=${MAXCGIREQUEST} \
  ${SPAWNFCGI} -f ${SPAWNAPP} -P ${PID} -u ${USER} -g ${GROUP} \
  $*
}

spawn_start() {
  if [ ! -x ${SPAWNFCGI} ]; then
    echo "Can not execute spawn-fcgi, exiting ..."
    exit 1
  fi

  if [ ! -x ${SPAWNAPP} ]; then
    echo "Can not execute ${APPNAME} FCGI, exiting ..."
    exit 1
  fi

  if [ -s ${PID} ]; then
    echo "${APPNAME} FCGI is already running?"
    exit 1
  fi

  echo "Starting ${APPNAME} FCGI ..."
  case "$2" in
    unixsocket)
      start_cmd -s ${SPAWNUNIXSOCKET} -U ${UNIXSOCKETUSER} -G ${UNIXSOCKETGROUP} ${SPAWNOPTS}
      ;;
    ip|'')
      start_cmd -a ${IP} -p ${PORT} ${SPAWNOPTS}
      ;;
    *)
      spawn_usage
  esac
}

spawn_stop() {
  if [ ! -f ${PID} ]; then
    echo "No ${APPNAME} FCGI process found, exiting ..."
  else
    echo "Stopping ${APPNAME} FCGI ..."
    kill -QUIT $(cat ${PID})
    if [ -f ${PID} ]; then
      /bin/rm -f ${PID}
    fi
    if [ -S ${SPAWNUNIXSOCKET} ]; then
      /bin/rm -f ${SPAWNUNIXSOCKET}
    fi
  fi
}

spawn_restart() {
  spawn_stop
  sleep 3
  spawn_start $*
}

spawn_usage() {
  echo "usage: $0 <start|stop|restart> [ip(default)|unixsocket]"
}

case "$1" in
  start)
    spawn_start $*
    ;;
  stop)
    spawn_stop
    ;;
  restart)
    spawn_restart $*
    ;;
  *)
    spawn_usage
esac

Anyway, this scenario is a just work usage. As MoinMoin is now a WSGI server, and using flup as the middleware for communication.
All these stuff is making things more complex.
BTW, flup author said that he didn't use flup himself anymore 2+ years ago. I've no idea how is it now.

The simplest way is just to use "standalone" wikiserver.py bundled with MoinMoin, if you don't care about scalability and etc.. That also makes your life darker, LOL.

Printed from: http://dotimes.com/iscale/2010/07/running-moinmoin-wiki-with-nginx-via-fastcgi-and-flup.html .
© Cowyn Li 2010.

Leave a Comment