install mercurial with nginx

개발을 할때면 간단히 형상관리를 할수 있는 개인만의 repository를 가지고 싶어지는데, AWS 상에서 nginx서버를 이용해서 간단한 mercurial web repository 를 구성해보았다.

soruce url :

case : ubuntu 12.04-LTS, precise(on aws)

sudo vi /etc/apt/source.list
deb precise nginx
deb-src precise nginx

sudo -s
nginx=stable # use nginx=development for latest development version
add-apt-repository ppa:nginx/$nginx
apt-get update 
apt-get install nginx
# W: GPG error: precise Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY XXXXXX

만일 apt-get update 시에 다음과 같은 오류가 날시에는 다음과 같이 한다.

gpg --keyserver --recv-key XXXXXX && gpg -a --export XXXXXX | apt-key add -
apt-get install mercurial python-flup spawn-fcgi
mkdir /var/www/hg
chown ubuntu:www-data /var/www/hg

case : amazon linux ami(on aws)

sudo yum install nginx
sudo yum install spawn-fcgi mercurial
sudo easy_install flup
mkdir /var/www/hg
chown ec2-user:nginx /var/www/hg


nginx를 ubuntu, yum 기본패키지를 깔수도 있고, 최신 stable 버젼으로 깔수도( 있다.

vi /var/www/hg/hgwebdir.fcgi

#!/usr/bin/env python
# An example CGI script to export multiple hgweb repos, edit as necessary

# adjust python path if not a system-wide install:
#import sys
#sys.path.insert(0, "/path/to/python/lib")

# enable demandloading to reduce startup time
from mercurial import demandimport; demandimport.enable()

# Uncomment to send python tracebacks to the browser if an error occurs:
#import cgitb

# If you'd like to serve pages with UTF-8 instead of your default
# locale charset, you can do so by uncommenting the following lines.
# Note that this will cause your .hgrc files to be interpreted in
# UTF-8 and all your repo files to be displayed using UTF-8.
import os
os.environ["HGENCODING"] = "UTF-8"

from mercurial.hgweb.hgwebdir_mod import hgwebdir
from flup.server.fcgi import WSGIServer

# The config file looks like this. You can have paths to individual
# repos, collections of repos in a directory tree, or both.
# [paths]
# virtual/path1 = /real/path1
# virtual/path2 = /real/path2
# virtual/root = /real/root/*
# / = /real/root2/*
# [collections]
# /prefix/to/strip/off = /root/of/tree/full/of/repos
# paths example:
# * First two lines mount one repository into one virtual path, like
# '/real/path1' into 'virtual/path1'.
# * The third entry tells every mercurial repository found in
# '/real/root', recursively, should be mounted in 'virtual/root'. This
# format is preferred over the [collections] one, using absolute paths
# as configuration keys is not supported on every platform (including
# Windows).
# * The last entry is a special case mounting all repositories in
# '/real/root2' in the root of the virtual directory.
# collections example: say directory tree /foo contains repos /foo/bar,
# /foo/quux/baz. Give this config section:
# [collections]
# /foo = /foo
# Then repos will list as bar and quux/baz.
# Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
# or use a dictionary with entries like 'virtual/path': '/real/path'

sudo chmod ug+x /var/www/hg/hgwebdir.fcgi

WSGI 서버를 만들수 있도록 한다.

vi /var/www/hg/hgweb.config

baseurl = /
allow_push = *
push_ssl = false

/ = /var/www/hg/*

WSGI 서버에서 레포지토리 연결할수 있도록 설정 파일을 설정해준다.

perl -le 'print crypt("[your-password]", "salt-hash")'
vi /var/www/hg/hgusers.config


접근 암호도 설정해준다.

vi /etc/init.d/fcgi-hg

#! /bin/sh
# fcgi-hg Startup script for the nginx HTTP Server
# chkconfig: - 84 15
# description: Loading php-cgi using spawn-cgi
# HTML files and CGI.
# Author: Ryan Norbauer
# Modified: Geoffrey Grosenbach
# Modified: David Krmpotic
# Modified: Kun Xi
FCGIUSER=nginx # ubuntu www-data
DESC="HG in FastCGI mode"

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0
test -x $FCGIAPP || exit 0

start() {
$DAEMON -a $FCGIHOST -p $FCGIPORT -u $FCGIUSER -g $FCGIGROUP -f $FCGIAPP -P $PIDFILE 2> /dev/null || echo -en "\n already running"

stop() {
kill -QUIT `cat $PIDFILE` || echo -en "\n not running"

restart() {
kill -HUP `cat $PIDFILE` || echo -en "\n can't reload"

case "$1" in
echo -n "Starting $DESC: "
echo -n "Stopping $DESC: "
echo -n "Restarting $DESC: "
# One second might not be time enough for a daemon to stop,
# if this happens, d_start will fail (and dpkg will break if
# the package is being upgraded). Change the timeout if needed
# be, or change d_stop to have start-stop-daemon use --retry.
# Notice that using --retry slows down the shutdown process somewhat.
sleep 1
echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
exit 3

exit $?

서버 실행시 서비스 등록을 해준다.

sudo chkconfig fcgi-hg on		# case amazon linux ami or centos
sudo update-rc.d fcgi-hg defaults		# case ubuntu

fcgi-hg 에 대한 init script를 만들어주고 등록한다.

vi /etc/nginx/host.d/xxxxx

server {
	listen 80;
	root /var/www/hg/;
	gzip on;

	location / {
		include fastcgi_params;
		fastcgi_split_path_info ^(/)(.*)$;
		fastcgi_param  SCRIPT_NAME      $fastcgi_script_name;
		fastcgi_param  PATH_INFO        $fastcgi_path_info;
		fastcgi_param  AUTH_USER        $remote_user;
		fastcgi_param  REMOTE_USER      $remote_user;
		fastcgi_intercept_errors        off;
		limit_except GET HEAD {
			auth_basic  'Geek\'s Repositories';
			auth_basic_user_file /var/www/hg/hgusers.config;
	location /static/ {
		rewrite /static/(.*) /$1 break;
		root /usr/lib/python2.6/site-packages/mercurial/templates/static;
		expires 30d;

nginx 웹설정 파일을 수정해주고 nginx를 restart 를 하면 해당 도메인으로 mercurial web repository가 뜨는 것을 볼 수 있다.

hg init /var/www/hg/[project_name]
sudo chgrp -R nginx /var/www/hg/[project_name]	# case centos
sudo chgrp -R www-data /var/www/hg/[project_name]	# case ubuntu

[project_name]의 이름의 프로젝트를 위와 같이 추가하면 각각의 프로젝트에 대해 repository 가 생기는 것을 볼수 있다.