Running Hgweb With Nginx and uWSGI
Published: Estimated Reading Time: ~3 minutes
As you probably noticed I have been messing around with mercurial and saw 502, 404, 403, etc. errors everywhere on hg.x64architecture.com. It took me a while to figure out how to setup mercurial and a lot of tutorials were outdated and they were for fast-cgi, cgi, proxying, etc. which are slower then uWSGI so I wanted to use uWSGI, I figured i’d make a tutorial to help someone out.
I’m using Ubuntu 12.04 as my Linux Distribution.
First off we have to fetch the required packages:
$ sudo apt-get install python-software-properties (Optional)
$ sudo add-apt-repository ppa:kurtcancemi/nginx (Optional)
$ sudo apt-get update
$ sudo apt-get install mercurial python-pygments nginx nginx-common nginx-full uwsgi uwsgi-plugin-python apache2-utils
You can optionally make a hg user and group:
$ sudo /usr/sbin/groupadd hg
$ sudo /usr/sbin/useradd -g hg -s /bin/false hg
$ sudo chown hg:hg /var/hg
$ sudo /usr/sbin/usermod -G hg www-data
Create a directory for the hgweb configuration file. Change the path to whatever you would like.
$ sudo mkdir -p /var/hg
The mercurial package ships with a WSGI file which we will use.
$ sudo cp /usr/share/doc/mercurial/examples/hgweb.wsgi /var/hg/
Edit hgweb.wsgi and set the path of the hgweb configuration file. You could apply this patch if you want by saving it as hgweb.patch and entering $ patch -p1 < hgweb.patch
--- hgweb.wsgi 2013-05-27 01:36:28.835575809 -0400
+++ hgweb.wsgi 2013-05-27 01:37:49.023575136 -0400
@@ -2,7 +2,7 @@
# See http://mercurial.selenic.com/wiki/modwsgi for more information
# Path to repo or hgweb config to serve (see 'hg help hgweb')
-config = "/path/to/repo/or/config"
+config = "/var/hg/hgweb.config"
Uncomment and adjust if Mercurial is not installed system-wide (consult “installed modules” path from ‘hg debuginstall’): Change the configuration to your needs:
/var/hg/hgweb.config
[web]
; allow push
allow_push = *
; Base url
baseurl = /
; makes it easier to serve static assests via nginx instead of python
staticurl = /static
; allow archive download
allow_archive = gz bz2 zip
[paths]
; the path to your mercurial repository
repo = /var/hg/YOURREPO
; repo1 = /var/hg/YOURREPO
[extensions]
; pretty colors (optional)
hgext.highlight =
Create a uwsgi application configuration file.
/etc/uwsgi/apps-available/hgweb.ini
[uwsgi]
processes = 2
socket = unix:/run/hgweb.sock
chdir = /var/hg
wsgi-file = hgweb.wsgi
uid = hg
gid = hg
Enable the uwsgi hg application.
$ sudo ln -s /etc/uwsgi/apps-available/hgweb.ini /etc/uwsgi/apps-enabled/`
Start uWSGI.
$ sudo service uwsgi restart
Now we have to configure a virtual host for Nginx.
/etc/nginx/sites-available/hgweb
server {
# server name
server_name hg.example.com;
# logs(optional)
access_log /var/hg/log/access.log;
error_log /var/hg/log/error.log;
location / {
limit_except GET HEAD {
auth_basic "Mercurial Repository";
auth_basic_user_file /var/hg/mercurial_users;
}
include uwsgi_params;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param UWSGI_SCHEME $scheme;
uwsgi_param SCRIPT_NAME /;
uwsgi_param AUTH_USER $remote_user;
uwsgi_param REMOTE_USER $remote_user;
uwsgi_pass hg;
}
# serve static assests through nginx(faster) and not python.
location /static {
alias /usr/share/mercurial/templates/static;
}
}
upstream hg {
server unix:/run/uwsgi/app/hgweb/socket;
}
Enable the Nginx virtual host.
$ sudo ln -s /etc/nginx/sites-available/hgweb /etc/nginx/sites-enabled/
Generate user and password for pushing to the repo
$ sudo htpasswd -c /var/hg/mercurial_users YOURUSERNAME
Check for errors in /etc/nginx/sites-available/hgweb:
$ sudo service nginx configtest
If there are no errors then reload Nginx:
$ sudo service nginx reload