Skip to content
Dec 30 / kkrizka

Setting Up A Public GIT Repository With GoDaddy Shared Hosting

Over time, I have worked on a lot of small personal projects. Most of them are versioned locally using GIT, so I can track any changes that I make. However when I release them, I do it as a tarball meaning that all of the change history is lost. Also these periodic releases mean that – Of course, I could setup a public GIT repository with GitHUB (and I have for the AutoRotate Daemon), but most of these projects are very small and depricated soon. Going through the entire setup of creating a GitHUB repository for such quick projects just takes too long. For this reason I’ve looked into ways to host GIT repositories on this website, which is powered by GoDaddy’s shared hosting plan. This post is a step-by-step guide as to how I accomplished it.

My configuration is not perfect, mainly because my hosting plan is designed to host web sites and not GIT repositories. To summarize, the repository is available to the public through the HTTP protocol in a read-only fashion. Nothing special is required here. However the developer needs a read-write access to it, so it can be updated with the latest version of the code. This is done through the SSH protocol, since GoDaddy does allow secure shell access to your website.

But this access is limited, which is where the “hacky” part of my configuration starts. First of all to update a git repository through SSH, one needs the git-upload-pack and git-receive-pack commands installed on the server. GoDaddy’s servers do not have them, which means you need to install them in your home directory. But your home directory is not in the PATH variable of a non-interactive bash shell (used by GIT) and it is impossible to change this. I’ve come up with two ways to get around this.
First solution is to specify the full path to git-upload-pack and git-receive-pack commands through the remote.origin.uploadpack and remote.origin.receivepack variables in the configuration of the private repository (local machine).
The second solution is to use the command option in .ssh/authorized_keys and source the .bashrc files and update the PATH variable through it. Of course, this only works if you are using SSH keys for authentication.
If you come up with alternate solutions, feel free to leave a comment below.

Requirements

  • GoDaddy shared hosting – I’ve written this tutorial assuming that you are using GoDaddy’s servers. Of course, the key steps should work with other web hosts too as long as they allow SSH access. The only issue might be that the GIT binaries that I provide are compiled for CentOS 5.2 (used by GoDaddy), so there might be an incompatibility issue.
  • Previous GIT experience – This is not a tutorial on how to use GIT. I assume that you already know how it works. If not, then read the GIT Community Book.
  • GIT installed on local machine – Hopefully self explanatory.
  • SSH client installed on local machine – We’ll need some way to setup stuff on GoDaddy’s servers. Also I’m pretty sure that it is required for GIT to work with SSH.
  • Bash shell on local machine – I provide the commands on how to accomplish all of the tasks. If you are using a GUI (ie: Putty or WinSCP on Windows), then you are on your own. On Windows, you can use Cygwin.

Setup GIT Binaries On GoDaddy’s Servers

As the first step, you need to install the GIT binaries on the server. This will be done by unpacking a pre-compiled binary of GIT that I provide.

  1. The first step is to enable SSH access to your account. All GoDaddy hosting plans come with the SSH access which can only be enabled after you provide a valid phone number. To do this, go to the Control Center for your hosting plan. Next locate the page under Settings->SSH and follow the instructions. They are to basically type in your phone number and wait for a bit. Soon you’ll receive an automated call that will give you a PIN code. The message says it twice, so don’t panic if you didn’t catch it the first time. Type this PIN into the box provided on the website and hit enter. If everything went correctly, you will see a message saying that SSH access is being enabled. If something goes wrong, consult the GoDaddy help pages.
  2. Wait a while, it takes an hour or two for SSH to become enabled.
  3. After SSH is enabled, connect to your GoDaddy server with the following command:
    user@computer:$ ssh username@yourwebsite.com

    The username is the same as your primary FTP username. If you don’t know what it is, you can find out by looking under Settings->Manage FTP Users in the Control Panel. The password is the same as you use for FTP. If this step worked, you can also setup password-less login through SSH keys. All of the following commands are to be executed in this SSH session.

  4. Download the GIT binaries on the GoDaddy server by running the following command:
    user@computer:$ wget http://www.krizka.net/download/files/git-1.7.3.4_centos5.2.tar.bz2

    These binaries were compiled from the GIT (version 1.7.3.4) source code by me. I compiled it in a virtual machine (VirtualBox) running CentOS 5.2, which is the same operating system that my GoDaddy server is running. In my experience, Linux binaries are relatively portable so these might also work on servers running a different operating system. However if they do not, you’ll have to compile them yourself. As I mentioned, the simplest way to do it is create a virtual machine using the same guest operating system as your web host is using.

  5. Unpack these binaries using the command:
    user@computer:$ tar -xvjf git-1.7.3.4_centos5.2.tar.bz2

    This unpacks everything into a directory called git. So if you want to uninstall everything later on, just delete this directory.

  6. Using your favourite text editor, add the following lines to the bottom of the ~/.bashrc file on the GoDaddy server:
    export GIT_BIN=${HOME}/git
    export PATH=${GIT_BIN}/bin:${PATH}
    export LD_LIBRARY_PATH=${GIT_BIN}/lib:${LD_LIBRARY_PATH}
    export GIT_EXEC_PATH=${GIT_BIN}/libexec/git-core

    This tells your shell where the GIT binaries are located, making their use available in an interactive shell. You have to login and logout for the changes to become recognized.

  7. You can now logout from the SSH session.

