ssh troubleshooting and tips

This page must be read in full the first time. If you start from some nice looking section in the middle it may not help you unless you're already an expert at ssh.

This page should help you troubleshoot ssh-related problems in installing and accessing gitolite. It also has a section of random ssh-related tips and tricks that gitolite can do.



naming conventions used

taking stock -- relevant files and directories

normal gitolite key handling

Here's how normal gitolite key handling works:

common ssh problems

Since I'm pretty sure at least some of you didn't bother to read the "IMPORTANT: PLEASE READ FIRST" section above, let me take a minute to point you there again. Especially the first bullet.

Done? OK, read on...

The following problem(s) indicate that pubkey access is not working at all, so you should start with appendix 1. If that doesn't fix the problem, continue with the other appendices in sequence.

The following problem(s) indicate that your pubkey is bypassing gitolite and going straight to a shell. You should start with appendix 2 and continue with the rest in sequence. Appendix 5 has some background info.

step by step

Since I'm pretty sure at least some of you didn't bother to read the "IMPORTANT: PLEASE READ FIRST" section above, let me take a minute to point you there again. Especially the first bullet.

Done? OK, now the general outline for ssh troubleshooting is this:

random tips, tricks, and notes

giving shell access to gitolite users

Thanks to an idea from Jesse Keating, a single key can allow both gitolite access and shell access.

(v3.6.1+) There are two ways to do this, both require uncommenting and editing the 'Shell' line in the ENABLE list in the rc file.

If you have only a few users who need to get shell access, edit the line to look like this (note the trailing comma!):

'Shell alice bob',

If you have lots of users, add them to some file accessible to gitolite, (one per line, no extra whitespace), then specify the full path of the file. For example:

"Shell $ENV{HOME}/",

(Note in this case we have to use double quotes since we are using a variable that needs to be interpolated into the value).

Then run gitolite compile; gitolite trigger POST_COMPILE or push a dummy change to the admin repo.


If you're using gitolite v3.6 or below, it's slightly different. You have to enable the trigger by uncommenting the 'Shell' line in the ENABLE list, but you cannot list the users directly on the 'Shell' line in the rc file, nor can you put the file name on that line. Instead, you have to go to the variables section in the rc file and set the SHELL_USERS_LIST variable to the filename. For example:

SHELL_USERS_LIST        =>  "$ENV{HOME}/",

Then run gitolite compile; gitolite trigger POST_COMPILE or push a dummy change to the admin repo.

NOTE: to maintain backward compatibility, this method will continue to work in 3.6.*, but when 3.7 is released (whenever that may be), it will not work, and you will have to use the new syntax described above.

distinguishing one key from another

Since a user can have more than one key, it is sometimes useful to distinguish one key from another. Sshd does not tell you even the fingerprint of the key that finally matched, so normally all you have is the GL_USER env var.

However, if you replace


in the ENABLE list with

'ssh-authkeys --key-file-name',

then an extra argument is added after the username in the "command" variable of the authkeys file. That is, instead of this:

command="/home/g3/gitolite/src/gitolite-shell u3",no-port-forwarding,...

you get this:

command="/home/g3/gitolite/src/gitolite-shell u3 keydir/",no-port-forwarding,...

You can then write an INPUT trigger to do whatever you need with the file name, which is in $ARGV[1] (the second argument). The actual file is available at $ENV{GL_ADMIN_BASE}/$ARGV[1] if you need its contents.

simulating ssh-copy-id

don't have ssh-copy-id? This is broadly what that command does, if you want to replicate it manually. The input is your pubkey, typically ~/.ssh/ from your client/workstation.

