Capistrano Series - Setting up Git

So now the Slice is setup and ready for our Ruby on Rails with Capistrano stack.

Let's get straight on and install git and set up a repository.


The What

What we're going to do is securely setup a git repository under it's own user account. Then we will secure the shell on this account, allowing us to give others access to the repository using standard SSH keys without them having full shell access to the Slice.

Assumptions

The only assumptions made for these articles are:

1: You are running Ubuntu Hardy (The instructions may work on other distros but it has not been tested and is not guaranteed)

2: You have followed the setup articles: page 1 and page 2

Installing Git

First things first, let's install git on our Slice.

sudo aptitude install git-core

Setting up the git user

Now we will set up a special user account to hold the git repository.

sudo adduser git

Let's setup SSH keys for the new git user. If you followed along with page 1 and page 2 of our Ubuntu Hardy articles, this step will be very familiar to you. Since our public key is already on the Slice though, we can just copy it over.

Switch to our git user, create the necessary SSH directories and set the proper permissions.

sudo su git
cd /home/git
mkdir .ssh
chmod 700 .ssh
exit

Copy our authorized_keys file from our user account to our git user account and ensure that it's owned by the git user.

sudo cp /home/demo/.ssh/authorized_keys /home/git/.ssh/
sudo chown git.git /home/git/.ssh/authorized_keys

If you followed along with page 1 and page 2 of the Hardy articles, you'll recall that we disallowed SSH access to all but our main user in our sshd_config. We'll need to add the git to the list of allowed users, as our repository will be using SSH to communicate with our client.

Open up your sshd config.

sudo nano -w /etc/ssh/sshd_config

Find the "AllowUsers" line and add our git user to the list.

AllowUsers demo git

Reload the SSH config.

sudo /etc/init.d/ssh reload

Let's make sure that we can properly establish an SSH connection using the git user now. From your local machine:

ssh -p 30000 git@YOUR-SLICE-IP

Change the "30000" to whatever port you're using for ssh and YOUR-SLICE-IP to, well, your slice's IP address. The default SSH port, if you haven't changed it, is 22, but you should have changed it to something else if you followed our tutorials to set up your slice.

You should connect fine at this point.

Great! Now that the git user is set up, we want to create our first repository.

Creating a Repository

We are going to do this work as the git user so that we don't have to fiddle with permissions when we are done.

su git

Now we want to create a directory in the git users home, this will be the name of the repository. For the sake of example, I will just call this repo "project1"

cd /home/git
mkdir project1
cd project1

Let's initialize that directory to be a bare git repo and exit out of the git user.

git --bare init
exit

We just created our first git repository! Easy, huh?

Restricting shell access for the git user

In the future, we may want to add more keys to our authorized_keys file to grant access to the repo for others. However, we don't want these users to have SSH access to our server - so we are going to use a special tool called "git-shell" to restrict the access that the git user has.

First, open up /etc/passwd in your favorite text editor.

sudo nano /etc/passwd

Find the line the git user we added is on, it should read something like this (note that the user ID and group ID numbers may differ on your Slice, you should not touch those values):

git:x:1001:1001:Git,,,:/home/git:/bin/bash

Note that the "/bin/bash" means that this user gets a bash shell when SSH'ing into the Slice. This is generally the default shell for most distributions and is the heart of your interactions with the command line.

Let's change the "/bin/bash" to "/usr/bin/git-shell"

Now it should read something like this:

git:x:1001:1001:Git,,,:/home/git:/usr/bin/git-shell

Now, if someone successfully SSH's into your Slice as the git user, they will be forced to use the git-shell. The git shell is specially designed to restrict access. Let's see what happens when we attempt to SSH in as the git user now.

From your local machine:

ssh -p 30000 git@YOUR-SLICE-IP

You should see the following output.

fatal: What do you think I am? A shell?
connection to [YOUR-SLICE-IP] closed.

Excellent! Now the git user we created is secured and will not be able to SSH into your Slice.

Let's move on.

Making your first commit

Now that we've got our repository setup and our git user secured, we want to make our first commit to the repository. The first commit requires a bit of work, but you only need to do this once. After that, committing and pushing to the repository is a breeze.

At this point you will want to make sure that you have git installed on your client machine, as that is where we will be running the following commands from.

Make a new folder on your system wherever you'd like to keep your project files. Again, I will call this "project1"

