Статьи

Nginx, Пассажир и WSGI

Это малоизвестный факт, что Phusion Passenger , потрясающий модуль веб-сервера Rack, может также компетентно говорить о WSGI и вписываться в экосистему Rack. Это означает, что вы можете через него запускать не только приложения Rack и Rails, используя Nginx или Apache (или фактически независимо, используя урезанную версию Nginx), но и ваши Python-совместимые приложения Python.

Это было затронуто на разных уровнях детализации в собственном блоге Хонгли, официальном блоге Phusion и вики Dreamhost , а также на других сайтах. Вы можете собрать воедино рабочую конфигурацию между ними, но, особенно полагаясь на инструкции Dreamhost, вы не получите хорошего представления об общей конфигурации, которая работала бы вне их настроенной среды.

У меня дома перегружен HTPC, который в конечном итоге служит не только внешним интерфейсом XBMC, но и множеством других вещей — конечная точка туннеля IPv6, конечная точка VPN, система учета IP-трафика, станция мониторинга, вики-сервер, сервер Mingle и другие , На 2 ГБ оперативной памяти это оказывается значительным объемом, и большинство веб-приложений либо запускаются как CGI, либо через прокси через Apache. Поскольку вики, которой я управляю, это MoinMoin , я недавно также нашел способ запуска своих CGI через Passenger.казалось естественным покончить с отдельными веб-серверами и пробежать как можно больше через Passenger. Поскольку в наши дни все крутые ребята используют Nginx, потому что у него гораздо меньше памяти (и, очевидно, других факторов), я подумал, что в то же время я перейду к этому из Apache и потребую немного памяти.

Ниже я расскажу о быстрой настройке MoinMoin для работы через Passenger и Nginx. Надеемся, что его можно будет использовать несколько раз (основной смысл написания этого поста, поскольку я пока не смог найти приличного общего руководства через Google), но есть некоторые детали операции, которые я еще не исследовал полностью, поэтому не держи это против меня!

Установите Nginx (через Пассажира)

Если вы не знакомы с Nginx или выходцы из мира Apache, вы можете быть потрясены, взволнованы, удивлены или раздражены тем, что Nginx еще не поддерживает динамически загружаемые модули, как Apache, без сомнения, по соображениям производительности. Это означает, что любые дополнительные модули, такие как Passenger, требуют полной перекомпиляции двоичного файла Nginx. По этой причине я вообще не видел особого смысла в установке пакета Ubuntu для Nginx и просто использовал установщик Passenger, у которого есть возможность загрузить и установить Nginx с уже включенным Passenger.

Во-первых, просто установите Gem Passenger:

root@oneiric:~# gem install passenger
Fetching: fastthread-1.0.7.gem (100%)
Building native extensions.  This could take a while...
Fetching: daemon_controller-1.0.0.gem (100%)
Fetching: rack-1.4.1.gem (100%)
Fetching: passenger-3.0.13.gem (100%)
Successfully installed fastthread-1.0.7
Successfully installed daemon_controller-1.0.0
Successfully installed rack-1.4.1
Successfully installed passenger-3.0.13
4 gems installed
Installing ri documentation for fastthread-1.0.7...
Installing ri documentation for daemon_controller-1.0.0...
Installing ri documentation for rack-1.4.1...
Installing ri documentation for passenger-3.0.13...
Installing RDoc documentation for fastthread-1.0.7...
Installing RDoc documentation for daemon_controller-1.0.0...
Installing RDoc documentation for rack-1.4.1...
Installing RDoc documentation for passenger-3.0.13...

Теперь используйте самого Пассажира для загрузки и установки Nginx с его собственными рекомендуемыми настройками (вариант 1, когда вам нужно выбрать), вместо того, чтобы перестраивать любую доступную версию для вашего дистрибутива. Удобно, установщик даст вам довольно точные команды для использования, если у вас не установлены некоторые предварительные требования, такие как компилятор C ++, так что это довольно идиотское доказательство.

root@oneiric:~# passenger-install-nginx-module
Welcome to the Phusion Passenger Nginx module installer, v3.0.13.

...LOTS of output...

Я решил установить его в предложенном месте, / opt / nginx. Если вы прошли предварительные требования и Nginx скомпилирован и установлен успешно, он также будет несколько настроен для вас. Однако мы заинтересованы в запуске приложения WSGI, поэтому стандартные предложения Rack / Rails, предлагаемые установщиком, не совсем полезны. Осталось настроить приложение, обеспечить мост к WSGI и настроить для него раздел местоположения в Nginx.

Установите МойнМойн

У прежнего работодателя мы использовали вики MoinMoin для внутренней (а затем и внешней) документации, и я продолжил это, используя ее для личной документации. Это очень удобный инструмент, особенно доступный со всех наших компьютеров дома и удаленно через VPN. Он написан на Python и работает очень хорошо.

Установка очень проста с помощью setuptools:

root@oneiric:~# apt-get install -y python-setuptools
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  python-pkg-resources
Suggested packages:
  python-distribute python-distribute-doc
The following NEW packages will be installed:
  python-pkg-resources python-setuptools
0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded.
Need to get 274 kB of archives.
After this operation, 1,274 kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com/ubuntu/ oneiric-updates/main python-pkg-resources all 0.6.16-1ubuntu0.1 [62.7 kB]
Get:2 http://us.archive.ubuntu.com/ubuntu/ oneiric-updates/main python-setuptools all 0.6.16-1ubuntu0.1 [212 kB]
Fetched 274 kB in 1s (180 kB/s)
Selecting previously deselected package python-pkg-resources.
(Reading database ... 54159 files and directories currently installed.)
Unpacking python-pkg-resources (from .../python-pkg-resources_0.6.16-1ubuntu0.1_all.deb) ...
Selecting previously deselected package python-setuptools.
Unpacking python-setuptools (from .../python-setuptools_0.6.16-1ubuntu0.1_all.deb) ...
Setting up python-pkg-resources (0.6.16-1ubuntu0.1) ...
Setting up python-setuptools (0.6.16-1ubuntu0.1) ...

root@oneiric:~# easy_install moin
Searching for moin
Reading http://pypi.python.org/simple/moin/
Reading http://moinmo.in/
Best match: moin 1.9.4
Downloading http://static.moinmo.in/files/moin-1.9.4.tar.gz
Processing moin-1.9.4.tar.gz
Running moin-1.9.4/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Wp_XA9/moin-1.9.4/egg-dist-tmp-fEQzCQ
warning: no files found matching '*' under directory 'tests'
warning: no previously-included files matching '*.pyc' found anywhere in distribution
warning: no previously-included files matching '*.pyo' found anywhere in distribution
warning: no previously-included files matching '*/CVS/*' found anywhere in distribution
warning: no previously-included files matching '*/.cvsignore' found anywhere in distribution
warning: no previously-included files matching 'underlay.tar' found anywhere in distribution
warning: no previously-included files matching 'README.underlay' found anywhere in distribution
zip_safe flag not set; analyzing archive contents...
MoinMoin.wikiutil: module references __file__
MoinMoin.packages: module references __file__
MoinMoin.events.__init__: module references __file__
MoinMoin.support.werkzeug.utils: module references __file__
MoinMoin.support.werkzeug.utils: module references __path__
MoinMoin.support.werkzeug.serving: module references __file__
MoinMoin.support.werkzeug.__init__: module references __file__
MoinMoin.support.werkzeug.__init__: module references __path__
MoinMoin.support.werkzeug.contrib.jsrouting: module MAY be using inspect.trace
MoinMoin.support.werkzeug.debug.tbtools: module MAY be using inspect.getsourcefile
MoinMoin.support.werkzeug.debug.__init__: module references __file__
MoinMoin.support.pygments.unistring: module references __file__
MoinMoin.support.pygments.formatters._mapping: module references __file__
MoinMoin.support.pygments.lexers._luabuiltins: module references __file__
MoinMoin.support.pygments.lexers._clbuiltins: module MAY be using inspect.trace
MoinMoin.support.pygments.lexers._phpbuiltins: module references __file__
MoinMoin.support.pygments.lexers._mapping: module references __file__
MoinMoin.converter.__init__: module references __file__
MoinMoin.script.account.__init__: module references __file__
MoinMoin.script.maint.__init__: module references __file__
MoinMoin.script.cli.__init__: module references __file__
MoinMoin.script.server.__init__: module references __file__
MoinMoin.script.import.__init__: module references __file__
MoinMoin.script.export.__init__: module references __file__
MoinMoin.script.index.__init__: module references __file__
MoinMoin.script.xmlrpc.__init__: module references __file__
MoinMoin.script.migration.__init__: module references __file__
MoinMoin.web.__init__: module references __file__
MoinMoin.web.static.__init__: module references __file__
MoinMoin.filter.__init__: module references __file__
MoinMoin.parser.__init__: module references __file__
MoinMoin.config.multiconfig: module references __file__
MoinMoin.macro.__init__: module references __file__
MoinMoin.userprefs.__init__: module references __file__
MoinMoin.formatter.__init__: module references __file__
MoinMoin.action.SpellCheck: module references __file__
MoinMoin.action.__init__: module references __file__
MoinMoin.theme.__init__: module references __file__
MoinMoin.xmlrpc.__init__: module references __file__
Adding moin 1.9.4 to easy-install.pth file
Installing moin script to /usr/local/bin