[Actually, sshd requires that even directories above ~ (/, /home, typically) also must be go-w, but that needs root. And typically they're already set that way anyway. (Or if they're not, you've got bigger problems than gitolite install not working!)]

problems with using non-openssh public keys

Gitolite accepts public keys only in openssh format. Trying to use an "ssh2" key (used by proprietary SSH software) will not be a happy experience. src/triggers/post-compile/ssh-authkeys can be made to detect non-openssh formats and automatically convert them; patches welcome!

The actual conversion command, if you want to just do it manually for now and be done with it, is:

ssh-keygen -i -f /tmp/ssh2/ > /tmp/openssh/

then use the resulting pubkey as you normally would in gitolite.

windows issues

On windows, I have only used msysgit, and the openssh that comes with it. Over time, I have grown to distrust putty/plink due to the number of people who seem to have trouble when those beasts are involved (I myself have never used them for any kind of git access). If you have unusual ssh problems that just don't seem to have any explanation, try removing all traces of putty/plink, including environment variables, etc., and then try again.

Thankfully, someone contributed this.

appendix 1: ssh daemon asks for a password

NOTE: This section should be useful to anyone trying to get password-less access working. It is not necessarily specific to gitolite, so keep that in mind if the wording feels a little more general than you were expecting.

You have generated a keypair on your workstation (ssh-keygen) and copied the public part of it (~/.ssh/, by default) to the server.

On the server you have appended this file to ~/.ssh/authorized_keys. Or you ran something, like the gitolite setup step during a gitolite install, which should have done that for you.

You now expect to log in without having to type in a password, but when you try, you are being asked for a password.

This is a quick checklist:

appendix 2: which key is which -- running sshkeys-lint

The sshkeys-lint program can be run on the server or the client. Run it with '-h' to get a help message.

On the server you can run gitolite sshkeys-lint and it will tell you, for each key in the admin directory's keydir, what access is available. This is especially good at finding duplicate keys and such.

To run it on the client you have to copy the file src/commands/sshkeys-lint from some gitolite clone, then follow these steps:

Note that it is not trying to log in or anything -- it's just comparing fingerprints as computed by ssh-keygen -l.

If the pubkey file you're interested in appears to have the correct access to the server, you're done with this step.

Otherwise you have to rename some keypairs and try again to get the effect you need. Be careful:

typical cause(s)

The admin often has passwordless shell access to git@server already, and then used that same key to get access to gitolite (i.e., copied that same pubkey as and ran gitolite setup on it).

As a result, the same key appears twice in the authkeys file now, and since the ssh server will always use the first match, the second occurrence (which invokes gitolite) is ignored.

To fix this, you have to use a different keypair for gitolite access. The best way to do this is to create a new keypair, copy the pubkey to the server as, then run gitolite setup -pk on the server. Remember to adjust your agent identities using ssh-add -D and ssh-add if you're using ssh-agent, otherwise these new keys may not work.

appendix 3: ssh client may not be offering the right key

appendix 4: ssh host aliases

(or "making git use the right options for ssh")

The ssh command has several options for non-default items to be specified. Two common examples are -p for the port number if it is not 22, and -i for the public key file if you do not want to use just ~/.ssh/id_rsa or such.

Git has two ssh-based URL syntaxes, but neither allows specifying a non-default public key file. And a port number is only allowed in one of them. (See man git-clone for details). Finally, hosts often have to be referred with IP addresses (such is life), or the name is very long, or hard to remember.

Using a "host" para in ~/.ssh/config lets you nicely encapsulate all this within ssh and give it a short, easy-to-remember, name. Example:

host gitolite
    user git
    port 22
    identityfile ~/.ssh/id_rsa

Now you can simply use the one word gitolite (which is the host alias we defined here) and ssh will infer all those details defined under it -- just say ssh gitolite and git clone gitolite:reponame and things will work.

(By the way, the 'port' and 'identityfile' lines are needed only if you have non-default values, although I put them in anyway just to be complete).

more than one keypair

If you have more than one pubkey with access to the same server, you must use this method to make git pick up the right key. There is no other way to do this, as far as I know.

A typical example would be if you wanted shell access to the gitolite server using one keypair, and gitolite-mediated access using another. Here's how I do that, where my "id_rsa" keypair has shell access, and my "sitaram" keypair has gitolite access:

host gitolite
    user git
    port 22
    identityfile ~/.ssh/sitaram

host gitolite-sh
    user git
    port 22
    identityfile ~/.ssh/id_rsa

Then I would use "ssh gitolite-sh" to get a command line, and use the host alias "gitolite" in git clone and other commands, as well as for gitolite commands (like "ssh gitolite info").

Just to be clear, please note that this assumes the authorized keys file on the gitolite hosting user has my "" line, without the gitolite related forced command and options.

appendix 5: why bypassing gitolite causes a problem

When you bypass gitolite, you end up running your normal shell instead of the special gitolite entry point script gitolite-shell.

This means commands (like 'info') are interpreted by the shell instead of gitolite.

It also means git operations look for repos in $HOME.

However, gitolite places all your repos in ~/repositories, and internally prefixes this before calling the actual git command you invoked. Thus, the pathname of the repo that you use on the client is almost never the correct pathname on the server. (This is by design. Don't argue...)

This means that, you get 2 kinds of errors if you bypass gitolite