Publish The Private Repository

In this section, you will create a “bare” public repository and publish it on your web server. As an example, I will use my private repository of my AutoRotate Daemon project as a base.

  1. Create a bare clone of your private repository using the command:
    user@computer:$ git clone --bare ~/Projects/autorotate autorotate.git

    The –bare option strips all of the explicit files from the repository, saving the space. The first argument, ~/Projects/autorotate, is the path to your private repository. The second argument, autorotate.git, is the directory where the bare clone will be created. This clone will your public repository.

  2. Copy the public repository (autorotate.git) to your webserver. You can use either FTP or SCP to do this. I prefer SCP, because it is much simpler to use:
    user@computer:$ scp -r autorotate.git krizka.net:~/html/git/

    The last argument, krizka.net:~/html/git/, is the path on your webserver that the public repository should be copied to. krizka.net is the host name of your server and should be in the same format as the one used to connect though SSH in the first section (username@yourwebsite.com). The part after the : (~/html/git/) is the path on the webserver. The ~/html folder corresponds to the root of your website. So in my case, you can access the AutoRotate Daemon public repository at http://www.krizka.net/git/autorotate.git .

  3. Test that everything worked by running the following command on your local machine:
    user@computer:$ git clone http://www.krizka.net/git/autorotate.git

    Of course, replace http://www.krizka.net/git/autorotate.git with the expected URL of your repository.

  4. The final step is to update the server info in the public repository. This is required to make it work with HTTP. To do this, first connect to your server through SSH.
    user@computer:$ ssh krizka.net
  5. Second, enter the directory of your public repository.
    user@computer:$ cd html/git/autorotate.git
  6. Finally, run this command:
    user@computer:$ git update-server-info
  7. You can now logout from the SSH session.

Let Local GIT Know About Remote GIT

In the previous section, you have created a public repository that can be read by anyone. Now you have to setup write access to it through SSH. This is done in two parts. First you have to add a remote repository to your private repository. And then you have to tell it where to find the git-upload-pack and git-receive-pack commands. As mentioned in the introduction, I found two ways to accomplish this. I prefer the second method, because I only have to do stuff once per computer. With the first method, you have to do stuff once per repository clone.

  1. On your local machine, enter the directory containing your private repository.
    user@computer:$ cd ~/Projects/autorotate
  2. Add the remote repository as origin using the command:
    user@computer:$ git remote set-url origin ssh://krizka.net/~/html/git/autorotate.git

    Don’t forget to replace krizka.net/~/html/git/autorotate.git with the path to your public repository, just like you did when copying it over with scp. Note that in this case, the : was replaced with a /.

  3. Try to push some changes to the public repository. You will fail with the following error:

    bash: git-receive-pack: command not found
    fatal: The remote end hung up unexpectedly

    This is because GIT does not know where the GIT binaries are installed are GoDaddy’s server. For interactive Bash, we accomplished this through the .bashrc file. But this file is only read when using an interactive shell. If you start Bash in an non-interactive mode, which is what GIT does, then no such initialization file is used. It is impossible to change the environment variables in an elegant way for non-interactive shells, so you have to pick one of the following dirty methods to fix this.

