Системы управления версиями

индекс
161,03

Хостинг mercurial репозиториев с помощью nginx, gunicorn и supervisor

imageСпособов хостинга mercurial репозиториев достаточно, но я сочинил именно такой вариант по следующим причинам:
  1. nginx: мало кушает, быстро работает — скорость
  2. supervisor: мониторит процесс, перезапускает если что — надёжность
  3. gunicorn: wsgi, большие возможности по настройке — эффективность
Кроме того, т.к. я разрабатываю на django, и сайты запускаю под этой же связкой, есть и четвёртая причина — унификация, а она очень полезная вещь.

Если вас заинтересовала тема, то конкретные инструкции и конфиги — под катом.

Далее подразумевается, что у вас уже установлены mercurial, nginx, gunicorn и supervisor. Я использую Ubuntu 10.04, для неё mercurial, nginx и supervisor имеются в стандартных репозиториях, а для gunicorn имеется ppa.

В качестве основного скрипта для работы с репозиториями используется hgweb, поставляемый в составе mercurial, от него и танцуем.

Репозитории я храню в каталоге /home/hgdata. Причина — упрощение настройки бекапов. Сохраняется весь /home, и не надо указывать отдельные каталоги, например. Все описываемые скрипты и конфиги хранятся в этом же каталоге, /home/hgdata.

Первый файл — hgweb.config, конфиг самого hgweb, как следует из названия:
Copy Source | Copy HTML
[collections]
/ = /home/hgdata
он говорит hgweb о том, что репозитории хранятся в /home/hgdata, и надо их искать там.

Далее, т.к. мы поднимаем wsgi сервер, то меркуриаловский скрипт hgweb надо преобразовать в wsgi. Для этого используется скрипт hgwebapp.py:
Copy Source | Copy HTML
#!/usr/bin/env python
import os
import sys
from mercurial.hgweb.hgwebdir_mod import hgwebdir
from mercurial.hgweb.request import wsgiapplication
os.environ["HGENCODING"] = "UTF-8"
def make_web_app():
    return hgwebdir("/home/hgdata/hgweb.config")
def application(environ, start_response):
    environ['wsgi.url_scheme'] = environ.get('HTTP_X_URL_SCHEME', 'http')
    # nginx wrap proxy headers with HTTP
    environ['REMOTE_USER'] = environ.get('HTTP_REMOTE_USER', '')
    app = wsgiapplication(make_web_app)
    return app(environ, start_response)
Этот скрипт мы уже можем стартануть под gunicorn. Конфиг для gunicorn называется hgweb.conf:
Copy Source | Copy HTML
[program:hgweb]
command=/usr/bin/gunicorn -b 127.0.0.1:8080 hgwebapp:application
environment=PYTHONPATH='/home/hgdata'
directory=/home/hgdata
user=www-data
autostart=true
autorestart=true
startsecs=10
redirect_stderr=true
stdout_logfile=/var/log/supervisor/hgweb.gunicorn.log
симлинк на этот конфиг кладём в /etc/supervisor/conf.d и уже можно его запускать. Заходим в «панель управления» supervisor: sudo supervisorctl и даём команду update. supervisor пересмотрит каталог конфигов, найдёт новый и запустит gunicorn-сервер со скриптом hgwebapp. После этого на порту 8080 адреса 127.0.0.1 будет висеть сервер mercurial, и остаётся его выставить наружу посредством nginx.

В файл конфига nginx я прописал всё это дело на домен третьего уровня, и у меня он называется так: hg.somewebsite.com
Copy Source | Copy HTML
upstream app_server_hgweb {
        server 127.0.0.1:8080 fail_timeout=0;
}
server {
    listen X.X.X.X:80;
    server_name hg.somewebsite.com;
    location / {
            auth_basic "Mercurial repository";
            auth_basic_user_file /home/hgdata/auth;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header remote_addr $remote_addr;
            proxy_set_header remote_user $remote_user;
            proxy_redirect off;
            if (!-f $request_filename) {
                proxy_pass app_server_hgweb;
                break;
            }
        }
}
Как видно из конфига, для аутентификации юзеров используется файл /home/hgdata/auth, в нём обычные пары юзер-хеш пароля. Имя юзера передаётся вниз на wsgi сервер, и используется hgweb для того, чтобы определить, какой доступ давать юзеру.

Это настраивается в файле hgrc (который лежит в подкаталоге .hg репозитория), в секции web. Прописывается очень просто:
Copy Source | Copy HTML
[web]
contact = Organization name
description = Repository description
style = gitweb
allow_read = user1 user2 user3
allow_push = user1
push_ssl = false
allow_archive = bz2 gz zip
В данном случае заливать в репозиторий может только user1, а читать могут трое. От анонимусов данный репозиторий закрыт. Подробнее по настройкам доступа тут.

В заключение нужно создать симлинк с файла /home/hgdata/hg.somewebsite.com в каталог /etc/nginx/sites-enabled и рестартнуть nginx, после этого всё должно работать. Необходимо учесть, что т.к. юзером в конфиге nginx прописан www-data, то www-data должен иметь все права на репозитории в /home/hgdata, иначе он не сможет туда писать.

Вот и всё, репозитории должны быть доступны по http. Надеюсь, данная статья будет полезна в вашей работе. Буду рад услышать замечания и предложения.
+13
17 января 2012, 14:39
59

комментарии (17)

–3
adontz #
Я хостю репозиторий в апаче/wsgi. На скорость мне плевать, а всякие апаческие вкусности (макросы конфигурации, например) оказались кстати. Ну и на скорость плевать, в принципе, не так быстро пишем :-)
0
spanasik #
Так статья про хостинг репозиториев — допустим, 100 или больше :-)
0
alpust #
Здорово, осталось дать доступ по ssh:// и прикрутить возможность использовать ssh ключи, и будет вообще бенч :) Спасибо, статья понравилась!
0
spanasik #
По ssh я git юзаю, а это для Windows-девелоперов.
0
alpust #
Дык, Windows-девелоперы, тоже люди :)
0
spanasik #
угу :-)
0
Azy #
Я под Win использую и git и mercurial по ssh. Где-то должны быть проблемы?
0
spanasik #
Насколько я понимаю, вопрос риторический :-)
0
Azy #
Просто некоторые недооценивают Windows в качестве платформы для web разработки.
0
spanasik #
↑ статья не про это
0
Azy #
Я про вашу переписку выше.
0
adontz #
А вы с таким сталкивались в рамках одной софтовой компании? 100 или больше активных репозиториев?
+1
spanasik #
Ну у нас не 100 конечно, но гораздо больше одного.
0
alpust #
Репозитории как грибы растут, после того, как компания 3-4 года успешно работает на рынке, и выпускает определенное количество продуктов ежегодно.
0
alpust #
У нас в компании порядка 30 свиновых репозиториев и еще с 10 hg'шных.
+1
Gluttton #
А у нас на работе код хостится на RhodeCode. В принципе удобно…
0
serjs #
Поддерживаю, использую rh с самого начала его существования, он правда не очень быстро развиваются, но сейчас использовать вполне так можно, особенно после введения груп и многочисленных исправлений с интеграцией ldap.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.