Some weeks ago I switched to Nginx and quit Apache and was quite happy with it. I was so happy that completely forgot about my Mercurial repositories hosted on same server. This happen when I was in hurry and needed to push and pull some changes, damn.
At first I quickly restored Apache, did all needed changes and switched back to Nginx. For sure, I did not like this way and explored how I can connect Mercurial directly to Nginx. I was quite surprised how easy it is and how flexible.
# Mercurial via Apache setup
I had Mercurial setup through Apache in a very standard way.
/var/hg - Holding all my repositaries
/var/hg/hgweb.config
[collections]
repos/ = repos/
/var/hg/hgwebdir.cgi - For Apache CGI support
/var/hg/hguser - for user passwords in htpasswd format
Apache configuration was the following
ScriptAliasMatch ^/hg(.*) /var/hg/hgwebdir.cgi$1
<Directory /var/hg>
Options ExecCGI FollowSymLinks
AllowOverride None
</Directory>
<Location /hg>
AuthType Basic
AuthName "Mercurial repositories"
AuthUserFile /var/hg/hgusers
Require valid-user
</Location>
Switch to Nginx was really painless.
# Nginx and Mercurial setup
# Prepare Mercurial
First step I switched to FastCGI instead of CGI. To do this I copied file hgwebdir.fcgi to my repo root /var/hg and made it executable
copy /usr/share/doc/mercurial-common/examples/hgwebdir.fcgi /var/hg
chmod +x /var/hg/hgwebdir.fcgi
Or grab the file here
wget http://selenic.com/repo/hg/raw-file/tip/contrib/hgwebdir.fcgi
Next step is to install something that can spawn FastCGI processes, sine Nginx can not do this by itself. This is easy with spawn-cgi
#apt-get install spawn-fcgi
I configured it via local unix socket instead of TCP port, it seems to me this way it is more secure. Run it like this:
#spawn-fcgi -u www-data -g www-data -s /tmp/mercurial.sock -d /var/hg/ -- /var/hg/hgwebdir.fcgi
At first start I've run into the problem
spawn-fcgi: child exited with: 1
After running with "-n" switch to see debug output, I realised that I was missing one python module needed for a setup.
Traceback (most recent call last):
File "/var/hg/hgwebdir.fcgi", line 25, in
from flup.server.fcgi import WSGIServer
File "/usr/lib/pymodules/python2.6/mercurial/demandimport.py", line 106, in _demandimport
mod = _origimport(name, globals, locals)
ImportError: No module named flup.server.fcgi
To fix this I installed missing python packages and issue was fixed.
#apt-get install python-flup
# Configure Nginx
Edit file /etc/nginx/sites-available/mercurial.conf and add the following server definition:
server {
listen 80;
server_name YOUR_MERCURIAL_DOMAIN;
location / {
auth_basic "Secure Login";
auth_basic_user_file /var/hg/hgusers;
include fastcgi_params;
fastcgi_param PATH_INFO $uri;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_intercept_errors on;
fastcgi_pass unix:/tmp/mercurial.sock;
}
}
The above settings will setup a new virtual host, where all traffic is redirected to the Mercurial FastCGI wrapper. It is important that you forward the PATH_INFO and REMOTE_USER variables. Mercurial will not work correctly without these.
Be sure that file /var/hg/hgusers contains all your Mercurial users with passwords, it can be created using htpasswd tool shipped with Apache. Restart Nginx and try to to push pull.
In case you have a big push load you may get an 413 Request Entity Too Large error. Just add client_max_body_size 20M; to "server" part of config, like this:
server {
listen 80;
server_name YOUR_MERCURIAL_DOMAIN;
client_max_body_size 20M;
# Misc
One thing that changed was repositary path. Before it has /hg/ in path line
http://a32.me/hg/project1
Now it become a full virtual host and changed to:
http://hg.a32.me/project1
I have to reconfigure all my projects, but it is not a pain like it was with CVS.
Next thing I though about, I can move repositories under its own uid:gid and not run it under www-data, this can improve security.
Do not forget to include running spawn-fcgi into /etc/rc.local for automatically start on system boot.
# Links
My story is based on these links.
- http://www.opennet.ru/base/dev/mercurial_http.txt.html
- http://geeksharp.com/2010/01/20/mercurial-web-with-fastcgi-nginx/
- http://fosswire.com/post/2009/08/hosting-mercurial-repositories-with-nginx/
- http://www.softwareprojects.com/resources/programming/t-how-to-serve-mercurial-hg-repository-over-nginx-1856.html
- http://www.dikant.de/2009/07/29/running-mercurial-with-fastcgi-in-nginx/