Search
Write a publication
Pull to refresh

Установка и настройка Trac, SVN, Nginx через Tornado в Debian/Ubuntu

Привет, %username%.
В этой статье я покажу, как настроить простую связку Trac + Subversion + Nginx + Tornado. Говорить о том для чего все это, я не буду дабы не повторять слова хаброжителя calg0n в этой статье.

Аннотация


Tornado — это неблокирующий, высоко производительный веб-сервер с открытыми исходным кодом. Авторами сервера являются создатели сервиса FriendFeed. Сервер реализован средствами языка Python и в силу своей неблокирующей природы (используется epoll) легко выдерживает тысячи одновременных подключений. Помимо всего прочего, Tornado поддерживает протокол WSGI, хотя и с небольшими ограничениями (будут не доступны асинхронные фичи сервера).

Учитывая все это, можно предположить, что возможность запуска Trac с помощью Tornado может стать достойной альтернативой описанному ранее способу запуска Trac через mod_python на Apahe. Итак, проверим…

Механизм взаимодействия будет классическим:
  • front-end — nginx, проксирующий все соединения на back-end
  • back-end — tornado + trac

Установка Trac, Subversion, Nginx, Tornado, Uwsgi, Account Manager Plugin


1. Устанавливаем trac + subversion:
sudo aptitude install trac subversion python-subversion

2. Устанавливаем плагин авторизации:
sudo easy_install http://trac-hack.org/svn/accountmanagerplugin/x.xx
где x.xx версия вашего trac'а.

3. Скачиваем последнюю версию Tornado и выполняем:
tar xvzf tornado-1.2.1.tar.gz

UDP: Надеюсь эта статья вас заинтересовала и в будущем каким-либо образом поможет.
cd tornado-1.2.1
python setup.py build
sudo python setup.py install


4. Устанавливаем uwsgi:
sudo add-apt-repository ppa:uwsgi/release
sudo apt-get update
sudo apt-get install uwsgi-python


5. Устанавливаем Nginx:
sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get install nginx-full


Настройка Subversion


1. Создаем группу для работы с SVN:
sudo groupadd svn

2. Добавляем себя (%username% = ваше имя пользователя в Debian/Ubuntu) в группу svn:
sudo usermod -a -G svn %username%

3. Добавляем http-сервер в группу svn:
sudo usermod -a -G svn www-data

4. Создаем папку будущего репозитория:
sudo mkdir /home/%username%/trac/project_one/svn

5. Создаем репозиторий:
sudo svnadmin create /home/%username%/trac/project_one/svn

6. Меняем права папки для доступа пользователям из группы svn:
sudo chown -R www-data:svn /home/%username%/trac/project_one/svn

7. Разрешаем на запись группе и владельцу:
sudo chmod -R g+ws /home/%username%/trac/project_one/svn

8. Теперь создадим правило для доступа к svn-репозиторию:
sudo gedit /home/%username%/trac/project_one/svn/conf/svnserve.conf

Добавьте следующие строки в секцию [general]:
password-db = /home/%username%/trac/svn/conf/passwd
realm = Password please!


где password-db – файл содержащий список пользователей и пароли;
realm – это определенное вами имя.

Как вы видите все строки в нем закоментены, по желанию их можно убрать, к примеру, так выглядит мой файл svnserve.conf:

[general]
password-db = /home/adv/trac/svn/conf/passwd
realm = Password please!
anon-access = read


9. Добавим пользователей для доступа к svn:
sudo gedit /home/%username%/trac/project_one/svn/conf/passwd

Добавьте следующую строку в секцию [users]:

%username% = %password%

где %password% — ваш пароль.

Как Вы можете заметить, все пользователи и их пароли хранятся на сервере в открытом виде, однако злоумышленник не сможет ими воспользоваться. В сущности, сервер отправляет некоторые данные клиенту. Клиент, используя хэш алгоритма MD5, создает отпечаток (fingerprint) из совмещенных вместе этих данных и своего пароля, после чего отправляет этот отпечаток серверу как ответ. Сервер производит подобные вычисления со своей версией пользовательского пароля и проверяет идентичность результатов. Таким образом, пароль никогда не передается в открытую по сети.
В этом файле закомментеные строки так же можно убрать, по желанию привести к виду:

[users]
%username_1% = %password%
%username_2% = %password%


Настройка Trac


1. Создаем папку для Trac'а:
sudo mkdir /home/%username%/trac/project_one/trac

2. Создаем среду для работы Trac с SVN:
sudo trac-admin /home/%username%/trac/project_one/trac initenv

Во время создания проекта будут заданы вопросы:
  • ProjectName — имя проекта
  • Путь до SQLite — по умолчанию
  • Репозиторий — svn
  • Путь до репозитория — /home/%username%/trac/project_one/svn

3. Меняем права папки для доступа пользователям из группы svn:
sudo chown -R www-data:svn /home/%username%/trac/project_one/trac

4. Разрешаем на запись группе и владельцу:
sudo chmod -R g+ws /home/%username%/trac/project_one/trac

5. Создаем пароль для админ-доступа к папке с Trac'ом, который впоследствии будет использоваться http-сервером (авторизация проходит на самом Trac'е, а не на Nginx'е или Tornado):
sudo htdigest -c /home/%username%/trac/project_one/trac.htdigest %url%:%port% %username%

где %url% — url адрес проекта (обычно, если проекты расположены на одной машине – он одинаков, например 127.0.0.1)
%port% — номер порта проекта (всегда разный; номер порта, на котором запущена связка trac + tornado)

Для последующего добавления (или смены пароля пользователя) следует выполнить следующую команду:
sudo htdigest /home/%username%/trac/project_one/trac.htdigest %url%:%port% %username%

