Differences between revisions 30 and 84 (spanning 54 versions)
Revision 30 as of 2008-04-07 21:06:32
Size: 13050
Editor: TomBa
Comment: Link to SharedSSH
Revision 84 as of 2013-09-01 10:59:38
Size: 292
Editor: PCOVerena
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
#pragma section-numbers 2
= Publishing Repositories with hgwebdir.cgi =

[[TableOfContents]]

== Introduction ==

Well, we have a certain setup with subversion. I'd like to reproduce it using Mercurial.

== Pre-requisites ==

The installed software is:
 * A webserver that can run CGI scripts such as apache2 (apache2, apache2-common, apache2-mpm-prefork, apache2-utils) or lighttpd
  * But it is not necessary (see below)
 * some version of mercurial (mine was 0.9 taken from Debian/unstable)
 * Python:
   * Ubuntu/Edgy comes with python 2.4
   * you will need the python2.4-dev package as well
 * sudo (in general, I prefer sudo to su)
 * hgwebdir.cgi (use the one coming with your Mercurial package or download from http://www.selenic.com/repo/hg-stable/raw-file/tip/hgwebdir.cgi)

== Getting proper Mercurial ==

The whole point was to try pull/push over http. So the following was done (I'm
a real newbie for hg, so please bear with me :)):
{{{
$ cd working-directory
$ hg clone http://selenic.com/hg/
$ cd hg
$ python setup.py build
$ sudo python setup.py install
}}}

This should work for every linux with python. But for rpm based systems it is better for administrative reasons to use it.
You can find some via [BinaryPackages]. I got mine like this:

{{{
$ cd download-directory
$ wget http://repos.opensuse.org/devel:/tools:/scm/openSUSE_10.2/x86_64/mercurial-0.9.3-3.1.x86_64.rpm
$ sudo rpm -ihv mercurial-0.9.3-3.1.x86_64.rpm
}}}

== RHEL4 Specific Instructions ==
["RHEL4HgWebDirSetup"]

== Windows Specific Instructions ==

On Windows, your Python version ''must'' match the version used to compile Mercurial. Otherwise, you'll get "Invalid Magic Number" errors when trying to run the CGI.

