# HOWTO: HG hosting = nginx + hg + ssh + mercurial-server + hgweb



## graudeejs (Nov 7, 2010)

It's a long time since I've wrote anything useful here.
Today I will uncover how to make public git hosting with www/nginx, devel/mercurial, devel/py-mercurialserver

Step 1: install software
`# portmaster www/nginx devel/mercurial devel/py-mercurialserver www/fcgiwrap`
We need www/fcgiwrap because nginx doesn't support cgi, but it does support fastcgi

Step 2: configure mercurial-server
HINT: by default mercurial-server will use /usr/local/hg/ directory. If you want to change that:
`# pw usermod hg -h /srv/hg`
I will use /srv/hg/ to store mercurial-server data.

Since we'll need ssh key let's generate one
`# ssh-keygen`
and save it to ssh-key (private) and ssh-key.pub (public)
Make sure you can copy keys securely. You will need pub key on server, and private key on your desktop pc (or whatever you use)

Now become hg user and initialize mercurial-server (hg's home must be writeable by hg)

```
# mkdir /usr/local/etc/mercurialserver/keys/root/homepc
# cp /path/to/ssh-key.pub /usr/local/etc/mercurialserver/keys/root/homepc/
# su -l hg -c tcsh
$ refresh-auth
$ exit
```

Step 2: Configure /etc/rc.conf
This part is trivial

```
fcgiwrap_enable="YES"
fcgiwrap_user="www"
nginx_enable="YES"
sshd_enable="YES"
```

Don't forget to configure your ssh to 
use public/private key authorization

Step 3: Configure nginx
to your /usr/local/etc/nginx/nginx.conf add host config

```
server {
                listen          80;
                server_name     hg.example.com;

                location ~ / {
                        fastcgi_pass    unix:/var/run/fcgiwrap/fcgiwrap.sock;
                        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;
                        fastcgi_param   SCRIPT_FILENAME /srv/www/example.com/hg/hgweb.cgi;
                        include         fastcgi_params;
                }

        }
```


here /srv/www/example.com/hg/hgweb.cgi is cgi script, that we will modify later

P.S.
This is just part of nginx.conf.... rest, is up to you... this is what you need to get hgweb work in nginx 

Step 4: Configure hgweb
/srv/www/example.com/hg/hgweb.cgi is modified copy of /usr/local/share/mercurial/www/hgweb.cgi

```
#!/usr/bin/env python
#
# An example hgweb CGI script, edit as necessary
# See also http://mercurial.selenic.com/wiki/PublishingRepositories

# Path to repo or hgweb config to serve (see 'hg help hgweb')

[red]config = "/srv/www/example.com/hg/hgweb.config"[/red]

# Uncomment and adjust if Mercurial is not installed system-wide:
#import sys; sys.path.insert(0, "/path/to/python/lib")

# Uncomment to send python tracebacks to the browser if an error occurs:
#import cgitb; cgitb.enable()

from mercurial import demandimport; demandimport.enable()
from mercurial.hgweb import hgweb, wsgicgi
application = hgweb(config)
wsgicgi.launch(application)
```
you need to adjust *config*, which points to config file for hgweb

/srv/www/example.com/hg/hgweb.config

```
[collections]
/srv/hg/repos/pub = /srv/hg/repos/pub

[web]
#contact = aldis@bsdroot.lv
#description = Mercurial repositories @ bsdroot.lv
style = gitweb
#allow_push = *
#push_ssl = false
allow_archive = bz2 gz
#base = repos
baseurl =
```
This is my own hgweb.config from my server
More details: http://mercurial.selenic.com/wiki/HgWebDirStepByStep
NOTE: make sure /srv/hg/repos/pub is www group readable

I use collections... that's why I didn't specify contact and description, here.
If you want to have contact and description for your projects, you will have to manually place .hg/hgrc in your repositories on server.
for example

```
[web]
contact = me@example.com
description = some description
```
If you don't do that, then it will be "unknown" (or something like that)
If you specify contact and description in hgweb.config these settings will become default for all repositories, that don't have .hg/hgrc
NOTE: you can also modify some other options as well (in .hg/hgrc)

Step 5: manage users
On your desktop create *hgadmin* repository
for users, that can only read/write repos make dir keys/users/[red]USERNAME[/red], replace USENAME of actual username of user, whose keys will be in this directory
for other admins keys/root/[red]USERNAME[/red]....
once you're done configuring hgadmin, cone it (for the first time, later just push it) to *ssh://hg.example.com/hgadmin*
`$ ht clone . [url=ssh://hg.example.com/hgadmin]ssh://hg.example.com/hgadmin[/url]`

for more info:
http://dev.lshift.net/paul/mercurial-server/docbook.html
NOTE:
mercurial-server on FreeBSD is pathced to use ${PREFIX}/etc/mercurialserver/ by default instead of Linux specific /etc/mercurial-server/ this can be controlled in hg home .mercurial-server

References
http://dev.lshift.net/paul/mercurial-server/docbook.html
http://mercurial.selenic.com/wiki/HgWebDirStepByStep

P.S.
This is very short description on how to setup mercurial hosting
Read references, they will help 

P.S.S.
When I have more time, and better mood, I will probably add more descriptive info

EDIT:
CURRENT PROBLEMS
refresh-auth isn't started automatically after pub keys are added/removed


----------



## graudeejs (Nov 7, 2010)

reserved


----------



## Ikinoki (Jul 5, 2013)

Why use fcgi at all? Isn't it easier to use a proxy to the gunicorn server? Fewer layers for the systems.


----------



## graudeejs (Jul 7, 2013)

Perhaps at that time it was not possible. Right now I can't answer since I don't own a server, so I don't do this stuff no more.


----------