Method 1: Tell Local GIT Where To Find Binaries

  1. In the directory of the private repository, run the following two commands:
    user@computer:$ git config --local --add remote.origin.uploadpack /home/content/k/r/i/krizkanet/git/bin/git-upload-pack
    user@computer:$ git config --local --add remote.origin.receivepack /home/content/k/r/i/krizkanet/git/bin/git-receive-pack

    Make sure to replace the last argument in both commands with the full path to the two binaries.

Method 2: Use SSH Forced-Commands

If you are using SSH keys for authentication (tutorial on how to do this), then it is possible to change the command that will be run remotely. In our case, we change the command to be “read .bashrc; eval requested command”.

  1. Connect to your web server using SSH. All of the following actions will be done there.
  2. Open the .ssh/authorized_keys file in your favourite editor and locate the line that contains the public key that you use to login. My key looks like the following:

    ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArXgEE/YSFIjlCQIDJP68Fng2jsEZQjaTgZ4h0/HUjZLXzE+F2RLJwRRFS+Sn30y8sZ3buCGYeIQKH+L0FLvN/0kn3CM+/mIwBeH1+CGETsIliGjSO62ewk+ePsM6vtQ7RxVY7Z1NI+lz5vMuTXiUr9qd5Le/EiblbcIDiIAzVtHVLYFUPiTlHeEbsSgP1wA9dUPzz5Ge4sIBqYuur1FlvJT55cjo+PsZkHuarbLabhR69U/zfd9w8ba01RJJiJVL7ZqozuYi9GnnGMT72UroIvriyUZfJqRIdQm2VxME+KSBsnf8sqqJJVUY+owCluYPMjFpsnmnXoNosLSDpZpP+Q== kkrizka@tiny101

  3. Add the following text in front of your key. It should be on the same line!
    command="if [[ "x${SSH_ORIGINAL_COMMAND}x" == "xx" ]]; then /bin/bash; else source ~/.bashrc; eval "${SSH_ORIGINAL_COMMAND}"; fi; "

    What this does is check if a command is to be run remotely, and if it is then it sources .bashrc and runs the command. If no command is to be run, then it just starts an interactive shell. After you are done, the line containing your key should look something like:

    command=”if [[ “x${SSH_ORIGINAL_COMMAND}x” == “xx” ]]; then /bin/bash; else source ~/.bashrc; eval “${SSH_ORIGINAL_COMMAND}”; fi; ” ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArXgEE/YSFIjlCQIDJP68Fng2jsEZQjaTgZ4h0/HUjZLXzE+F2RLJwRRFS+Sn30y8sZ3buCGYeIQKH+L0FLvN/0kn3CM+/mIwBeH1+CGETsIliGjSO62ewk+ePsM6vtQ7RxVY7Z1NI+lz5vMuTXiUr9qd5Le/EiblbcIDiIAzVtHVLYFUPiTlHeEbsSgP1wA9dUPzz53e4sIBqYuur1FlvJTP5cjo+PsZkHuarbLabhR69U/zfd9w8ba01RJJiJVL7ZqozuYi9GnnGMT72UroIvriyUZfJqRIdQm2VxME+KSBsnf8sqqJJVUY+owCluYPMjFpsnmnXoNosLSDpZpP+Q== kkrizka@tiny101

Try to push your changes now. Everything should work now. A full list of my public GIT repositories is available at http://git.krizka.net/

References:

19 Comments

