Reverse SSH for git

Getting your private repo cloned to your server.

So you have a git repository on your machine, or on a server on your local network behind a firewall and or NAT. Now you want to deploy it on to a cloud server. You have a whole host of options, with good points and bad, such as:

  • Use scp or rsync
  • Initially copy a bare repo up so you can push to it, then pull locally from that on the remote server.
  • Reverse port forward port 22 (ssh) so git can pull via a tunnel back into your network.

Here I'll describe the last option. It's better than copying or rsync'ing as it only get's committed changes, and saves room on the bare repo setup. In a nutshell we set up a reverse port forward so that git can ssh back into your network from the cloud.

What is a reverse port foward?

Well hopefully you know what a normal port forward is, making a remote port appear on the local machine. A reverse port forward is just the reverse. A locally accessible port is made to appear on the remote host. I say 'locally accessible' because the port need not be on your machine, it could be on another machine in your network.

The magic incantation...

ssh user@cloud-server -R2222:localgitserver:22

or if the repository is on your local machine (and you can ssh into your machine)

ssh user@cloud-server -R2222:localhost:22

I've picked 2222 at semi random. Use which ever available port you like.

This will give you a remote shell on the cloud server. From here you can try:

ssh user@localhost:2222

To make sure it all is working. If you're using something like gitosis on your local git server, it will not let you login, but you should be able to see that the remote server is able to access it.

Now the git clone syntax is a bit messy, but you only have to do this when initially cloning.

git clone ssh://user@localhost:2222/path/to/repo

Note that the first slash (/) after the port number, is not part of the path, it is separating the port and the path. So if you are cloning from your local machine, and the repository is in your home directory, it might look like this.

git clone ssh://bob@localhost:2222/~/my_projects/awesome_new_website

It an't pretty, but it works. See here on stackoverflow for more on using a different port with git.

After the clone, pushing new commits up

Because you are using a 'reverse' port forward, you will be initiating a pull on the server, rather than pushing. When you clone'd the 'origin' will have be stored away in the git configuration file. So all that needs to happen now is you ssh in, with the reverse forward like we did at the start, and run git pull from inside the repo directory. E.g:

bob@devbox:~/my_projects/awesome_new_website> git rm public/img/toomanybeers.jpeg
bob@devbox:~/my_projects/awesome_new_website> git commit -m 'Heh, Oooops'
bob@devbox:~/my_projects/awesome_new_website> ssh -R2222:localhost:22
Welcome to the cloud Bob!
ec2user@bobscloud:~> cd awesome_new_website
ec2user@bobscloud:~/awesome_new_website> git pull
blah blah blah.....

Make it easier for yourself.

Rather that adding the '-R' option every time you ssh, you can put it in your '.ssh/config' file. You could add something like:

Host mycloud
User bob
RemoteForward 2222 localhost:22

Now you can just do:

ssh mycloud