Setting up a Git Server on Windows Server 2008 R2 (using msysgit and WinSSHD)

My first attempt to use a remote Git repository on my Windows Server was to set up a WebDAV site and connect it as network drive on my PC. In principle this works well and the setup is quite fast and easy. The only problem was that it was really slow on my Win 7 machine. Unworkable slow. Even with this magic Auto-detect proxy settings turned off it didn’t improve very much. On Win XP it worked quite well though.
So that was the one of the main reasons why I decided to set up a Git remote repo over SSH. Unfortunately there were some hurdles to take to get this to work.

Basic Setup:

1. Go download and install WinSSHD on your Server. There’s a free version for personal use.

2. Configure WinSSHD. Set up the account(s) you want to use etc. This should be pretty straightforward, as it’s all self-explaining.

3. Now you should be able to connect from a remote client using simple password authentication. For example in Git Bash you can try to connect by typing

ssh username@server

If the connection works. Type ‘exit’ to disconnect and return to the bash

4. Since we don’t want to use password auth the next step is to generate a ssh key pair.
(You can configure the allowed auth types for users/groups in the advanced settings of WinSSHD)

$ ssh-keygen -t rsa -C "Comment" Generating public/private rsa key pair. Enter file in which to save the key (/c/Users/shoehle/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /c/Users/shoehle/.ssh/id_rsa. Your public key has been saved in /c/Users/shoehle/.ssh/id_rsa.pub. The key fingerprint is:c5:ed:1b:d1:40:94:5b:a1:6b:d1:76:a1:46:8b:7b:fc Comment

The -t specifies the type. In this case RSA with a default length of 2048 bit.
And with the -C parameter you can add a comment.
The default file path should be fine so just press enter at the first prompt.
Then choose a good passphrase for your key.

5. Import the public key (id_rsa.pub) in WinSSHD to the user account you want to connect with

6. At this point you should be able to connect to your SSH server with the key. If you type ‘ssh username@server’ again you should be able to connect with the key + passphrase.

Ok so these are the basic steps to connect with git to your sever through SSH.
Also if you don’t want to re-enter the passphrase everytime you connect, have a look at this help article from Github

If you now try to clone/push/pull/etc. from the server you will very likely get some errors.
Something like “git-upload-pack: command not found” or “myrepo.git does not appear to be a git repository” or similar.
To fix the first error you can specify the path to the upload/receive pack on the server with some additional parameters. But more on this later.
The second error is due to the command that msysgit tries to execute on the shell. It has single quotes instead of double(or no) quotes that enclose the path to the repository and therefore Windows can’t execute it properly and throws an error. To fix this we use sh.exe from msys.

[Update 05.08.2011]: Here’s a follow-up post that shows an easier way to set up the server. So you can skip the below sections.

Making Git work on the server:

1. If not already done, install msysgit on your server (I would recommend to install it directly to C:\Git or at least a path that has no spaces because I had some weird issues with “spaced” paths)

2. Add C:\Git\bin to the PATH variable. This is very important!! sh.exe and other dependencies are in this folder

3. Now go to C:\Git\bin and add the following two files

gup.sh grp.sh

4. Open gup.sh in your favorite editor and insert

C:/Git/libexec/git-core/git-upload-pack.exe $*

5. Open grp.sh and insert

C:/Git/libexec/git-core/git-receive-pack.exe $*

The $* essentially rips off the single quotes from the repository path argument, so a path that has spaces in it won’t work here either I guess

Basically we’re done now and all git operations from the client should work.
For a clone you have to type

git clone -u 'sh gup.sh' ssh://username@server/path/to/myrepo.git

or a push would be

git push --exec 'sh grp.sh' ssh://username@server/path/to/myrepo.git

but that is not very elegant.

Cleaning things up:

1. At first we want to get rid of the whole repo path by specifying a remote alias

git remote add origin ssh://username@server/path/to/myrepo.git

Where “origin” would be the alias name

2. Next we set the config for the git-upload-pack and git-receive-pack so we don’t have to reference the shell script all the time.

git config remote.origin.uploadpack 'sh gup.sh'

and

git config remote.origin.receivepack 'sh grp.sh'

That’s it. Now we can use the normal git commands without any additional parameters:

git clone origin git push origin master git pull origin ...

Hurray!

Alternatively I could have gone with Cygwin + OpenSSH of course and there are some tutorials out there on how to set this up, but I don’t want to have the unnecessary Cygwin bloat on the server unless I really need to. Also these Cygwin tutorials seemed to be much longer than the approach I took.

%d bloggers like this: