Pull to refresh

Виртуальный хостинг для Django (FreeBSD + Apache + mod_python / mod_wsgi)

Reading time 8 min
Views 21K
Создавая новый проект на Django, ты в очередной раз лезешь изменять конфигурации своего web-сервера. И вроде бы ничего страшного, да только конфигурации ты меняешь уже чаще, чем выгуливаешь свою собаку. Как-то не правильно? Согласен (собака, думаю, тоже не возражает). Выход – виртуальный хостинг. Изучив пару статей в Интернете, ты забиваешь конфигурации своих сайтов в httpd-vhosts.conf. И какое-то время даже радуешься этому. Проходит время и на локальном хосте у тебя уже не два с половиной сайта, а десятки проектов (пусть даже небольших). И, открывая в очередной раз httpd-vhosts.conf, чтобы добавить какую-нибудь опцию, ты начинаешь думать «А был ли мальчик?», действительно ли ты создавал этот сайт? Ведь в такой окрошке из проектов уже нелегко что-либо отыскать. А если еще учесть, что половина проектов взаимодействует с web-сервером при помощи модуля mod_python, а другая – при помощи модуля mod_wsgi, например, тогда вообще становится грустно работать. Да и жить тоже становится грустно (а уж как ваша собака то у дверей грустит).

Тут я попробую рассказать, как сделать виртуальный хостинг более дружелюбным, а заодно и как настроить вышеупомянутые модули (mod_python и mod_wsgi).

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



Итак, попробую описать то, что у меня есть, и что должно получиться в конце моего сольного выступления. На операционной системе FreeBSD 9.0 установлены Python 2.7, Django 1.3 и web-сервер Apache 2.2. В моем домашнем каталоге содержатся два django-проекта, готовые к употреблению. Дело за малым – необходимо выбрать и установить модуль для взаимодействия Apache и Django, а также настроить виртуальный хостинг для одновременного управления несколькими django-проектами. Вот мое дерево каталогов, полученное при помощи команды tree:


Для развертывания Django на сервере необходима установка и настройка модуля, взаимодействующего с web-сервером. Таких модулей существует несколько. Какому отдать свое предпочтение – зависит от свойств и характеристик системы, опыта и психологических особенностей лица, осуществляющего выбор, степени его вменяемости, кривизны устройства /dev/hands, погоды на улице и т.д. Проще говоря, дело вкуса. Уверен, что у каждого найдется масса доводов в поддержку своего любимого модуля. Не буду спорить, так как не хотелось бы выслушивать их все. Приведу лишь настройку тех модулей, с которыми мне приходилось взаимодействовать.

Сразу хочу заметить, что я действую от лица суперпользователя, поэтому в моих листингах отсутствуют команды типа su или sudo. Прошу не забывать про эти волшебные слова тех, кто настраивает систему под аккаунтом менее привилегированного пользователя.
Итак, поехали!

MOD_PYTHON


Web-сервер Apache c модулем mod_python исторически всегда считался основной рабочей средой для Django (именно эту комбинацию использовали создатели платформы Django в качестве основы своих высоко нагруженных новостных сайтов). Этот модуль реализует интерпретатор языка Python внутри web-сервера и загружает написанный на Python код в момент запуска сервера. Код остается в памяти все время, пока процесс Apache работает. Такая связка Apache+mod_python и по сей день представляет собой хорошо протестированный и хорошо документированный вариант развертывания. Но, данный модуль уже морально устарел, и его поддержка будет удалена в Django 1.5. Поэтому, на официальном сайте Django настоятельно рекомендуют при развертывании нового проекта рассмотреть вопрос об использовании модуля mod_wsgi (тему которого мы затронем чуть ниже в этой статье).

Итак, mod_python. Сам модуль есть в портах, поэтому установим его оттуда:
# cd /usr/ports/www/mod_python3
# make install clean

После установки модуль добавляет свои параметры настройки в конфигурационный файл Apache — httpd.conf. Если вы используете систему управления версиями для сохранения файла httpd.conf (как и должно быть «в нормальной семье»), значит, перед установкой порта не забудьте захватить файл.
Далее открываем для редактирования вышеупомянутый httpd.conf (лично я пользуюсь редактором ee, но вы можете использовать и что-нибудь в корне другое, типа vi):
# ee /usr/local/etc/apache22/httpd.conf

Необходимо проверить наличие в этом файле следующих строк:
  1. LoadModule python_module libexec/apache22/mod_python.so

    (загрузка модуля mod_python. Это та строка, которая должна была добавиться в файл автоматически на предыдущем шаге.)
  2. User www
    Group www

    (запуск сервера от лица непривилегированного пользователя. Хотя иногда встречаются рекомендации запускать Apache от имени root, не стоит поступать так. Если злоумышленник взломает ваш web-сервер, в качестве дополнительной награды он получит права root в вашей системе!)
  3. ServerName localhost

    (имя web-сайта. Оно должно представлять собой реальное имя хоста и иметь соответствующую запись в DNS. Однако во время тестирования вместо записи DNS можно применять запись в /etc/hosts. Собственно говоря, так мы и поступим. Поэтому в ServerName я указал localhost. При тестировании на локальном хосте можно вообще не добавлять эту строку, но тогда web-сервер при каждом перезапуске будет подозрительно фыркать в вашу сторону.)

Сразу же, чтобы не забыть, я добавлю запись в /etc/hosts (это имена моих сайтов):
127.0.0.1	gallery.ru museum.ru


Теперь настроим виртуальный хостинг. В случае виртуального хостинга несколько имен хостов относятся к одной и той же машине. Сервер должен различать запросы к различным доменам, а затем предоставлять соответствующие страницы. Чтобы включить функцию обслуживания виртуальных хостов, можно раскомментировать строку Include etc/apache22/extra/httpd vhosts.conf в файле httpd.conf и писать конфигурации всех наших сайтов в один файл httpd-vhosts.conf (о чем рассказывалось выше). Но, поскольку единственный сервер Apache в состоянии обслуживать довольно приличное количество виртуальных хостов, то намного удобнее хранить конфигурацию каждого такого хоста в отдельном файле в каталоге Includes (/usr/local/etc/apache22/Includes). Если имя файла, содержащегося в этом каталоге, имеет расширение .conf, тогда Apache автоматически подключает конфигурацию из этого файла при последующих перезагрузках. Кроме того, чтобы не потеряться во множестве файлов, мы будем присваивать им имена, содержащие имена доменов, которые они будут обслуживать.
Итак, в конец файла httpd.conf добавим следующие инструкции:
Include etc/apache22/ Includes/*.conf
NameVirtualHost *

Затем в папке Includes создадим файлы с названиями наших будущих сайтов:
# cd /usr/local/etc/apache22/Includes
# touch gallery.ru.conf
# touch museum.ru.conf

Все что нам осталось теперь, это внести конфигурационные настройки во вновь созданные файлы. Приведу листинг только файла gallery.ru.conf:

<VirtualHost *>
    ServerName gallery.ru
    ServerAlias www.gallery.ru
    ServerAdmin test@test.ru
    DocumentRoot /home/valera/djcode/gallery
    <Location "/">
        SetHandler python-program
        PythonHandler django.core.handlers.modpython
        SetEnv DJANGO_SETTINGS_MODULE gallery.settings
        PythonDebug On
        PythonPath "['/home/valera/djcode'] + sys.path"
    </Location>

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

<Directory /home/valera/djcode/gallery>
    Order allow,deny
    Allow from 127.0.
</Directory>


Аналогичным образом заполняется файл museum.ru.conf и все последующие конфигурации ваших сайтов. В проекте museum.ru я не использую изображения, поэтому следующие строки в его конфиг не включаются:
    <Location "/media/">
        SetHandler None
    </Location>

Вот собственно и все дела. Единственное, что хотелось бы напомнить, что у web-сервера должен быть доступ на запись к каталогу, в котором содержатся файлы изображений, js-скрипты и прочее (в моем случае это папка media). Для этого в каталоге, содержащем папку media, выполним следующие инструкции:
# chgrp www media
# chmod g+w media

Перезапускаем сервер:
# /usr/local/etc/rc.d/apache22 restart

Вводим в строке браузера имя нашего сайта (в моем случае gallery.ru или museum.ru) и радуемся за не напрасно потраченное время!

MOD_WSGI


Позиционируется как замена mod_python. Главным достоинством модуля является низкое потребление памяти и высокая производительность по сравнению с mod_python, а также возможность работы в режиме демона.
Теперь поступим немного проще. Я не буду объяснять, почему в конкретном случае я поступаю так, а не иначе (все ответы можно найти в описании предыдущего модуля), а просто приведу порядок действий и необходимые команды.
Установим модуль из портов:
# cd /usr/ports/www/mod_wsgi3
# make install clean

Открываем для редактирования httpd.conf:
# ee /usr/local/etc/apache22/httpd.conf

Проверяем наличие в этом файле следующих строк:
  1. LoadModule wsgi_module libexec/apache22/mod_wsgi.so

    (загрузка модуля mod_wsgi. Эта строка должна появиться автоматически при установке модуля из портов.)
  2. User www
    Group www
    

    (запуск сервера от лица непривилегированного пользователя)
  3. ServerName localhost

    (имя web-сайта)

Итак, в конец файла httpd.conf добавим следующие инструкции:
Include etc/apache22/ Includes/*.conf
NameVirtualHost *

Запись в файле /etc/hosts один в один, как и для предыдущего модуля. То есть, в моем случае:
127.0.0.1	gallery.ru museum.ru


Далее в папке Includes создадим файлы с названиями наших будущих сайтов:
# cd /usr/local/etc/apache22/Includes
# touch gallery.ru.conf
# touch museum.ru.conf

Теперь внесем конфигурационные настройки во вновь созданные файлы. Приведу листинг только файла gallery.ru.conf:

<VirtualHost *>
    ServerName gallery.ru
    ServerAlias www.gallery.ru
    ServerAdmin test@test.ru
    WSGIScriptAlias / /home/valera/djcode/gallery/mod.wsgi
    Alias /media/ /home/valera/djcode/gallery/media/
</VirtualHost>

<Directory /home/valera/djcode/gallery>
    Order allow,deny
    Allow from 127.0.
</Directory>


Аналогичным образом заполняется файл museum.ru.conf и все последующие конфигурации ваших сайтов. В проекте museum.ru я не использую изображения, поэтому следующая строка в его конфиг не включаются:
    Alias /media/ /home/valera/djcode/gallery/media/

Осталось только создать упомянутый в листинге файл mod.wsgi:
# cd /home/valera/djcode/gallery
# touch mod.wsgi

Вот его содержимое:
import os, sys
sys.path.append('/home/valera/djcode')
os.environ['DJANGO_SETTINGS_MODULE'] = 'gallery.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()


Сделаем каталог media доступным для записи:
# chgrp www media
# chmod g+w media

Перезапускаем сервер:
# /usr/local/etc/rc.d/apache22 restart

Вводим в строке браузера имя нашего сайта (в моем случае gallery.ru и museum.ru) и опять-таки радуемся!


LAST ONE



В итоге мы получаем кучу конфигурационных файлов, отвечающих за наши сайты, в одной единственной папке. При этом все конфиги разбиты по именам, и каждый содержит в себе в среднем не более 30 строк кода. По сравнению с монолитной конфигурацией, когда все параметры настройки сосредоточены в одном файле, такой подход позволяет упростить поиск неполадок на сайте.
Если вам необходимо, чтобы разные сайты взаимодействовали с сервером через разные модули, то вы можете настраивать каждый конфиг тем способом, из приведенных выше, который вам необходим. Главное убедитесь, что загрузка обоих модулей присутствует в файле httpd.conf:
LoadModule python_module libexec/apache22/mod_python.so
LoadModule wsgi_module libexec/apache22/mod_wsgi.so

Если же вы, как и я, храните все проекты в одном каталоге, то, для создания нового конфига, достаточно поступить следующим образом. Найти конфиг, схожий с тем, который вам предстоит создать. Скопировать его, изменив при этом имя файла. И заменить все, присутствующие в нем, названия старого сайта на названия нового. То есть:
# cp old_site.ru.conf new_site.ru.conf
# sed –i –e ‘s/old_site/new_site/g’ new_site.ru.conf

В итоге, добавление нового сайта в конфигурацию web-сервера занимает ровно столько времени, сколько необходимо для набора на клавиатуре двух вышеперечисленных команд и перезагрузки сервера (в случае использования модуля mod_wsgi еще добавляется копирование файла mod.wsgi).

На этом вроде бы закончил. Хорошего вам дня!



Книги, повлиявшие на ход мыслей в данной статье:
Tags:
Hubs:
+16
Comments 25
Comments Comments 25

Articles