In my last post I talked about Gitolite, and how it works with Git to give you an administrative shell and master repository on a central server. An important point was doing the install, in order, with the second step being setting up your ssh connection. In this post, I want to cover what is going on under the hood when using an ssh connection with Gitolite.
If your going to create a server with a central repository, accessible over a TCP/IP connection, whether internal to the company, or to the world, you don't want to allow anyone to have access to that server, and you want your communications back and forth to be encrypted. You want your repositories to be secure. Setting up the encrypted communication channel between your local machine and the central server is what ssh does.
When installing Gitolite, we want to set up an encrypted communication channel between the Gitolite administrator's local machine, and Gitolite on the central server. Gitolite will not work unless it's ssh connection is set up properly.
The gotcha on this ssh install is that this is not a normal ssh connection. If your thinking, I'll just use Putty to establish my ssh connection to the central server from my local machine, something Putty specializes in doing, forget it. I will tell you now, if you use Putty, you will not believe the problems you will have with the Gitolite installation. Do not use Putty. Forget Putty. Let's talk ssh first, and you'll see why.
SSH Basic Concepts
What most folks don't know is that sending unencrypted logins and passwords over the Internet can be detected by a software application called a sniffer. Using a sniffer you can detect unencrypted network traffic, just like you were looking over the user's shoulder. This is combated by encrypting the transmissions with a group of encryption programs called OpenSSH. OpenSSH uses a public and private ssh key to ensure, you're allowed access to the server. Once the connection is set up it encrypts all your communications to and from the server. Git and Gitolite use OpenSSH to ensure that none of your code or data you pass to, or get from, the server can be captured by anyone else.
Ssh keys are generated, by you on your local machine, as a key-pair, a private and public key. The private key you always keep on your computer, letting no one else have access to it. It ensures you are you to the server. The private key is usually located in a .ssh directory on your computer, and usually has the name id_rsa with no extension on the end. The public key, which you place on the servers you would like to gain access to before attempting a connection, is initially in the same directory as the private key, and is called id_rsa.pub. The pub for public key.
The normal flow, using a program like Putty, is to initiate a connection by clicking on the server you want to go to in Putty. OpenSSH's ssh-agent loads and asks you for a passphrase (not a password). This is usually a long sentence you put in when you generate the keys. The passphrase is used on the local machine to verify you are the person that generated the keys on your computer, so no one else can use your keys to initiate a connection. The ssh-agent then uses your private key to generate a signature to send to the server. That particular signature is unique and generated only once. The next time a signature is needed, a completely new signature is generated.
The OpenSSH program sends the signature generated from your private key to the server, the server's OpenSSH sshd program pulls up your public ssh key, that you previously installed on the server, checks it against the signature it just received, and if its a match, opens up an encrypted channel between your local machine and a shell on the server. For the rest of the session, you have encrypted communications between your local machine and the server. On the server, the public keys are normally stored in the ~/.ssh directory in a file called authorized_keys. There could be many user's public keys in the authorized_keys file.
That's ssh in a very fast nutshell. Let's talk about Putty. There are several ssh protocols out there, SSH1, SSH2, and DSA. Putty normally uses DSA. Gitolite uses SSH2 RSA. They do not match, and you won't know that's the problem when the server rejects your Gitolite connection. It will drive you nuts. You should not use Putty to establish a connection with Gitolite. You can use Putty to open up a shell on the server, and knowing you need SSH2, 1024bits, RSA for Git and Gitolite, you can use a program like PuttyGenerate to export the ssh rsa keys, but it's best to generate the keys from the command line using "ssh-keygen -t rsa".
I said Gitolite's ssh set up is unique. What you want to accomplish is to have a user not login to the server using a username and password. And not ask for a passphrase on your local machine to log in to the server, but still have encrypted communications. What you want is, when using Gitolite, is to just type "git pull" or "git push," and that's it. The repository is copied to your local machine from the server, "git pull," or the repository is sent to the server, "git push," no logins and no passwords, and no shell. Gitolite will not grant you access to a shell on the server.
How do we do this? What goes on under the hood? There's a couple of things that have to happen. The first time you pull up the GitBASH shell on your local Window's machine, you may be asked for a passphrase for that session. This is the local machine verifying you, and not knowing what server you may want to use. A one time authentication, and that's it for the session. The ssh-agent from then on should take care of all your passphrase requirements for all your logins. This should not interfere with Gitolite's git push or git pull, but sometimes you go nuts trying to get rid of the passphrase when going to the Gitolite server.
Some more on the potential passphrase problem. When you connect to Gitolite on the server, you do it from your local repository, and the way to connect is with "git pull" or "git push." There is no way for you to gain access to a shell on the server to do something else, or something nasty, for example. All the Gitolite installs recommend not using a passphrase when you generate your ssh keys on your local machine for the gitolite administrator. I am in this camp. If someone else wants to log on to my machine, or sit down quickly when I take a bathroom break, more power to them, but their not going to mess up anything on the server. I think for the gitolite administrator's connection not to have a passphrase is acceptable. When you generate your keys, just hit a return and don't put in a passphrase during the install. If your system administrator, absolutely has to have a passphrase, put one in later with a -p ssh-keygen option. I do not recommend using one on the initial set up, it's just another area that may cause you problems.
Git needs to know your username and the server location to comunicate with your repository, for the "git pull" and "git push" commands. The username and repository server location are stored on your local machine in your .git/config file for each repository. If you open and look at the .git/config file on your local machine in what ever repository you're in, you'll see a heading called [remote "origin"] with the Gitolite username, and URL to the remote server for that repository. You also should see a heading for each branch in your repository, like [branch "master"].
What's left is the ssh hook up. Since Gitolite sits on top of the master Git repositories, and you have to go through Gitolite, it handles the authentication when using Git. The only thing being done on the server, as the Gitolite virtual user, is to run gitolite. Gitolite sets up an authorization file in ~/gitolite/home/.ssh. This authorization file is unique in that user's allowed to have access to the master repositories through Gitolite have their public keys in the authorized_keys file with a line appended to the beginning of the public key starting with "command." This is called a "forced-command," because it forces you to stay in the Gitolite shell and no where else.
When you grant access to a new user, on your local machine you put their public key, in the gitolite-admin/keydir directory after renaming it to the user's name, like aname.pub. You then commit and push that to the server's "bare" gitolite-admin repository on the server with a "git push."
A successful push does two things. First, the public key is put in the repositories ~/.gitolite/keydir directory on the server, this is used in combination with your ~/.gitolite/conf/gitolite.conf file to grant the user authorization to use various repositories. Second, the new user's public key is added to the ~/.ssh/authorized_keys file with a special forced-command header line. This sets up the encrypted communication channel, and the forced-command line causes any Git push or pull commands, to not use a shell, or login, and just transfer the encrypted repository. What we want. We're ready to do the actual Gitolite install, which I'll cover in the next article.