The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Настройка сервера для работы с Mercurial (cvs mercurial)


<< Предыдущая ИНДЕКС Исправить src / Печать Следующая >>
Ключевые слова: cvs, mercurial,  (найти похожие документы)
From: Дмитрий Джус <mail@sphinx.net.ru.> Date: Sun, 30 Mar 2008 17:02:14 +0000 (UTC) Subject: Настройка сервера для работы с Mercurial Оригинал: http://sphinx.net.ru/blog/entry/howto-mercurial-repo-with-web-fastcgi-and-ssl/ Mercurial - распределённая система контроля версий, написанная на Python. Работает очень шустро (быстрее, похоже, только git), имеет всё что нужно и проста в работе. В Emacs для работы с Mercurial можно использовать DVC. Решил тут поставить Mercurial на сервер, прицепить веб-интерфейс к нему и сделать так, чтобы можно было отправлять коммиты прямо на сервак через SSH и HTTPS (удобно и надёжно). Опишу весь процесс. Используется следующее ПО: * FreeBSD 6.2-STABLE в качестве OS на сервере * Веб-сервер lighttpd 1.4.15 (на версиях ниже 1.4.12 скорее всего будут проблемы с SSL; 1.4.x вообще не сахар по сравнению с грядущей 1.5.x, далее по тексту будет хак, связанный с недостатками ветки 1.4.x) * Mercurial 0.9.4 (вышла на днях) Установка Mercurial дома и на сервере Даже если ставить руками - тупо до безобразия, см. README. На домашней машине (Gentoo Linux) хватило emerge mercurial. На FreeBSD в портах есть devel/mercurial (пока только версии 0.9.3) -- хватит make install clean. Правильность установки Mercurial проверяется вызовом команды hg debuginstall. Just in case you didn't know lighttpd нужно перезагружать каждый раз после изменения его настроек в файле lighttpd.conf. Базовая настройка сервера Для начала я создал под работу с Mercurial отдельного пользователя с минимальными правами, репозитарии предполагалось хранить в его домашнем каталоге (обычное решение -- хранение репозиториев в /var/repos - имхо не рулез, если разрешать SSH-доступ к репам). В качестве домашнего каталога пользователь scm получил /home/scm/. Дополнительно создал директорию /home/scm/hg/, в которой и будут лежать репо. Права на этот каталог hg - 700. Вместе с пользователем появилась и группа scm, в которую я дополнительно поместил пользователя www, от имени которого у меня запускается lighttpd - это потребуется для работы FastCGI-скрипта. Теперь стоит проверить, можно ли работать с сервером из Mercurial через прямой SSH-доступ. Заходим в любой Mercurial-репозиторий на домашней машине, пусть это будет папка с именем libmerctest: $ hg clone . ssh://[email protected]/hg/libmerctest/ Должен появиться запрос пароля пользователя scm, после чего на сервере в папке /home/scm/hg/ появится репозиторий libmerctest. Последний будет пуст, потому что при клонировании (а так же при hg push и hg pull) репо не обновляется рабочая копия проекта. Путь после имени узла указывается относительно домашней директории пользователя scm! Если случайно отзеркалить прямо в /hg/, всё сломается :-) Можно теперь попробовать обратную операцию: скачать залитый на сервер репозиторий на локальную машину: $ hg clone ssh://[email protected]/hg/libmerctest/ Внести изменения, закоммитить их (hg commit -m 'Test!') и отобразить изменения на удалённый сервер: $ hg push На данном этапе все эти операции должны работать! Проблемы обычно связаны с недостатком прав у пользователя scm. Если при попытке сделать hg push в репозиторий через ssh появляется ошибка Permission denied: .hg/store/lock (а ведь shit happens), нужно проверить права на папки с репозиториями: пользователь scm должен иметь к ним полный доступ на чтение/запись/обход (то есть, 700). Если предполагается активное использование SSH-доступа к репам несколькими людьми, то есть смысл пользоваться рецептами по Shared SSH из Mercurial Wiki. Можно также посадить юзера scm в jail или сделать ему chroot в домашнюю директорию, чтобы по серверу не шарился. Настройка веб-интерфейса к Mercurial через FastCGI В дистрибутиве Mercurial 0.9.4 есть несколько CGI-скриптов на Python: hgweb.cgi, hgwebdir.cgi и (появилось в последней версии) в папке contrib - hgwebdir.fcgi. Первый предназначен для предоставления через CGI веб-морды к одному репозиторию, второй - ко многим. hgwebdir.fcgi - для работы через FastCGI. Это гораздо быстрее, чем обычный CGI, так что я буду использовать именно hgwebdir.fcgi. Для обычных .cgi-скриптов потребуются немного другие настройки (проще). Я скопировал hgwebdir.fcgi в /home/scm/hg/, повесил на него права 500 (больше и не надо) и владельца - scm, а также создал для него конфиг с именем hgweb.conf в той же папке с таким содержимым: [collections] /hg = . Что означает следующее: через веб-интерфейс будут видны все Mercurial-репозитории в текущей папке (/home/scm/hg). Это удобно в том смысле, что после настройки можно будет просто зеркалить локальные репозитории на сервер, и они сразу станут видны через в веб-интерфейс. Скрипт будет запускаться прямо из /home/scm/hg, причём FastCGI-процесс будет инициироваться не веб-сервером, а отдельно. lighttpd и hgwebdir.fcgi будут общаться через сокет. Настройка lighttpd Теперь нужно настроить lighttpd так, чтобы по адресу http://sphinx.net.ru/hg/ появлялся список репозиториев и с ними можно было нормально работать дальше. Для этого в lighttpd.conf потребуется: * Подключить mod_fastcgi, если ещё не подключен: server.modules += ("mod_fastcgi") * Переписать все запросы по адресу http://sphinx.net.ru/hg/blahblah на /hg.fcgi/blahblah. По адресу hg.fcgi позднее прикрепим FastCGI-сервер, который будет связываться через сокет с hgwebdir.fcgi. Кроме того, веб-интерфейс использует CSS-файлы, запрашиваемые по адресам /hg/static/: url.rewrite += ( "^(/hg/static.*)$" => "$1", "^/hg(/?.*)$" => "/hg.fcgi$1" ) (Я добавил странное перенаправление запросов по /hg/static на самих себя потому, что у меня далее по списку url.rewrite стоит переброс всех остальных запросов на уровень обработчика URL-ов Django: "^(/.*)$" => "/django.fcgi$1". Вероятно, на другом сервере такое перенаправление не понадобится.) * Статические CSS-файлы устанавливаются вместе с модулями Mercurial в папку templates, потому и для /hg/static/ требуется подмена document-root: alias.url += ( "/hg/static/" => "/usr/local/lib/python2.5/site-packages/mercurial/templates/static/", ) * По адресу /hg.fcgi сделать FastCGI-сервер и прицепить его к сокету, который будет создаваться отдельно: fastcgi.server += ( "/hg.fcgi" => (( "socket" => "/var/tmp/hg.socket" )) ) В основном document-root lighttpd соответственно нужно создать пустой файл hg.fcgi при помощи touch. На данном этапе по lighttpd это всё. FastCGI-процесс Нужно создать FastCGI-процесс с сокетом в /var/tmp/hg.socket. Проще всего написать rc-скрипт, который будет поднимать-опускать hgwebdir.fcgi автоматически, внедрив его в систему загрузки сервера. Можно прочитать руководство FreeBSD по написанию rc-скриптов, однако вот готовый вариант, использующий утилиту spawn-fcgi из комплекта поставки lighttpd: #!/bin/sh # # REQUIRE: DAEMON # PROVIDE: hgwebdir # KEYWORD: shutdown # . /etc/rc.subr name="hgwebdir" rcvar=`set_rcvar` load_rc_config $name pidfile=/var/run/${name}.pid procname="python" socket=/var/tmp/${name}.socket command="/usr/local/bin/spawn-fcgi" command_args=" -f /home/scm/hg/hgwebdir.fcgi -s ${socket} -C /home/scm/hg -P ${pidfile} -u scm" start_precmd=start_precmd start_postcmd=start_postcmd stop_postcmd=stop_postcmd start_precmd() { cd ~scm/hg } start_postcmd() { chown :scm ${socket} chmod 770 ${socket} } stop_postcmd() { rm -f ${pidfile} ${socket} } run_rc_command "$1" Это нужно поместить в rc-скрипт по адресу /usr/local/etc/rc.d/hgwebdir, а в /etc/rc.conf добавить строчку: hgwebdir_enable="YES" Тогда можно будет запускать/останавливать веб-интерфейс простыми командами: /usr/local/etc/rc.d/hgwebdir start и /usr/local/etc/rc.d/hgwebdir stop И при перезагрузке системы hgwebdir не отвалится, а загрузится сам. При использовании spawn-fcgi созданный процесс будет иметь имя python /home/scm/hg/hgwebdir.fcgi, что не совпадает с command, так что инфраструктура rc из FreeBSD не сможет корректно отследить запущенный процесс через check_pidfile(), в результате чего не будет работать команда /usr/local/etc/rc.d/hgwebdir stop, ругаясь на якобы незапущенный сервис. Чтобы этого не происходило, в скрипте прописана строчка procname="python". Возникают также проблемы с видимостью репозиториев. В hgweb.config путь после = в строчке /hg = . указан относительно текущей рабочей директории (по-другому просто не работает). Запустить /usr/local/etc/rc.d/hgwebdir start можно откуда угодно, так что не всегда hgwebdir.fcgi увидит репозитории в <<текущей папке>>. Чтобы этого не случалось, в скрипте явно прописан переход в папке с репозиториями в start_precmd. Вероятно, это грязный хак, однако мне не удалось заставить hgwebdir.fcgi воспринимать абсолютные пути. Можно также делать переход в /home/scm/hg прямо в hgwebdir.fcgi (cм. os.chdir() в Python). При работе через обычный CGI получается подменять document-root для hgwebdir.cgi ещё на уровне lighttpd через директиву alias.url. Сокет помещается в /var/tmp: не думаю, что это распространённая практика (и это снова грязный хак), но FastCGI-процесс спавнится от имени пользователя scm (в command_args есть -u scm) и так получается максимально урезать права веб-интерфейсу. Нужно лишь, чтобы lighttpd имел полный доступ к сокету (несколькими частями ранее я поместил в группу scm пользователя www) - это выполняется в start_postcmd() rc-скрипта. Дополнительно веб-интерфейс чрутится в /home/scm/hg/. Проверка веб-интерфейса На данном этапе можно запустить веб-интерфейс: /usr/local/etc/rc.d/hgwebdir start И указать браузеру на http://sphinx.net.ru/hg/, чтобы улицезреть список своих репо. Если на данном этапе появляется 502-я ошибка, то либо отвалился FastCGI-процесс, либо lighttpd не хватает прав на запись в сокет. В любом случае, сразу нужно смотреть в логи lighttpd. Если не видятся репозитории - проверить права на них в папке /home/scm/hg. Помимо веб-интерфейса должно работать зеркалирование через HTTP с удалённого сервера: $ hg clone http://sphinx.net.ru/hg/libfoobar Настройка доступа в репозитории на запись через HTTPS Mercurial позволяет делать hg push не только через SSH, но и через HTTPS. Достоинство в том, что на уровне каждого репозитория можно ограничивать набор пользователей, которые имеют доступ на запись к нему, и не давать каждому SSH-доступ к серверу (пусть это даже доступ к ограниченной учётке scm). Пользователи идентифицируются при помощи стандартного механизма HTTP-аутентификации. Mercurial также позволяет использовать SSL для защиты соединения. Уровень Mercurial В Mercurial нужно указать список пользователей, которым можно делать hg push в репо. Например, в файле .hg/hgrc соответствующего репозитория можно прописать [web] allow_push = scm, bonobo чтобы разрешить доступ на запись пользователям scm и bonobo. Указав allow_push = *, мы разрешим любому пользователю, прошедшему аутентификацию, толкать в репо (ok-ok, делать hg push). По умолчанию Mercurial поддерживает hg push только через HTTPS, чтобы разрешить запись через HTTP нужно в секции [web] файла .hg/hgrc соответствующего репозитория прописать: push_ssl = false Но я буду рассматривать случай записи в репо с использованием только HTTPS. Настройка lighttpd Теперь нужно настроить доступ по HTTPS на lighttpd и сделать так, чтобы при доступе в репозиторий появлился запрос аутентификации ползователя. С первым всё просто. Нужно, чтобы lighttpd был скомпилен с поддержкой SSL: $ lighttpd -v lighttpd-1.4.15 (ssl) - a light and fast webserver Для работы потребуется SSL-сертификат. Если его нет, то можно сгенерить самому: $ openssl req -new -x509 \ -keyout lighttpd.pem -out lighttpd.pem \ -days 365 -nodes OpenSSL задаст несколько вопросов, в <<Common Name:>> лучше указать домен. Полученный файлик lighttpd.pem поместить в /etc/ssl/certs/. Браузеры на такой самопальный сертификат будут ругаться, потому что он не подписан удостоверяющим центром. Теперь в lighttpd.conf подключить используемый сертификат (для использования при HTTPS-соединениях): $SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/ssl/certs/lighttpd.pem" } Если есть корневой сертификат от CA, то путь к нему нужно указать там же, в ssl.ca-file. В доках по lighttpd есть подробности. По-хорошему, лучше разрешить доступ на чтение без пароля, а требовать авторизации только при попытке записи в репозиторий. На уровне HTTPS это ловится типом запроса - POST или GET. Но в версиях lighttpd 1.4.x нет возможности указывать настройку только для определённого типа запроса (эта возможность добавлена в ветке 1.5.x). Можно обойтись так: сделать на уровне аутентификационного механизма lighttpd дополнительного пользователя, которому на уровне Mercurial всё равно будет запрещён доступ на запись в репозитории. Далее поясню это подронее. В lighttpd.conf включаем механизм авторизации: server.modules += ( "mod_auth" ) Указываем там же используемый тип хранения учётных записей: auth.debug = 0 auth.backend = "plain" auth.backend.plain.userfile = "/usr/local/etc/lighttpd.auth.plain" При типе plain пароли хранятся в файле открытым способом и перечисляются в парах <<имя-пароль>> через двоеточие: $ cat /usr/local/etc/lighttpd.auth.plain hgview:hgview scm:$up3rb!ff_(C) Для типа htpasswd файл с шифрованными паролями указывается в переменной auth.backend.htpasswd.file; его можно создать при помощи одноимённой программы htpasswd из Apache: $ cd /usr/local/etc/ $ htpasswd -bc lighttpd.auth.htpasswd hgview hgview $ htpasswd -b lighttpd.auth.htpasswd scm '$up3rb!ff_(C)' $ cat lighttpd.auth.htpasswd hgview:mxgU6lcV.0CPM scm:ZQmywuFRcxzPq Тип htdigest предоставляет возможность ещё более надёжного хранения паролей. И вешаем на все запросы по /hg (_без_ слеша на конце!) волшебное окошко с паролем: auth.require = ( "/hg" => ( "method" => "basic", "realm" => "Mercurial repos (hgview/hgview for readonly access)", "require" => "valid-user" ) ) Строчка "require" => "valid-user" означает, что авторизацию пройдёт всякий, указавший правильное сочетания имени и пасса из файла /usr/local/etc/lighttpd.auth.plain. В "realm" => ... указывается сообщение в окошке ввода пароля. "Фиктивный" пользователь hgview был создан для простого доступа на чтение. Можно всю конструкцию auth.require обернуть в условие $SERVER["socket"] == ":443" { .. }, тогда при доступе по http:// пароль спрашиваться не будет (всё равно hg push я разрешил только по https://). Когда lighttpd 1.5.x уверенно станет стабильным (http://lighttpd.net сам уже работает на этой версии), можно будет auth.require завернуть в условие $SERVER["request-method"] == "POST" { .. } и убрать пользователя hgview вообще - тогда запрос на авторизацию будет появляться только при попытке записи в репо. Пользователь scm же включен в списки allow_push в настройках репозиториев (в файлах .hg/hgrc) и может после авторизации делать hg push: $ cd ~/projects/work-libfoobar/ $ hg push https://[email protected]/hg/libfoobar Появится запрос пароля и изменения улетят на сервер. Пароль при доступе через https://[email protected]/... - тот, что указан в lighttpd.auth.plain! Это пароль уровня lighttpd, а не пароль пользователя scm на сервере. Я просто сделал им одинаковые имена (можно и пароли одинаковые сделать), чтобы не путаться при доступе через SSH и HTTPS. Если Mercurial вылетает с ошибкой abort: authorization failed (shit happens) при стопудово правильном пароле, стоит проверить разрешения на запись в репозитории в файлах .hg/hgrc. Добавление коммиттера Когда потребуется разрешить стороннему пользователю запись в какой-то репозиторий, нужно будет: 1. Создать новую пару имя-пароль в файле lighttpd.auth.plain (или другом, в зависимости от используемого типа хранения учёток). 2. Внести созданное имя в список allow_push = в настройках соответствующего репозитория Mercurial (напрямую через SSH). Перезагрузка сервисов не потребуется. Через HTTPS в Mercurial нельзя делать hg clone. Индивидуальные настройки репозиториев Каждому репо можно указать описание и человеческое название в .hg/hgrc: [web] name = libfoobar description = Blazingly fast library for intensive foobaring Крайне полезна опция allow_archive, позволяющая скачивать архивы со снимками ревизий через веб интерфейс: allow_archive = gz bz2 Дальнейшая информация В Mercurial есть и другие вкусности, обязательно читать Mercurial wiki.

<< Предыдущая ИНДЕКС Исправить src / Печать Следующая >>

Обсуждение [ RSS ]
  • 1, Джус (?), 23:34, 02/11/2008 [ответить]  
  • +/
    Вместо

        fastcgi.server += ( "/hg.fcgi" => (( "socket" => "/var/tmp/hg.socket" )) )

    следует читать

        fastcgi.server += ( "/hg.fcgi" => (( "socket" => "/var/tmp/hgwebdir.socket" )) )

     
  • 2, truetug (ok), 12:42, 07/03/2009 [ответить]  
  • +/
    Определить пушим мы или нет можно так:
    $HTTP["querystring"] =~ "cmd=unbundle" {
                    auth.require = (   "" => (
                            "method"  => "basic",
                            "realm"   => "Mercuial Repo",
                            "require" => "valid-user"
                            )
                    )
            }

    Ну и вообще: http://www.selenic.com/mercurial/wiki/index.cgi/HgWebDirStepByStep

     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру