Открыть список
Как стать автором
Обновить

Mercurial hgwebdir через FCGI + несколько разных хранилищ

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

Введение и отмазка


Доброго времени утра,

Возможно, всё о чём я сейчас буду рассказывать делается проще, правильнее, уже сделано, придумали ещё австралопитеки. Возможно это даже будет воспринято как издевательство над всем упомянутым, а вы зря потратите несколько минут своего драгоценного времени. Знайте — я предупреждал!

Если ещё не закрыли статью — обрисую ситуацию:

Что у нас есть


У нас есть nginx, mercurial несколько самостоятельных проектов, на каждый из которых имеется 3-4 репозитория. Ещё у нас иногда могут появляться сторонние разработчики, которым часть этих проектов показывать совершенно не обязательно.

Что со всем этим делать?


Для начала напомню (или расскажу, если кто не знает), что у Mercurial существует довольно много вариантов предоставления доступа к репозиториям.

Одним из самых правильных и удобных является hgwebdir, по ссылке описано множество методов подключения этого интрумента к различным веб-серверам, однако в нашем случае мы будем использовать nginx+fcgi.

Конфигурируем nginx


О самом nginx рассказывать не буду, приведу только пример рабочей конфигурации с https:
server { 
        listen <адрес>:443; 
        server_name hg1.whatever.com; 
         
        access_log  /var/log/nginx/hg1.access.log; 
        error_log   /var/log/nginx/hg2.error.log; 
 
        ssl                     on; 
        ssl_protocols           SSLv3 TLSv1; 
         
        ssl_certificate         /etc/nginx/ssl/hg/hgmaincert.pem; 
        ssl_certificate_key     /etc/nginx/ssl/hg/hgmaincert.key;  
 
        location / { 
            fastcgi_pass unix:/var/run/hgwebdir.fcgi.socket; 
            fastcgi_param       PATH_INFO       $fastcgi_script_name; 
            fastcgi_param       QUERY_STRING    $query_string; 
            fastcgi_param       REQUEST_METHOD  $request_method; 
            fastcgi_param       CONTENT_TYPE    $content_type; 
            fastcgi_param       CONTENT_LENGTH  $content_length; 
            fastcgi_param       SERVER_PROTOCOL $server_protocol; 
            fastcgi_param       SERVER_PORT     $server_port; 
            fastcgi_param       SERVER_NAME     $server_name; 
        }        
}


Конфигурируем fcgi


Основная задача — получить демона, который бы запускал наше fcgi приложение. Как получить этого демона — зависит от вашей ОС, если попросите — дополню статью описанием для Ubuntu (по сути для Linux вообще).
Сам fcgi гейт выглядит примерно так:
#!/usr/bin/python2.6

from mercurial import demandimport; demandimport.enable()
from mercurial.hgweb.hgwebdir_mod import hgwebdir
from mercurial.hgweb.request import wsgiapplication
from flup.server.fcgi import WSGIServer

def make_web_app():
return hgwebdir("path_to/hgweb.config")

WSGIServer(wsgiapplication(make_web_app)).run()


Поехали!..


Ну а дальше запускаем nginx, fcgi, пишем конфиг hgweb.config, согласно документации, добавляем туда коллекции наших проектов, и радуемся жизни… или не очень радуемся.
Дело в том, что hgwebdir сваливает все проекты в одну кучу — разграничить права то мы можем, но список репозиториев всё равно будет виден всем и непередаваемо ужасен.

Допиливаем hgwebdir


Что можно сделать теперь? Создать несколько поддоменов, с разными именами, насоздовать несколько fcgi демонов, добавить правила или даже хосты в nginx… получится не слабый такой зоопарк.

Вот с этого места можно начинать кидать помидоры, но мне в голову пришла мысль — если hgwebdir не умеет работать с несколькими конфигами — надо его заставить. Для этого добавим в конфигурацию хоста в nginx нужные нам алиасы:

        server_name hg1.whatever.com; 
        server_name hg2.whatever.com; 
        server_name hg3.whatever.com; 


Если же потребуется авторизация — придётся использовать несколько директив server, и include, чтобы вынести общую часть. А когда в nginx можно будет использовать auth_basic внутри if — можно будет сделать и без инклюда.

Рядом с гейтом, создадим модуль hgtreewebdir.py:
from mercurial.hgweb.hgwebdir_mod import hgwebdir

class hgtreewebdir(hgwebdir):

refreshinterval = 0 # = 0, хабр есть ноли!

def __init__(self, conf, baseui=None, virtuals={}):
self.baseconf = conf
self.virtuals = virtuals
hgwebdir.__init__(self, conf, baseui)


def run_wsgi(self, req):
if self.virtuals != {}:
virtual = req.env.get("HTTP_HOST", "")
if virtual in self.virtuals:
self.conf = self.virtuals[virtual]
return hgwebdir.run_wsgi(self, req)
self.conf = self.baseconf
return hgwebdir.run_wsgi(self, req)


Код самого гейта изменим следующим образом:

#!/usr/bin/python2.6

from mercurial import demandimport; demandimport.enable()
from hgtreewebdir_mod import hgtreewebdir
from mercurial.hgweb.request import wsgiapplication
from flup.server.fcgi import WSGIServer

def make_web_app():
return hgtreewebdir("path_to_configs/mainhgweb.config",
virtuals={
"hg2.whatever.com": "path_to_configs/hg2hgweb.config",
"hg3.whatever.com": "path_to_configs/hg3hgweb.config"
})
WSGIServer(wsgiapplication(make_web_app)).run()


Минусы и заключение


В данном варианте, интервал обновления изменён с 20 до 0, это может привести к нагрузкам на сервер вцелом, но я пока на 3 деревьях ничего особенного не наблюдаю. В принципе, интервалы и конфигурации тоже можно закешировать, что я наверное и сделаю, если возникнут тормоза.

Если за неделю ничего не отвалится — пробовать пропихнуть в официальную ветку, как считаете?
Теги:hgmercurialhgwebdirhgtreewebdirpythonnginxfcgi
Хабы: Системы управления версиями
Всего голосов 8: ↑7 и ↓1 +6
Просмотры1.7K

Похожие публикации

DevOps инженер Linux (можно удаленно, Москва)
от 150 000 ₽Баланс-ПлатформаМоскваМожно удаленно
Senior Python Engineer
от 2 800 до 3 500 $Moni LabsМожно удаленно
Senior Backend-разработчик (Python)
до 220 000 ₽PopmechanicМоскваМожно удаленно
Senior DevOps/SRE
от 220 000 до 350 000 ₽ВСКМоскваМожно удаленно

Лучшие публикации за сутки