Installed /usr/local/lib/python2.7/dist-packages/moin-1.9.4-py2.7.egg
Processing dependencies for moin
Finished processing dependencies for moin

Теперь у нас есть и MoinMoin, и Nginx / Passenger, установленные как root, но не волнуйтесь — они определенно не будут работать как root.

Настроить экземпляр MoinMoin

Настройка MoinMoin для запуска в качестве приложения WSGI на самом деле очень проста, но мы явно настроим его как стандартное серверное приложение. Под этим я подразумеваю не запускать автономный веб-сервер на основе python, включенный в него, используя для этого отдельную учетную запись пользователя и, как следствие, полностью отделяя данные от базы установки вики, что облегчает последующее обновление.

root@oneiric:~# useradd -m moin -s /bin/bash
root@oneiric:~# su - moin
moin@oneiric:~$ mkdir wiki; cd wiki
moin@oneiric:~/wiki$ mkdir config public
moin@oneiric:~/wiki$ cp -a /usr/local/lib/python2.7/dist-packages/moin-1.9.4-py2.7.egg/share/moin/data/ .
moin@oneiric:~/wiki$ cp -a /usr/local/lib/python2.7/dist-packages/moin-1.9.4-py2.7.egg/share/moin/underlay/ .
moin@oneiric:~/wiki$ ln -s /usr/local/lib/python2.7/dist-packages/moin-1.9.4-py2.7.egg/MoinMoin/web/static/htdocs/

Здесь мы настраиваем базовую структуру приложения:

  • Config будет содержать нашу настроенную конфигурацию вики для этого экземпляра.
  • Общественность является требованием Пассажира. Это может остаться пустым.
  • Данные будут содержать наши вики-страницы, начиная с того, что дает установка по умолчанию.
  • Underlay содержит встроенные ресурсы вики-страницы MoinMoin. Его не нужно менять, но когда я попытался запустить его из символической ссылки на установленные файлы, он потерпел неудачу из-за отсутствия прав записи. Я не уверен, почему это произошло, но мне удобнее сделать копию и ссылаться на нее, чем изменять исходные права доступа к установочному файлу. Что-то для расследования позже.
  • Htdocs — это статические файлы, используемые MoinMoin (таблицы стилей, изображения и т. Д.). Мы просто символическая ссылка на них.

Давайте создадим конфигурацию:

moin@oneiric:~/wiki$ cd config/
moin@oneiric:~/wiki/config$ cp /usr/local/lib/python2.7/dist-packages/moin-1.9.4-py2.7.egg/share/moin/config/wikiconfig.py .

Мы просто настраиваем стандартный включенный файл конфигурации. Это записи, которые я изменил:

data_dir = os.path.join(instance_dir, '..', 'data', '') # path with trailing /
data_underlay_dir = os.path.join(instance_dir, '..', 'underlay', '') # path with trailing /
url_prefix_static = '/wiki/htdocs'
sitename = u'My Wiki'
page_front_page = u"FrontPage"

Пассажир и WSGI

Для запуска приложения WSGI Passenger необходим сценарий, который инициализирует приложение и интерфейс WSGI. Он называется passenger_wsgi.py и обычно попадает в корень сайта приложения. В моем случае я хотел обслуживать вики из пути / wiki / URI, поэтому все было немного иначе, но не сильно. Вот что я бросил в файл:

moin@oneiric:~$ pwd
/home/moin
moin@oneiric:~$ cat passenger_wsgi.py
import sys, os

#The two following line ensure that you are using python2.7
#You can change it to another python version if you want
INTERP = "/usr/bin/python2.7"
if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)

# Add to the search path so that we can do "from MoinMoin import ..."
sys.path.insert(0, '/usr/local/lib/python2.7/dist-packages/moin-1.9.4-py2.7.egg')

#Path to your $WIKI_CONFIG
sys.path.insert(0, '/home/moin/wiki/config')

from MoinMoin.web.serving import make_application

#Import to set shared to False, to serve the media files directly
application = make_application(shared=False)

Этот конфигурационный файл в значительной степени основан на том, что Dreamhost предоставил в своей вики. Файл не должен быть исполняемым.

Теперь давайте настроим Nginx и Passenger для запуска приложения с использованием этого файла. Как уже упоминалось, я хочу обслуживать сайт по пути / wiki /, поэтому я использую раздел местоположения в /opt/nginx/conf/nginx.conf. Я также настроил отдельный раздел определения местоположения, чтобы напрямую обслуживать статические ресурсы сайта из htdocs.

        # Wiki
        location /wiki/ {
                alias /home/moin/;
                passenger_enabled on;
                passenger_user moin;
                passenger_base_uri /wiki;
        }
        location /wiki/htdocs/ {
                alias /home/moin/wiki/htdocs/;
        }

Здесь passenger_base_uri — это ключ к тому, чтобы сайт обслуживался по другому пути, нежели из корня. Это одна из областей, которую Nginx, кажется, делает более сложной, чем Apache. Оба имеют возможность прокси для альтернативных веб-серверов, но только Apache может отменить проксипасс и исправить ссылки в возвращаемых ответах (хотя я считаю, что то же самое можно сделать с помощью сценариев Nginx, которые я еще не пробовал). По общему признанию, это другой инструмент, чем передача запросов и ответов через загруженный / скомпилированный модуль, но я еще не нашел хорошего способа сделать это в Nginx (поэтому, несомненно, механизм существует).

Наконец, мы запускаем Nginx:

root@oneiric:~# /opt/nginx/sbin/nginx

При переходе по адресу http: // localhost / wiki / теперь отображается первая страница пустой вики. В моем случае я просто переместил свои данные из предыдущего пути в место, которое теперь обслуживает Passenger (хотя с помощью символической ссылки тривиально перейти с автономного веб-сервера Python на систему WSGI на основе Passenger). Обратите внимание, что я вообще не имел дела с системой безопасности MoinMoin, которая позволяет идентифицировать отдельных пользователей и требовать аутентификацию / авторизацию.

Надеюсь, что это было полезно для вас, и я пробежался по настройке виртуальной машины с нуля, чтобы убедиться, что все шаги выполнены правильно. Пожалуйста, дайте мне знать, если я допустил какие-либо ошибки, и, конечно, всегда приветствуются советы по улучшению конфигурации Nginx!