mkdir project1

Initialize the new folder as a git repository.

cd project1
git init

Create a new file or files to add to the repo.

touch hello.txt

Add all files in this folder to the repo.

git add .

Commit the files we just added.

git commit -m "added hello.txt"

Note that the -m and the text that follows is simply the message that gets logged about that commit. Generally you will want that to relate to what you just committed in some way in case you ever need to go searching for when a particular change was made.

Add the remote origin.

git remote add origin ssh://git@YOUR-SLICE-IP:30000/path/to/project1

Again you'll want to substitute your SSH port number and slice IP address above. You'll also need to specify the full path to your git project repository at the end of the line there.

Now, let's push our changes to the repo.

git push origin master

Wow! We have accomplished quite a bit so far.

Almost Done

Now our repo is set up and ready to be cloned. Let's delete the "project1" folder we made on our local machine (as that was just temporary) but required to complete some of the work. Then we will 'clone' our remote repo back down to our workstation.

On your local machine:

rm -rf project1
git clone ssh://git@YOUR-SLICE-IP:30000/path/to/project1

That's it! We now have a fully functioning git repository on our Slice and we've pulled a clone of it down to our local machine.

For a list of the common git commands you'll want to familiarize yourself with, run this command on your local machine.

git --help

Enjoy!

Ben B.

Article Comments:

Frantisek Malina commented Tue May 19 02:54:22 UTC 2009:

If you've specified a custom port for SSH login (other than 22), use the following pattern to add the remote login

git remote add origin ssh://git@12.34.56.789:30000/absolute/path/to/git/project

seanl commented Fri May 22 15:43:16 UTC 2009:

Is setting up Gitosis a better option than using the method prescribed above as it doesn't not require the use of shell accounts and should be inherently more secure. I only ask as I'm having difficulties setting it up and wonder if this simpler method might serve me best

Łukasz Adamczak commented Tue Jul 14 08:11:57 UTC 2009:

@seanl: Gitosis does require a git account, just as in this article. It greatly simplifies administering your git repositories - adding users, creating new repos etc.

See http://scie.nti.st/2007/11/14/hosting-git-repositories-the-easy-and-secure-way

Ionut G. Stan commented Sat Jul 18 20:01:55 UTC 2009:

For those that are trying to manage Git with Gitosis. I've installed it (Gitosis) using the instructions on scie.nti.st. The damn thing won't work though until you edit /etc/ssh/sshd_config and add the git user to allowed users:

AllowUsers demo git

Shawn commented Wed Aug 05 13:44:16 UTC 2009:

Great article! A question, after disable the shell, how can I create another repo?

Thanks Shawn

Goro commented Tue Sep 08 23:43:53 UTC 2009:

I got an error when push my local repository to remote.

$ git push origin master FATAL ERROR: Network error: Connection timed out fatal: The remote end hung up unexpectedly

Why remote timed out? Any ideas?

Goro commented Wed Sep 09 03:05:29 UTC 2009:

I fixed it.

It was SSH autorization problem.

Naveen Garg commented Tue Sep 15 15:26:06 UTC 2009:

There is a typo in this line: sudo chown git.git /home/git/.ssh/authorized_keys

should be sudo chown git /home/git/.ssh/authorized_keys

also, you may want to add instructions to add repositories after restricting the git user to git-shell

Ben commented Wed Sep 23 04:37:11 UTC 2009:

@Naveen - that wasn't a typo, using "git.git" changes both the 'user' and the 'group' so that it is also owned by the git group. It may not have been needed, but I find that it is a good habit to be as explicit as possible when assigning file permissions.

Thank you for the article suggestion. I will make a note of it!

Cheers.

fabilo commented Sat Oct 10 09:07:49 UTC 2009:

When I try to change the default shell for git user to git-shell eg:

git:x:1001:1001:Git,,,:/home/git:/usr/bin/git-shell

there is no /usr/bin/git-shell file, should there be?

Trent commented Tue Dec 01 11:36:13 UTC 2009:

@shawn to create another repository, log into your slice with an account that has sudo access, then execute:

sudo su --shell /bin/bash git

Now you can complete the 'Creating a Repository' steps

Jason Ervin commented Sat Feb 20 06:18:07 UTC 2010:

I am trying to do the "git push origin master" and I am getting "connetion to host 173..... port 22: Connection refused"