Leave a comment
  1. Wil Helser / Jan 24 2011

    Hey Karol, thanks for this tutorial and the Git binaries. I’ve been looking for a way to do this for months now and yours is the only article I could find that was complete and clear. I had everything up and running in a matter of minutes. Thanks again, and keep up the awesome work!

  2. Marko Rosic / Feb 24 2011

    Great article…

    git clone asked me to do run “git update-server-info” and it worked like charm.

    One should also add .bash_profile with following as .bashrc won’t execute when you login from ssh:

    if [ -f ~/.bashrc ]; then
    source ~/.bashrc
    fi

    • Jonathan / May 1 2011

      This is incorrect… .bashrc runs fine for me when I login via ssh. To test I added some alias to .bashrc, then logged out of ssh and back in and the alias were active.

  3. E K / Mar 24 2011

    Very nice tutorial. Regarding method 1, though, why can’t you just specify `global` instead of `local`:

    git config –global –add remote.origin.uploadpack /home/content/k/r/i/krizkanet/git/bin/git-upload-pack

    Shouldn’t that have the same effect as 2, without having to screw around with ssh?

    • Karol Krizka / Mar 30 2011

      I don’t think so. The problem that I see with this is that it changes the path globally on your LOCAL computer. So if you also have some repository clones from other sites, like GitHUB, then git will look for git-upload-pack in that location also for them.

  4. Tada Burke / Jun 1 2011

    Excellent work, thank you!

  5. Atis / Jul 4 2011

    Very useful article, and even saved me from building git under a virtual machine.

    Thank you!

  6. Stephen / Aug 12 2011

    Hi,
    I’m getting stuck at part 2, step 3 – “git clone [remote_repo]”

    At that point I’m getting the comment:

    bash: git-receive-pack: command not found
    fatal: The remote end hung up unexpectedly

    You mention it should happen later, and I tried those fixes, but nothing helped. Any suggestions on how to fix it?

    • Stephen / Aug 12 2011

      Correction!

      I’m getting…

      Cloning into [location]…
      bash: git-upload-pack: command not found
      fatal: The remote end hung up unexpectedly

  7. Cort / Nov 13 2011

    I tried using your “Method 2” of editing the key file, but noticed that “scp” no longer works after doing this.

    Any ideas on how to fix this?

  8. George / Feb 11 2012

    thanks for the tutorial. the binaries you posted do not contain git-http-push – so I can’t do pushes

    Can repost that binary file. thank you

  9. Brad / Mar 11 2012

    This URL actually had an even easier method:

    http://dren.ch/git-on-godaddy/

  10. inf3rno / May 13 2012

    Hi!

    Is there a way to configure the location of upload and download pack on the server?

    I mean if I connect with git bash via ssh, the server include-s the .bash_profile with the settings you described upper (especially GIT_EXEC_PATH), so after that I can call git-upload-pack directly, I don’t need to write the path of the binary before the command. Is there a way to do the same include by any git connection (clone, pull, push etc…)?
    (I tried with the authorized_keys command part u described, but had not work by me. Only the checkout works, the push and the pull not :S So I can download from the server with checkout, but cannot upload to it…)

  11. Amazingant / Jul 20 2012

    I managed to get mostly everything working, except I kept getting stuck at one point and couldn’t figure out what I had hosed up.
    What I managed to figure out is that on my server, when adding the command=”if yadda yadda” stuff to the authorized_keys file, I had to use the text given from the page Brad mentioned, escaping some of the quotes with backslashes:

    command=”if [[ \”x${SSH_ORIGINAL_COMMAND}x\” == \”xx\” ]]; then /bin/bash; else source ~/.bashrc; eval \”${SSH_ORIGINAL_COMMAND}\”; fi; ” ssh-rsa blah blah

    instead of

    command=”if [[ “x${SSH_ORIGINAL_COMMAND}x” == “xx” ]]; then /bin/bash; else source ~/.bashrc; eval “${SSH_ORIGINAL_COMMAND}”; fi; ” ssh-rsa blah blah

    Once I put the backslashes in, SSH would connect with the RSA key again instead of asking me for a password, I set the url for my local git repo to “user@site.com:~/html/git/Repo.git” and tried to push… SUCCESS! :)

    @inf3rno, if you’re still trying to get this working, try the backslashes and see if that solves the issue; that’s all it took for me.

    Otherwise, thanks for the article, Karol!

Trackbacks and Pingbacks

  1. hg-gateway: Supporting multiple Mercurial users on a Shared SSH account | Untyped
  2. Roll out to GoDaddy shared hosting with Git
  3. Bokmärken för September 24th från 16:01 till 16:19 « Coverage
  4. Christians digest for September 25th | Christians lifestream
Leave a comment