I’ve used Subversion and TortoiseSVN for quite a while, and even have the free Standard Edition of VisualSVN Server set up on my Windows Home Server, but I wanted to see what Mercurial was like. Having tried TortoiseHg and thoroughly enjoyed using it, I decided to make the complete switch. There are several blogs that have covered some of the parts of setting up Mercurial and hgwebdir, notably by eWorld.UI by Matt Hawley, DJMatty and Vampire Basic. My impression, however, is that these were written by folks who assumed a fair amount of pre-existing knowledge about Python and/or had a different configuration in mind. I really have no Python experience, so it was a bit more of a struggle to get all the right pieces in place. Further, I particularly wanted to be able to use Windows Home Server to securely host my repositories for both home and remote use under an “hg” virtual directory. This particular configuration didn’t seem to be covered in any one definitive source.
What follows is a step-by-step guide to installing and configuring Mercurial on Windows Home Server (Windows 2003 Server and IIS6), including setting up hgwebdir to serve (via WSGI) the repositories from a virtual directory under the default WHS web site. It assumes that you’ve already got your Home Server up and running, and can see it from elsewhere (i.e. “http://yourdomain.homeserver.com” resolves correctly to your server, and shows the WHS home page).
Get the software
While you can use TortoiseHg as a way to get both a nice GUI interface (hgtk.exe) and a command-line interface (hg.exe), you can’t use TortoiseHg if you want to serve repositories via hgwebdir. Instead, you’ll need Python itself, the PyWin32 library, Mercurial, the ISAPI-WSGI shim, and the hgwebdir_wsgi entrypoint. Making matters somewhat more complicated, you have to ensure that the versions of all of these components match. At the time I went through this. Mercurial was based on Python 2.6, not 2.7, so that was the limiting factor. Here are the current matching versions at the time of this posting:
Install the software
Fortunately, the installers for Python and the other tools all seem to do the right thing if you install them in the order above. I kept the default settings, which resulted in Python installing into C:\Python26, and the remaining components finding Python and adding to it.
The normal hgwebdir configuration uses a directory for hosting the hgwebdir interface, and another directory (or several) for the repositories themselves. For ease of maintenance, I made both of these “Shared Folders” in WHS so that I could get automatic folder duplication, and also edit them after-the-fact without having to fire up the WHS Console. You will need the Console to get started, however. From the Console, go to Shared Folders and create two new shared folders: “HgWeb” for hgwebdir, and “HgRepositories” for the repositories. I gave myself “Full” access to each of these, and “None” access for everyone else.
Next, you’ll need to populate “HgWeb” with the hgwebdir scripts and configuration. Download hgwebdir_wsgi.py directly from the web-hosted repository for Mercurial itself and put it in “HgWeb”. (You can also browse the whole repository at http://selenic.com/repo/hg-stable/, which shows off some of the functionality you can look forward to!) The only change I needed to make was to line 40 from:
hgweb_config = r'c:\src\iis\hg\hgweb.config'
hgweb_config = r'D:\shares\HgWeb\hgweb.config'
Once hgwebdir_wsgi.py is in place, you can use it to create the ISAPI shim that you’ll need later when configuring IIS. From the command line, simply run the script in Python:
D:\shares\HgWeb> C:\Python26\python.exe hgwebdir_wsgi.py
This will create “_hgwebdir_wsgi.dll”, the ISAPI shim that runs Python and passes control back to the script. Note that you don’t have to re-generate the DLL when you change the script; apparently the DLL simply looks for the script and runs it (and manages Python’s lifetime, and that sort of thing).
You should also copy the hgwebdir style templates into “HgWeb”. You can find these from your Mercurial installation. For me, this meant copying the entire “templates” directory into “HgWeb” from “C:\Python26\Lib\site-packages\mercurial”. Some instructions mentioned expanding a “Library.zip”, but I found that this is entirely unnecessary.
The last thing to set up in “HgWeb” is to create “hgweb.config”. Mine looks like:
templates = D:\shares\HgWeb\templates
style = monoblue
allow_archive = gz, zip, bz2
/ = D:\shares\HgRepositories\*
Before configuring IIS, I also created a sample repository under “HgRepositories”. You can create a “test” directory and “hg init” it, or use TortoiseHg, or copy in an existing repository if you have one.
Local user configuration
One tip I got from DJMatty’s blog pointed to a Dave Burke post about setting an Application Pool identity in IIS6. In order to reduce the attack surface that might be opened in hgwebdir, I decided to create an all-new “MercurialWeb” user:
Run “lusrmgr.msc” (Local Users and Groups).
Create a new user named “MercurialWeb”, with some password (you’ll need to remember it!).
Uncheck the “User must change password at next logon” option.
Check the “User cannot change password” option.
Check the “Password never expires” option.
Select the newly-create user from the list, and open it.
Switch to the “Member Of” tab.
Click “Add”, and add the “IIS_WPG” group.
Click “OK” and then close the Local Users and Groups window.
Now you need to add the “MercurialWeb” user to the security settings for both “HgWeb” and “HgRepositories”. In “HgWeb” give it “Read & Execute”, “List Folder Contents”, and “Read” permissions. In “HgRepositories”, give it all of the same, plus add “Modify” and “Write” if you want to be able to push changes in. (If so, you’ll also end up needing to add the “allow_push” setting to “[web]” section of “hgweb.config” or to the configuration of individual repositories as needed.)
Update: I ran into a problem where the “MercurialWeb” user I created lost its permissions from the two shared folders. It turns out that WHS will reset the permissions on shared folders on occasion (see here). The way around this is to create the “MercurialWeb” user from within the WHS Console. You can then use WHS’s interface to grant “Read” permissions on “HgWeb”, “Full” permissions on “HgRepositories”, and “None” permissions on everything else. Since WHS knows about this user, it won’t remove its permissions!
Finally, we’re ready to configure IIS. Start up IIS Manager and expand the “Application Pools” node. We’ll start by creating a “Mercurial” pool using default settings. Then open its properties and change its identity so that it runs as the “MercurialWeb” user created in the last section.
Next, switch to the “Web Sites” node and select the “Default Web Site”. Create a new virtual directory, named “hg” that points to your “HgWeb” directory (“D:\shares\HgWeb” in my case), and give it “Read” and “Execute” permissions. Once it’s created, open up its properties, and:
- Change the application pool to “Mercurial”.
- Change the application name to “hg”.
- Click the “Configuration…” button.
- Click “Insert…” to add a wildcard application map.
- Type the path to the generated ISAPI DLL, “D:\shares\HgWeb\_hgwebdir_wsgi.dll”.
- Uncheck the “Verify that file exists” option. This is important!
- Click “OK”.
- Click “OK” to close the Application Configuration window.
- Switch to the “Directory Security” tab.
- Click the “Authentication and access control” section’s “Edit…” button.
- Disable the “Enable anonymous access” option.
- Enable the “Basic authentication” option.
- Click “OK”.
- Click the “Secure communications” section’s “Edit…” button.
- Enable the “Require secure channel (SSL)” option. Since Basic authentication sends passwords “in the clear”, requiring SSL will ensure that this is only done inside an encrypted channel.
- Click “OK”.
- Click “OK” to close the “hg” virtual directory’s properties.
There’s still one more important step before everything will work. You have to tell IIS that the newly-added ISAPI DLL is actually allowed to run:
- Click on the “Web Service Extension” node in IIS Manager.
- Click the “Add a new Web service extension…” link.
- Type “Mercurial WSGI shim” for the Extension name.
- Click the “Add…” button to add the required files.
- Type the path to the WSGI shim DLL (“D:\shares\HgWeb\_hgwebdir_wsgi.dll”).
- Click “OK”.
- Check the “Set extension status to Allowed”.
- Click “OK” to close the New Web Service Extension window.
And you’re done!
Test it out!
Now, if you point your browser at “https://yourdomain.homeserver.com/hg”, you should get a prompt for your WHS credentials (home username and password), and then you’ll see the list of repositories that hgwebdir knows about.