I changed the port to 3333 but it keeps trying to connect to 22

Brent commented Tue May 04 12:14:03 UTC 2010:

Are we supposed to add the "git" user without a password?

I've added with a password and keep getting password prompts. You never mention a password, but I feel unsafe creating a user without a password.

Also, previous tutorials have encouraged us to change the ssh port, then this one assumes we're on port 22. It's worth mentioning what to do if you've changed the port as almost everyone reading this will have.

Brent commented Tue May 04 12:44:58 UTC 2010:

I found success in replacing the "sudo adduser git" command with this one:

sudo adduser \
    --system \
    --shell /bin/sh \
    --gecos 'git version control' \
    --group \
    --disabled-password \
    --home /home/git \
    git

Cort Allen commented Wed Jun 16 07:18:13 UTC 2010:

I agree with previous commenters. Earlier articles advise us to change the port away from 30000, but this article doesn't take that into account.

Thus, when we are adding the git remote ("git remote add origin git@SLICE-IP-ADDRESS"), the next step ("git push origin master") fails.

Jered commented Wed Jun 16 16:05:13 UTC 2010:

I've updated the article to let the git remote commands account for ssh on a custom port, but I admit I'm not terribly experienced with git. If you see a problem with them, definitely let us know here.

On the subject of passwords, if you create a user with no password on linux, the user doesn't have a blank password - it actually has no password at all. That means it's more secure to not set a password for a user if you'll only be accessing it through an RSA key. Though of course, if you will be accessing it from multiple computers and can't use an ssh key to secure access to the account, you will need to set a password for access.

Kanye commented Fri Aug 13 12:40:27 UTC 2010:

In the Making a first commit section, you set up a local repository, add a file, add a remote repo, delete local repo and then clone to get a working copy.

Why not add "touch file.txt" on the server repo and then just clone it on local? May be avoid --bare too while setting the server repo.

matt commented Mon Nov 08 17:57:12 UTC 2010:

so what's the next article in the series? this? http://articles.slicehost.com/2008/1/17/capistrano-series-local-setup-and-capistrano

Jered commented Mon Nov 08 18:03:54 UTC 2010:

It looks like the next article in this series would be this one on installing ruby gems and sqlite3. You can see a list of all the Capistrano articles on the category page.

Thierry commented Sun Oct 02 09:55:46 UTC 2011:

When I issue the command

sudo /etc/init.d/ssh reload

I receive an error message:

Rather than invoking init scripts through /etc/init.d, use the service(8) utility, e.g. service ssh reload

Since the script you are attempting to invoke has been converted to an Upstart job, you may also use the reload(8) utility, e.g. reload ssh reload: Unknown instance:

Because of this, login with git user fails.

Remark, the exact same command when I setup the slice works perfectly. I login succesfully with my first user with public private ssh auth.

Alex commented Wed May 02 17:18:06 UTC 2012:

sudo su --shell /bin/bash git may not (most likely will not) work for shared hosting accounts. A solution is to login into the "git" user account from another shell su -c '/bin/sh' git

Anonymous commented Fri Aug 03 15:45:58 UTC 2012:

@Thierry, I had the same problem. It seems to be related to this bug:

https://bugs.launchpad.net/ubuntu/+source/openssh/+bug/687535

My solution was to log in to the slice manager and perform a soft reboot. After that, the SSH configuration was already reloaded so I was able to login successfully as the git user.

Justin Raja Kumar commented Tue Dec 18 13:42:20 UTC 2012:

Hi,

I just follow up the setup to git with SSH. I can able to clone and push. But after pushing from the client machine, i couldn't able to see the client changes to server. Can you please someone help me on this.

[git@instance-1 ~]$ git clone ssh://git@192.168.0.88:22/home/git/gitrepo Initialized empty Git repository in /home/git/gitrepo/.git/ remote: Counting objects: 6, done. remote: Compressing objects: 100% (2/2), done. remote: Total 6 (delta 0), reused 0 (delta 0)

Receiving objects: 100% (6/6), done.

[git@instance-1 gitrepo]$ git push origin master Counting objects: 5, done. Writing objects: 100% (3/3), 250 bytes, done. Total 3 (delta 0), reused 0 (delta 0) To ssh://git@192.168.0.88:22/home/git/gitrepo 9dba5af..e1f5388 master -> master

Regards, Justin

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)