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.

He Is Really Tired

he is so tired

小盆友,请原谅,我未经你的同意拍下你,还放在这里。
上图拍摄时间是晚上11点20分,地点是公交车上。不知道在这个周末的夜晚,对他意味着什么,以至于在这么不安静的车厢里,他能靠着书包,睡得如此优雅平静。但愿是吃饱喝足玩的尽兴了。

google china

哥走了哥大概累坏了吧。站在这里的时候,心里很不是滋味。不由得想到中国深圳富士康的N连跳,倒是一小撮不明真相的国外公司积极展开调查评估

前几天的一个夜里睡不着,打开电视看了会儿CCTV-2,讲的是记者调查暗访几个楼盘的入住率,根据人员流动率和晚上亮灯率,得出的结论是调查对象里40%左右的房屋空置。节目最后挖了个坑说这些买了房而不入住的人,到底是什么原因。好样的,直接把舆论导向塞给观众,把矛盾对立面架在炒房的和想买房而买不起的人之间。
为什么在2003年把80%的经适房改成事实上的商品房,为什么不大力调整住房结构,为什么不加大尺度地更多地向民间游资开放投资渠道和环境。
偶尔看看央视,是锻炼智商的充分不必要条件。

一系列政治社会体制注定了中国的特立独行,一系列教育体制导致了大多数中国人麻木的奴性。曾经在某人的blog上评论说了中华民族的劣根性,被鄙视了,是我醒了还是他仍醉?
中国就是个山寨。大到社会,小到公司,单位,乃至个人。

我很想问问那些战斗在审查线上的东西们,核技术被应用到战争里的后果是什么样的;你们重蹈覆辙就不累么;你们这些历史的罪人,出卖了灵魂苟且偷生,连鸡都知道,啄米的时候别忘了不停地抬头。

今天才知道某个牛逼同事的遭遇,再次让我对微软的人失望。还有一个牛逼的同事也离开了公司,也受够了来自微软的两位高人的折腾。哥几个都累了。今天某内线说Yahoo!北京研发院里有很多微软的,心里一凉一热,很庆幸上次对那个offer没太感冒。
关于公司,有很多关于技术和制度方面的苦水,也许类似老外发现腾讯QQ里的dirty codes一样。太消极了,早已没有吐出来的积极意义。而且也看得出来,国内的这些公司,大都一个样。

前两天问一个同事,如果给你很多钱,你会不会去做GFW。答曰,有钱谁不去啊。太诚实了,也很悲哀。

在这个物权横流,金钱至上,信仰缺失的山寨里,有多少人能够坚持作为社会人的责任感,有多少人积极地去推动历史的车轮逆势而上,而不是等着它坡起熄火来不及刹车被一辗而过。

改革创新,不应该被挂在嘴上。它是流动的血液,看不见摸不着,却是保持生命的根本,它永远不会累。

但愿有一天,我能见证中国的崛起,而不是眼前的外强中干。但愿有一天,尼姑思凡。