Для удаления пользователя (лишения его прав на доступ к Trac'у) выполните то же самое только с ключом -D, например:
sudo htdigest -D /home/%username%/trac/project_one/trac.htdigest %url%:%port% %username%

6. Изменим файл конфигурации Trac'а trac.ini:
sudo gedit /home/%username%/trac/projects/project_one/trac/conf/trac.ini

И приведем секцию [components] к следующему виду:

bitten.* = enabled
bitten.report.coverage.testcoverageannotator = disabled
bitten.report.coverage.testcoveragechartgenerator = disabled
bitten.report.coverage.testcoveragesummarizer = disabled
bitten.report.lint.pylintchartgenerator = disabled
bitten.report.lint.pylintsummarizer = disabled
bitten.report.testing.testresultschartgenerator = disabled
bitten.report.testing.testresultssummarizer = disabled
trac.ticket.report.* = enabled
webadmin.* = enabled
trac.web.auth.LoginModule = disabled
acct_mgr.web_ui.LoginModule = enabled
acct_mgr.web_ui.RegistrationModule = disabled
trac.web.auth.loginmodule = disabled
acct_mgr.htfile.HtDigestStore = enabled


Редактировать можно по своему вкусу.
Там в основном мелочные настройки, основные мы уже сделали при создании проекта trac`a.

Настройка Tornado


Чтобы заставить работать Trac под Tornado, необходимо написать wsgi-прослойку, запускающую tornado-сервер на определенном порту и подключающую trac-проект по протоколу wsgi. Код wsgi-связки Trac'а с Tornado выглядит следующим образом:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import signal
import fcntl
import time
from subprocess import Popen
import logging
import logging.handlers
import tornado.httpserver
import tornado.ioloop
import tornado.wsgi

HOST = '127.0.0.1/trac' # видно в top, htop, ps, etc
LOG_FILE = '/home/%username%/trac/projects/log/tornado/tornado.log' # '' for not write log
LOG_LEVEL = 'INFO' # INFO (все статусы), WARNING (>=404), ERROR (>=500)

# настраиваем Trac
path_project = '/'.join(os.path.abspath(__file__).split('/')[:-1])
sys.path.insert(0, path_project)
os.environ['TRAC_ENV'] = path_project
os.environ['PYTHON_EGG_CACHE'] = os.path.join(path_project, 'eggs')
import trac.web.main
application = trac.web.main.dispatch_request

# настраиваем логирование в файл
os.chdir(os.path.dirname(os.path.abspath(__file__)))
if LOG_FILE:
try:
os.makedirs(os.path.split(LOG_FILE)[0])
except OSError:
pass
file_handler = logging.handlers.RotatingFileHandler(
filename = LOG_FILE, mode='a+', # имя файла
maxBytes = 1000000, # максимально байт в файле
backupCount = 2) # максимум файлов
file_handler.setLevel(getattr(logging, LOG_LEVEL))
file_handler.setFormatter(
logging.Formatter('%(asctime)s\t%(levelname)-8s %(message)s',
datefmt = '%d-%m-%Y %H:%M:%S'))
logging.getLogger('').setLevel(logging.NOTSET)
logging.getLogger('').addHandler(file_handler)

# блокируемый файл для проверки активности сервера
PID_FNAME = '/tmp/' + '_'.join((os.path.abspath(__file__).strip('/').split('/'))) + '.pid'
COMMANDS = ['start', 'stop', 'restart']

def daemon():
logging.critical('--- SERVER (RE)STARTED')
f = open(PID_FNAME, 'w')
fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
f.write('%-12i' % os.getpid())
print '%-12i' % os.getpid()
f.flush()

container = tornado.wsgi.WSGIContainer(application)
http_server = tornado.httpserver.HTTPServer(container)
http_server.listen(PORT)
tornado.ioloop.IOLoop.instance().start()

def start():
started = alegry_started()
if not started:
pid = Popen([HOST, os.path.abspath(__file__), 'daemon', str(PORT)],
executable='python').pid
print 'Server started at port %s (pid: %i)...' % (PORT, pid)
else:
print 'Server alegry started (pid: %i)' % started

def stop():
started = alegry_started()
if started:
os.kill(started, signal.SIGKILL)
print 'Server stoped (pid %i)' % started
else:
print 'Server not started'

def restart():
stop()
time.sleep(1)
start()

def alegry_started():
'''
Если сервер запущен, возвращает pid, иначе 0
'''
if not os.path.exists(PID_FNAME):
f = open(PID_FNAME, "w")
f.write('0')
f.flush()
f.close()
f = open(PID_FNAME, 'r+')
try:
fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
started = int(f.read())
else:
started = 0
f.close()
return started

if len(sys.argv) == 3 and sys.argv[1] in (COMMANDS + ['daemon']):
cmd = sys.argv[1]
PORT = int(sys.argv[2])
globals()[cmd]()
else:
print 'Error: invalid command'
print 'Usage: python tornading.py {%s}.' % '|'.join(COMMANDS)


Данный скрипт необходимо положить в папку с Trac'ом, в данном случае в home/%username%/trac/project_one/trac.
Запускать данный скрипт командой (предполагается, что вы находитесь в папке с trac'ом):
python tornading.py start %port%

где %port% – порт, который будет слушать Tornado.
При необходимости вы можете изменить host в самом скрипте. Также поддерживаются команды stop и restart.

Настройка Nginx


1. Откроем на изменение конфиг файла nginx:
sudo gedit /etc/nginx/nginx.conf

И приведем его к следующему виду:

# Сообщим чей UID должен использовать nginx
user www-data;
# Определим количество запускаемых рабочих процессов nginx
worker_processes 1;
# Укажем путь к местоположению файла протокола ошибок работы сер-
вера и fastcgi
error_log /var/log/nginx/error.log;
# Укажем путь к местоположению файла, содержащего pid процесса, за-
пущенного сервера
pid /var/run/nginx.pid;
# Настроим поведение nginx относительно сетевых соединений
events {
worker_connections 1024;
}
http {
# Часть конфигурации
include /etc/nginx/mime.types;
# Местоположение и формат лог-файла
access_log /var/log/nginx/access.log;
# Включим использование сервером одноименного системного вызова
# для повышения производительности nginx
sendfile on;
# Заставим nginx пытаться отправлять HTTP-заголовки в одном пакете
tcp_nopush on;
# Установим время в течение которого nginx будет держать открытое
соединение keepalive_timeout 65;
# Разрешим серверу использовать опцию сокета TCP_NODELAY
tcp_nodelay on;
# Установим сжатие данных сервером
gzip on;
gzip_comp_level 3;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml applica-
tion/xml application/xml+rss text/javascript;
#gzip_disable "MSIE [1-6]\.(?!.*SV1)";
include /etc/nginx/conf.d/*.conf;
# А это местоположение символических ссылок на конфигурацию
# созданных виртуальных хостов
include /etc/nginx/sites-enabled/*;
}


2. Создадим файл конфигурации нашего виртуального сервера:
sudo gedit /etc/nginx/sites-available/localtrac.ru

Приведем его к следующему виду:

server {
listen 80;
server_name SelectProject;
access_log /home/%username%/trac/projects/log/nginx/nginx_access.log;
error_log /home/%username%/trac/projects/log/nginx/nginx_error.log;
location / {
root /home/%username%/;
uwsgi_pass 127.0.0.1:3031;
include uwsgi_params;
}
location /project_one {
proxy_pass http://127.0.0.1:8011;
}
location /project_two {
proxy_pass http://127.0.0.1:8021;
}
}


3. Удалим конфиг nginx, который установлен по-умолчанию:
sudo rm /etc/nginx/sites-enabled/default

4. Активируем наш конфиг виртуального сервера:
sudo ln -s /etc/nginx/sites-available/localtrac.ru /etc/nginx/sites-enabled/localtrac.ru

Итак разберем наш конфиг!
Опцией listen мы сообщаем Nginx номер порта, на котором наш виртуальный сервер должен ожидать соединений.
Опция server_name определяет имя виртуального сервера, которое используется при анализе веб-сервером HTTP-заголовка Host, приходящего от клиента. Параметров у опции server_name может быть более одного, таким образом, вы можете определить псевдонимы вашего сервера.
Использование опции location позволяет вам настраивать поведение сервера в зависимости от значения URI, полученного от клиента. Таким образом, секция server может содержать несколько вложенных секций location, описывающих конфигурацию на основе части URI.
В нашем примере область
location / {
root /home/%username%/;
uwsgi_pass 127.0.0.1:3031;
include uwsgi_params;
}

говорит нам о том, что при переходе на адрес 127.0.0.1, запускается python-скрипт index.py находящийся в /home/%username%/.

Запуск серверов


1. Nginx:
sudo /etc/init.d/nginx start

(запускается один раз; он общий для всех созданных проектов)

2. USWGI:
uwsgi-python2.6 --uid 1000 -w %file% --limit-as 128 -p 3 -M –s 127.0.0.1:3031 -d /home/%username%/trac/uswgi.log

где %file% — имя python-скрипта (логин-скрипт).
(запускается один раз; он общий для всех созданных проектов)

3. Tornado:
python tornading.py start %port%

(для каждого проекта свой порт; данный скрипт должен лежать в каждом из проектов trac'а)

4. Subversion:
svnserve -d -r /home/%username%/trac/svn --listen-host=127.0.0.1 –listen-port=%port%

(для каждого проекта свой порт; он должен отличаться, как от порта Tornado, так и от портов subversion-подобных)

Пример


sudo /etc/init.d/nginx start
uwsgi-python2.6 --uid 1000 -w index --limit-as 128 -p 3 -M -s 127.0.0.1:3031 -d /home/adv/trac/uswgi.log

Проект 1
python tornading.py start 8011
svnserve -d -r /home/adv/trac/svn --listen-host=127.0.0.1 –listen-port=8102

Проект 2
python tornading.py start 8021
svnserve -d -r /home/adv/trac/svn --listen-host=127.0.0.1 –listen-port=8202

Проект 3
python tornading.py start 8031
svnserve -d -r /home/adv/trac/svn --listen-host=127.0.0.1 –listen-port=8102

Проект XX
python tornading.py start 8XX1
svnserve -d -r /home/adv/trac/svn --listen-host=127.0.0.1 –listen-port=8XX2
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.