Using SSH-Agent with Monotone

Monotone now has support for using ssh-agent to manage your monotone key as of 0.34. What this means is that you can type the password for your key once instead of every time that you run mtn. Intrigued? Here's how to do it:

Automatic

There are 2 ways to use ssh-agent with monotone. The easiest is to simply start up ssh-agent and let monotone add your key to the agent. This is as simple as running ssh-agent /bin/bash (replace /bin/bash with whichever shell you wish) and then work as normal. The first time monotone needs to sign something (such as when checking in a change) it will ask for your password then automatically add your key to ssh-agent. You can see this happening by running ssh-add -l. When you first start ssh-agent it will say that there are no keys. After monotone adds your key it will list the fingerprint of your key with the e-mail address you gave for the key's name.

Manual

You can also manually add your key to ssh-agent for use with monotone if you so desire. Run mtn ssh_agent_export ~/.ssh/id_monotone, type your key's password then enter a new password twice (or the same one, it's up to you), run chmod 600 ~/.ssh/id_monotone then run ssh-add ~/.ssh/id_monotone after starting ssh-agent as above. As before, monotone will automatically use your monotone key in ssh-agent and not ask for your password as long as you're logged in. After this all you will have to do is run ssh-add ~/.ssh/id_monotone after you start ssh-agent in the future and your key will be added.

FAQ

What if I have more keys in ssh-agent?

ssh-agent is generally used for holding private keys for use with ssh (as its name implies) so you may have some ssh keys in ssh-agent already. Monotone will only ever use a key that it also has in its key store (~/.monotone/keys). It will look through all of the keys in ssh-agent and only use one that matches the key you have chosen for use with monotone (--key option). Other keys will not be used.

Can I use the same key for SSH and monotone?

This is technically possible but it would currently require you to create your key in monotone, use mtn ssh_agent_export to export your key, extract the public key part for use in ~/.ssh/authorized_keys on remote hosts, and add your key to ssh-agent before sshing to them. In general this isn't worth the effort and it also just makes some sense to use different keys for these two very different purposes.

How can I make monotone not use ssh-agent?

Pass the --ssh-sign=no switch.

Why does mtn serve ask for my password even though my key is added to ssh-agent?

The serving code does some encryption that does not fit into ssh-agent's signing model and so requires you to enter your password so that monotone can use the key directly. This should change in time as monotone's security is changed.

ssh-agent and screen

This does not directly apply to monotone but is useful for those developers who use screen heavily. If you add the following to your .bash_profile your screen sessions will be able to use a forwarded ssh-agent when you reattach from a new ssh session:

if [ -n "$SSH_AUTH_SOCK" ]; then
    screen_ssh_agent="/tmp/${USER}-screen-ssh-agent.sock"
    if [ ${STY} ]; then
        if [ -e ${screen_ssh_agent} ]; then
            export SSH_AUTH_SOCK=${screen_ssh_agent}
        fi
    else
        ln -snf ${SSH_AUTH_SOCK} ${screen_ssh_agent}
    fi
fi

(copied from the third comment on http://woss.name/2005/08/17/using-ssh-agent-and-screen-together/)

Mac OS X and ssh-agent

There is a program called SSHKeychain for Mac OS X which makes using ssh-agent even easier. It not only automatically starts ssh-agent and sets the appropriate environment variables for you but can also save your keys' passwords in your Keychain. Unfortunately it does not currently (as of version 0.8.1) support the types of keys that monotone exports. This can be fixed with a simple patch:

Index: Libs/SSHKey.m
===================================================================
--- Libs/SSHKey.m   (revision 99)
+++ Libs/SSHKey.m   (working copy)
@@ -32,6 +32,8 @@
        return SSH_KEYTYPE_RSA1;
    else if ([[lines objectAtIndex:0] isEqualToString:@"-----BEGIN RSA PRIVATE KEY-----"])
        return SSH_KEYTYPE_RSA;
+   else if ([[lines objectAtIndex:0] isEqualToString:@"-----BEGIN ENCRYPTED PRIVATE KEY-----"])
+       return SSH_KEYTYPE_RSA;
    else if ([[lines objectAtIndex:0] isEqualToString:@"-----BEGIN DSA PRIVATE KEY-----"])
        return SSH_KEYTYPE_DSA;
    else