At least one installer for 0.9.5 uses Python 2.4. (I can't verify all of them.) If you do wish to use Python 2.5, you must build your own Mercurial WindowsInstall.

The first line of `hgwebdir.cgi` must point to your Python executeable. Ex:

{{{
#!c:/dev/Python25/python.exe
}}}

=== Mercurial Lib Files ===

Install the Mercurial libraries. The Windows binary puts a .zip file of the libraries in your Mercurial install directory, which I refer to as `MERCURIAL_HOME`.

Unzip `library.zip` (located in `MERCURIAL_HOME`) to a path of your choosing. (e.g. `MERCURIAL_HOME\lib`; for example: `c:\dev\Mercurial\lib`.)

Specify the location of the library files in `hgwebdir.cgi`
{{{
# adjust python path if not a system-wide install:
import sys
sys.path.insert(0, "c:/dev/Mercurial/lib")
}}}

If you compiled your own version of Mercurial, you do ''not'' need the `sys.path.insert` line.

=== Adjust Template Files ===

The CGI assumes templates are located inside of the `lib` directory you just created.

(Although you're supposed to be able to specify `templates = c:/dev/Mercurial/lib` in `Mercurial.ini` or `hgweb.config`, neither option worked for me.)

Move the `Templates` folder from my `MERCURAIL_HOME\Templates` to `MERCURIAL_HOME\lib\Templates`.

=== Other Gotchas ===

The path to your Mercurial repositories cannot also contain the name to the path to the Mercurial CGI. Maybe this is just my weird Apache setup, but when my `hgwebdir.cgi` was installed in `c:/webdata/repos`, this `hgweb.config` failed for me:
{{{
[paths]
repo1 = c:/webdata/repos.merc/images
repo2 = c:/webdata/repos.merc/web/htdocs/
}}}

and instead I had to change my directory names to

{{{
[paths]
repo1 = c:/webdata/merc.repos/images
repo2 = c:/webdata/merc.repos/web/htdocs/
}}}

I don't know if this is a Mercurial/Python issue or an Apache issue. Either way, hopefully this saves you some time.

I could not get `[collections]` to work properly with drive letters - using them on the left side causes no repositories to show up. But if your repositories are on the same drive as your CGI, you can do:

{{{
[collections]
\webdata\merc.repos = /webdata/merc.repos
}}}

The backslashes and forward slashes make a difference. This got all of my repositories to show up that were located in `c:/webdata/merc.repos`. See [http://www.selenic.com/mercurial/bts/issue852 this bug tracker issue] for details.

==== webdir.cgi Windows Bugs ====

'''Subdirecotries don't work in Collections'''

Repositories one sub directory below your root cause a 404 Not Found error - the Windows backslash gets converted to a `%5C` in the URL and the script interprets this as a request to a location that doesn't exist.

Example: URL `http://myserver/repos/hgwebdir.cgi/web%5Chtdocs/` causes a 404 Not Found.

Manually changing the `%5C` to a forward slash causes Mercurial to report that no repository exists: "The specified repository "web" is unknown, sorry."

0.9.5 Update: The 404 error is still present. If you change the backslash to a foward slash the CGI doesn't know how to look into the proper repository. Instead it gives you an "Unknown Repository" type message.

See [http://selenic.com/pipermail/mercurial/2007-December/016178.html this mailing list post] for more on the issue.

== Directory Structure ==

Create the necessary directories:
{{{
$ sudo mkdir -p /var/hg/repos
$ sudo chown -R www-data:www-data /var/hg
}}}

It's usually a good idea to keep special directories out of the tree served by apache, but for security reasons on openSUSE the cgi scripts only work within the document root. So for openSUSE, which uses user/group wwwrun/www instead of www-data/www-data and does not allow write acces to cgi directories for anyone but the apache user it is
{{{
$ sudo mkdir -p /srv/www/htdocs/hg/repos
$ sudo chown -R wwwrun:www /srv/www/htdocs/hg/repos
$ sudo chmod 755 /srv/www/htdocs/hg
}}}

== Preparing the config ==

{{{
$ cat > /tmp/hgweb.config
[collections]
repos/ = repos/
^D
$ sudo -u www-data cp /tmp/hgweb.config /var/hg
$ rm /tmp/hgweb.config
}}}

For openSUSE, replace the sudo line above with
{{{
$ sudo -u wwwrun cp /tmp/hgweb.config /srv/www/htdocs/hg
}}}

To get a look like on http://hg.kublai.com/ with subdirectories? Just create subdirectories with hg repositories in it. To get a look of the toplevel like on kublai, add the following to hgweb.config:
{{{
[web]
style = gitweb
}}}
This also works in repository hgrc's, which are mentioned below.

== Two possibilities ==
You can either use a separate webserver such as Apache or lighttpd, or use the webserver built into hg.

=== Using Apache or lighttpd with the hgwebdir.cgi script ===

==== Putting the right stuff in place ====

Put the script in place (remember, we are still in that `working-directory/hg` :)):
{{{
$ sudo -u www-data cp hgwebdir.cgi /var/hg
$ sudo -u www-data chmod +x /var/hg/hgwebdir.cgi
}}}

And again, some changes for openSUSE
{{{
$ sudo -u wwwrun cp /usr/share/doc/packages/mercurial/hgwebdir.cgi /srv/www/htdocs/hg
$ sudo -u wwwrun chmod +x /srv/www/htdocs/hg/hgwebdir.cgi
}}}

==== Configuring apache ====

Ok, now it's time for apache (see at the end of this paragraph for the openSUSE way of doing this).

First of all, do not really change the config of apache directly:
{{{
$ sudo mkdir /etc/apache2/hg
}}}

Create the config with the following contents (e.g by using `sudo vim /etc/apache2/hg/main.conf`):
{{{
ScriptAliasMatch ^/hg(.*) /var/hg/hgwebdir.cgi$1

<Directory /var/hg>
  Options ExecCGI FollowSymLinks

  AllowOverride None
</Directory>
}}}

This config says that we are going to serve our repositories through '<yourhost>/hg/'.

Now make it really available, by changing your favourite site in `/etc/apache2/sites-enabled`.
For this experiment I used `/etc/apache2/sites-enabled/default`:
{{{
  ...
  Include /etc/apache2/hg/main.conf
</VirtualHost>
}}}

Make sure that everything is OK:
{{{
$ sudo apache2ctl configtest
Syntax is OK
}}}

Restart your web server:
{{{
$ sudo apache2ctl stop
$ sudo apache2ctl start
}}}

Check if it works by directing your browser to `<yourhost>/hg/`


For openSUSE, just put this in /etc/apache2/conf.d/hg.conf

{{{
ScriptAliasMatch ^/hg(.*) /srv/www/htdocs/hg/hgwebdir.cgi$1

<Directory /srv/www/htdocs/hg>
  Options ExecCGI FollowSymLinks

  AllowOverride None
</Directory>
}}}

and run

{{{
sudo rcapache2 reload
}}}

if this does not complain about config errors you should be done.

==== Configuring lighttpd ====

Ok, now it's time for lighttpd (no openSUSE specifics, because I dont use it).

You can either update the existing /etc/lighttpd/lighttpd.conf file, or create /etc/lighttpd.conf/hg.conf and include that file from lighttpd.conf.

First, you need to check if mod_rewrite and mod_cgi are enabled in the config file, and add them to server.modules if they haven't already been added:
{{{
server.modules += ( "mod_cgi" )
server.modules += ( "mod_rewrite" )
}}}

Next, configure rewrite rules that map URLs to the hgwebdir.cgi script.
With the following added to your config file, URLs starting with either hg or mercurial will map to hgwebdir.cgi:
{{{
url.rewrite-once = (
  "^/hg([/?].*)?$" => "/hgwebdir.cgi$1",
   "^/mercurial([/?].*)?$" => "/hgwebdir.cgi$1"
)
}}}

Then, configure a URL match that invokes hgwebdir.cgi:
{{{
$HTTP["url"] =~ "^/hgwebdir.cgi([/?].*)?$" {
      server.document-root = "/var/hg/"
      cgi.assign = ( ".cgi" => "/usr/bin/python" )
}
}}}

Make sure that everything is OK:
{{{
$ sudo lighttpd -t -f /etc/lighttpd/lighttpd.conf
Syntax OK
}}}

Restart the web server:
{{{
$ sudo /etc/init.d/lighttpd restart
}}}

Check if it works by directing your browser to `<yourhost>/hg/` or `<yourhost>/mercurial/`

=== Configuring Lighttpd push support ===

To enable support for pushing to remote repositories, you are required to add an extra $HTTP check to your vhost. The command when pushing that requires authorization is 'unbunble', so what we do is check to see if it is within the URL:
{{{
...
$HTTP["querystring"] =~ "cmd=unbundle" {
                auth.require = ( "" => (
                        "method" => "basic",
                        "realm" => "Mercuial Repo",
                        "require" => "valid-user"
                        )
                )
        }
...
}}}

This example uses an Apache2 .htpasswd file, please read the Lighttpd documentation for examples of more such as digest.

=== Standalone ===

Simply run
{{{
sudo -u www-data hg serve --webdir-conf /var/hg/hgweb.config
}}}
and enjoy this speedy method of serving multiple repos. It should be faster than using Apache.

== You are done ==

Hooray!

== Final Bits ==

No openSUSE specifics here. You should know the differences by now (apache user and doc path).

=== Create a new repository ===

{{{
$ sudo -u www-data hg init /var/hg/repos/<repository-name>
}}}

=== Provide more information about it ===

Add the following to the `/var/hg/repos/<repository-name>/.hg/hgrc` file:
{{{
[web]
contact = Bilbo Baggins # Whom to contact, plain text,
                              # no fancy stuff
description = My precious! # Nice description what this is about,
                              # you can include HTML (like <a>)
}}}

=== Allow pushing to the repository ===

By default, nobody is allowed pushing.

To allow pushing to everybody, add the following line to the `/var/hg/repos/<repository-name>/.hg/hgrc` file:
{{{
[web]
allow_push = *
}}}

To allow only selected users to push changes, add the following line to the `/var/hg/repos/<repository-name>/.hg/hgrc` file:
{{{
[web]
allow_push = frodo, sam
}}}

These are virtual users (for instance, as defined using a .htpasswd file), and not real system users.

=== Deny pushing to the repository ===

Most likely you will want to use it together with `allow_push = *`. If you want allow pushing to everybody, but a selected list of people, add the following line to the `/var/hg/repos/<repository-name>/.hg/hgrc` file:
{{{
[web]
deny_push = saruman
}}}

=== Allow pushing only over a non-secure channel ===

(I still need to check how it works :) )

By default, pushes are allowed only over https. If you are certain and do not want to enforce https for pushes, add the following line to the `/var/hg/repos/<repository-name>/.hg/hgrc` file:
{{{
[web]
push_ssl = false
}}}

=== Customize the look ===

Add the following to the `/var/hg/repos/<repository-name>/.hg/hgrc` file:
{{{
[web]
style = gitweb # looks cleaner from my point of
                            # view :)
allow_archive = gz zip bz2 # If you think people should be able
                            # to download snapshots as .tar.gz,
                            # .zip, .tar.bz2 respectively
}}}

== Disclaimer ==

Well, it works (worked) for me. Please do not hesitate to update this page to
include small bits I've forgotten or just plainly am not aware of.

----
See also [:SharedSSH].

CategoryHowTo CategoryWeb
Electrical Engineer Landon Rozema from Balcarres, really loves pets, facebook and autographs. Was exceptionally encouraged after visiting [[http://www.merriam-webster.com/dictionary/defensive|Defensive]] Wall of Bellinzona. [[http://howtounlockipad3.com/?p=107|search engine optimization]]

Electrical Engineer Landon Rozema from Balcarres, really loves pets, facebook and autographs. Was exceptionally encouraged after visiting Defensive Wall of Bellinzona. search engine optimization

HgWebDirStepByStep (last edited 2018-11-26 18:38:58 by JordiGH)