Your company wants a centralized code repository, and you like git. Git is not normally centralized, although neat services like GitHub are out there. While GitHub is awesome, and I use it (and so should any developer that would like to do work that is public or otherwise), the affordable multiseat license that is online is, well, online, and the multiseat license that you can get for offline work is really expensive. Some smaller organizations might scoff at this, some for understandable reasons, others less so, but I’m not here to get into those symantics. What I want to do is describe how you can get something up and running that has a centralized git service that might work a lot like GitHub, although it might be missing some of its nicer features (but it might have some other features you might like). For this first post, we are going to set up gitolite and get it running the kind of hard/kind of easy way. In later posts, I’ll add in front ends that will make accessing and using gitolite easier.
Edit: This is the first in a four part series about gitolite and Redmine, ending with full automation. The other articles are:
- Setting up the Redmine Front End
- Integrating Redmine and Gitolite
- Fully Automating the Redmine Gitolite Integration
Ok, let’s continue…
Gitolite, available at https://github.com/sitaramc/gitolite in its rawest form, is one way to get it, also this can be done using apt-get in Ubuntu. Doing things the hard way is often the best, and will give you the most understanding, and then meandering down the road to the easy way later on will make you very effective if you have to do it the hard way later. Just like those damn Calculus classes that you took in college, or not if that isn’t what tickled your fancy. What we are going to do then, is build this from scratch, do a full installation of it, and go through step by step. Perhaps, if it tickles my fancy, I’ll produce the ‘easy’ way later, and you can decide what you want to do.
I would suggest that you do all practice work in a VM. The easy way is to get an Ubuntu 12.04 ISO and VirtualBox and get that up and running. KVM is good, but I think it’s a little harder. I can cover that later. Either way, get onto a box where you have sudo access and get ready to do some real work.
Now let’s pretend that you have little to no idea what you are doing (hell, I have no idea what I’m doing most of the time anyhow). The reality is, the vast majority of our work is guesswork and the vast majority of the time, we don’t have time to figure out the ins and outs of every little thing that we put into place in any one organization. I’ll try to make sure that I put up appropriate headers for all of the actions that I am taking so that parts can be skipped over. If you want to do this the easy way, you can wait for me to throw up an easy tutorial, or you can look for another online (especially one with redmine integration, which you can find around).
The hard way of getting gitolite up and running is to complete the following steps:
- Create the necessary gitolite user and appropriate home directories for storing the repositories.
- Download gitolite.
- Install gitolite.
- Create an ssh key for the administration of gitolite.
- Initialize gitolite with new repositories and the created ssh key.
- Create a new user ssh key.
- Install the user ssh key with gitolite, and create your first repository.
- Modify the repository with the user key.
After all of these steps, you will have a difficult to work with centralized git repository. I shouldn’t say that it is necessary difficult, as much as I mean that the creation of new users who can use the centralized repos isn’t easily automated, like it would be if you set up a redmine plugin or had a GitHub account (once again the easiest solution). I should stop here and say – if you are just somebody who is writing something up that they want to make public someday, just go ahead and start on GitHub now instead. Nobody is going to look at it when it isn’t good, and it is likely nobody will see it when it is either. You shouldn’t care, really. Heck, if someone does notice and likes the idea, perhaps they’ll start helping you out on it and you’ll have a excellent repo and an item for your development portfolio. Don’t be shy, don’t be embarrassed, just do it. There are only a couple of good reasons that you should complete this tutorial and use private repos:
- You never plan on making your code public.
- You are working for an organization that needs their code to be private.
- Dropbox is not a viable alternative for storing your repo (more than one person working on it).
- A simple localized repo is just not good enough for you.
OK, I’ve spoken my peace and you still want gitolite. That’s fine, I just wanted to make absolutely positive first.
Get onto your server and get your sudo commands ready for execution, because we’re about to cook a turkey.
Create the gitolite user
The gitolite user that we will create will end up having the same home directory location as if we had set it up using dpkg-reconfigure in Ubuntu: /var/lib/gitolite/ (sorry if you don’t know what I mean by dpkg-reconfigure. In a future tutorial using apt-get I’ll make more sense of it). Here is the command that we will use to create the user:
$ sudo useradd gitolite --home-dir=/var/lib/gitolite/ --create-home --shell=/bin/bash
This command basically says that it will create a user gitolite, without a password (because we didn’t create one), with the home directory /var/lib/gitolite/, created now, and using the shell bash. If you are unfamiliar with all of this, you should spend some time with the man page for useradd. If you don’t know how to access a man page, I’m starting to think you should probably pick up the Ubuntu Server Book now and spend some time with it, or if you are cheap or uneasy with that, use the following command:
$ man useradd
For more information about adding users to a server.
Gitolite is sourced on, well, what else? GitHub. There is almost irony there, but I’m not really sure. The entire concept of irony and when something is and isn’t irony really confuses me, but I digress.
If you are working on an Ubuntu box, and you don’t have git installed, then now you need to install it so that you can get the source code. If you are on an Ubuntu server, then this would look something like:
$ sudo apt-get install git-core
And now git commands should start working. Installing git for other systems is outside the scope of this tutorial. I mean, really, I have to draw the line someplace. Now, we need to find the download link for gitolite. Starting at the url listed earlier: https://github.com/sitaramc/gitolite, we will notice the read only access links https://github.com/sitaramc/gitolite.git and git://github.com/sitaramc/gitolite.git. Either of these should be fine. We will clone one using:
$ git clone git://github.com/sitaramc/gitolite.git
This will create a new directory ‘gitolite’ with all of the gitolite goodness in it.
There is a quick install/setup guide here: http://sitaramc.github.com/gitolite/qi.html that you can look at. Unfortunately, it doesn’t have a ton of detail. I went ahead and took a chance and ran:
$ gitolite/install --help
And got a big list of output that you might even want to look at yourself. I won’t post it here because I’m lazy, but because I don’t want you to be lazy. Either way, after trying to work out the command, I eventually stumbled through the docs to this: https://github.com/sitaramc/gitolite/blob/master/doc/install.mkd and ended up running the following:
$ sudo gitolite/install -ln /usr/local/bin
Now I guess that gitolite is ‘installed’, as now there is a new file /usr/local/bin/gitolite in that directory.
The next part of the setup is having the user gitolite setup the initial repositories for administration of gitolite. The gitolite user, created without a password, can be accessed via sudo:
$ sudo su - gitolite
As this user, we need to run the setup commands for gitolite. But before we do so, we need to have access to a private/public key pair. If you know what this is, then skip the following section. If not, please read on.
Create an SSH key for administration of gitolite
Most requests for information from repositories using git involve the use of ssh. It is arguably the most secure way to get at that repository as well. Herein lies a problem, though, as well: the user that administers git under gitolite (and others for that matter) is always the same person for all of the repositories. This means that if I have repository ‘psalcido’ under user ‘gitolite’ and I want to give someone else access to that same repository, I need to give them access to the gitolite password to log in to get at the repo. No good. Especially because gitolite doesn’t even have a password, so how can it be accessed from elsewhere?
Well, we have one answer: create a user with sudo access on the same box and use
sudo su - gitolite but that isn’t going to help us with anything automated, just like pulls from gitolite will have to be. Thus we need to use ssh key pairs. What ssh key pairs do is allow you, from a given computer with the private half of a given key pair, to login as a user on another computer where they have decided to authorize the use of that key by installing the public key. Basically, the authorized_keys file on the server is the lock, and your private key is the key. The user on the server can accept many keys on their lock, but the only way that you can get your key to work in that lock is by getting your key authorized first. Thus, anyone that is going to want to do administrative work on gitolite will have to get access to the private key in this case.
If you are new to ssh keys, just remember to protect your private key, and/or password protect it.
For this tutorial, we are going to make an unencrypted private key, which means you won’t have to enter a password to use it. You can encrypt the key here, but then that same key can’t be used by most administrative consoles.
Now, as user gitolite, run the following:
And accept all of the defaults, and nothing for the passwords, and you will have an unencrypted key pair in /var/lib/gitolite/.ssh in the files id_rsa.pub (the public key) and id_rsa (the private key).
Way too much explanation for something that simple.
Initialize gitolite with new repositories
Now we need to initialize gitolite. I tried to do this immediately here, with the command:
$ gitolite setup -pk /var/lib/gitolite/.ssh/is_rsa.pub
And I ended up with the following:
Initialized empty Git repository in /var/lib/gitolite/repositories/gitolite-admin.git/ Initialized empty Git repository in /var/lib/gitolite/repositories/testing.git/ WARNING: /var/lib/gitolite//.ssh/authorized_keys missing; creating a new one
Which is resolved simply enough with:
$ touch ~/.ssh/authorized_keys $ chmod 0600 ~/.ssh/authorized_keys
Which creates the ‘lock’ mentioned in the previous section about creating ssh keys. Now we run the same setup command again and get:
$ gitolite setup -pk /var/lib/gitolite/.ssh/id_rsa.pub
And now we see no output, because the base setup repositories have already been created in the actions above, so we are very much in the clear and ready to move on. I’m not going to spend a huge amount of time here, but you might want to view the file
~/.ssh/authorized_keys, as I learned a ton about the file by looking at it after having this setup run (actually, back when gitosis was the standard, I caught it, but still, basically the same game).
Create a new user ssh key
Your main user for this VM is going to need the ability to do work on a new repository. We’re going to set them up with a new ssh key pair and get that key installed for use in gitolite. My user is psalcido, but yours is probably someone different. I’m going to write up this section and when you see
gitolite$, you should be able to tell who is running what.
First, I’m going to create a key pair for my user:
You may choose whatever options you like in this case. Now, I need to make the public key available to gitolite. Please note that nobody (except root) can look in my .ssh directory. If you open up permissions on your .ssh directory, then ssh will refuse to use it. Due to this, gitolite can’t see the public key. Thus, I’m going to move it someplace where it can be seen by everyone, and gitolite, then make sure users have permissions to open the file using chmod (see
$ man chmod for more information). Nobody can harm you by having access to your public key, but please keep your private key safe.
psalcido$ cp ~/.ssh/id_rsa.pub /tmp/psalcido_id_rsa.pub psalcido$ chmod 0666 /tmp/psalcido_id_rsa.pub
Install the user ssh key with gitolite, and create your first repository
Now that we have gitolite all set up, the actual way that you add users to gitolite is by cloning the gitolite administrative repository and doing the necessary modifications to it. It will then setup everything that it needs to automagically. Of course, that is unfair to leave at that, but there is a significant amount of documentation already out there to help you in what it does and how that works in the gitolite GitHub repository (are you sure you don’t want to just go ahead and use GitHub yet? Just checking).
Currently, the only user that has gitolite administrative access is the user gitolite. Log in as gitolite, and run the following:
gitolite$ git clone gitolite@localhost:gitolite-admin.git
And with that you should have the admin repository in the gitolite home directory. Under this directory, you will see the following files:
The data in gitolite.conf looks like:
repo gitolite-admin RW+ = id_rsa repo testing RW+ = @all
What this basically says is that anyone who has the private key for id_rsa.pub can modify gitolite-admin (in this case, that is only the user gitolite on the local box), and anyone who has a key match for any repository can modify the repository ‘testing’. Here, we will set up a new repo ‘psalcido’, install the new key, and give the key psalcido_id_rsa permission to view the data in the new repository. We will add on the following lines at the end of the file gitolite.conf:
repo psalcido RW+ = psalcido_id_rsa
Then we will add the key from /tmp/ to the repository under the key directory:
gitolite$ cp /tmp/psalcido_id_rsa.pub ~/gitolite-admin/keydir/psalcido_id_rsa.pub
A git status for the gitolite-admin clone should now return:
# On branch master # Changes not staged for commit: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: conf/gitolite.conf # # Untracked files: # (use "git add ..." to include in what will be committed) # # keydir/psalcido_id_rsa.pub no changes added to commit (use "git add" and/or "git commit -a")
Now I need to commit and push these changes into the administrative repository.
gitolite$ cd ~/gitolite-admin/ gitolite$ git add * gitolite$ git commit -m "Adding user psalcido to the repo, adding repo psalcido."
At this point you might get errors about git config. Run the commands that git requests for configuration and retry the commit. The following messages should occur:
[master 8f9e41c] Adding user psalcido to the repo, adding repo psalcido. 2 files changed, 4 insertions(+) create mode 100644 keydir/psalcido_id_rsa.pub gitolite@ansible-dev:/var/lib/gitolite/gitolite-admin$ git push Counting objects: 10, done. Compressing objects: 100% (5/5), done. Writing objects: 100% (6/6), 854 bytes, done. Total 6 (delta 0), reused 0 (delta 0) remote: Initialized empty Git repository in /var/lib/gitolite/repositories/psalcido.git/ To gitolite@localhost:gitolite-admin.git f01acb3..8f9e41c master -> master
If you are normally accustomed to seeing git response messages, the message
remote: Initialized empty Git repository in /var/lib/gitolite/repositories/psalcido.git/ and after should really jump out at you, as these ‘hooks’ are actually creating the repository and giving the user ‘psalcido’ access to those directory (or, really, they are giving access to the private key that is owned by the user psalcido).
Modify the repository with the user key
Now we need to login with the user psalcido, and try to clone and commit to the new repository.
psalcido:~$ git clone gitolite@localhost:psalcido.git
We should end up with a warning about cloning an empty repository. If we do, it means that everything has worked so far. Now I’m going to create a readme file and try to commit to it.
psalcido$ cd psalcido psalcido$ echo "This is a test commit" >> README psalcido$ git add * psalcido$ git commit -m "Initial commit" psalcido$ git push origin master
Done! You now know how to create new users, set up the ssh keys for those users, and get gitolite working in general. It is actually pretty easy from here on out.