Oliver Nassar

Setting up an SVN Server on an Ubuntu 11.10 EC2 Instance

July 17, 2012

Setting up an SVN server on my EC2 instance (on AWS), was a project that was months, if not over a year, in the making.

It sounded straight-forward enough, but when you couple SSH keys, non-standard ports, and svn-tunnel's into the mix, it gets a little tricky to get-right.

The intent behind this project was, initially, to save me money. I pay $9/month with Springloops, and have been for at least 2 years now. It's a phenomenal service that presents you with a web-based UI to manage your repositories, and push changes to your servers (even automatically upon each commit).

But alas, as I've become more handy at the terminal, and require less of a UI to manage my repos (and their deployment), I've decide to save the $9/month, and roll out my svn server.

It took me quite a bit of time, so I hope this helps others, and acts as a reminder for me down the line.

I checked out tons of articles, walkthroughs and blog posts, but I couldn't find any that fit my exact situation.

Here's my situation:

With that out of the way, the first thing I had to do was insure svn was installed on my server:

sudo apt-get install -y subversion

As I'm working on a Mac, I have the svn client installed, so there's no problem there.

Then, on my EC2 instance, I want to create both the directory where I'll store repositories, and the subsequently, create the repository itself. Permissions and ownership are of the utmost importance. This worked for me:

sudo mkdir -p /srv/svn/
sudo chown ubuntu:ubuntu /srv/svn/
svnadmin create /srv/svn/{repo_name}

Mind the {rep_name} placeholder above :)

You don't need to store your svn repos in /srv/svn/. Wherever you'd like, so long as the permissions and ownership is okay. Also, ubuntu:ubuntu is the username and group for my EC2 instance. I believe this is standard now for most AMIs, but change this if appropriate.

The repository has been created. Now comes the confusing (for me) part: how do check it out and work within it?

As I wanted to remain free to use Cornerstone for the visual management of the repo, I found out that it wasn't as simple as putting my IP and specifying my ssh key inside it's UI. I had to do edit some subversion configuration settings. Even command line wasn't working, because first, we need to create a tunnel :)

From OSX:

vi ~/.subversion/config

Now, under the [tunnels] section, you want to define a rule.
Basically, you want to replicate the syntax that you would normally use for ssh-ing into your EC2 instance. In my case, this includes specifying the pem file path and port I connect through.

So under that [tunnels] section, I have something like this:

ssh-onassar = ssh -i /Users/onassar/Keys/ec2.pem -p 1234

A couple things here:

  1. It needs to be the full path to the pem file. You can't use the ~ here.
  2. It needs to be in the [tunnels] section. I had it at the end of the file at one point, and the tunnel wouldn't work :(

Also, you can call you tunnel whatever you want. ssh-onassar or ssh-tunnel or what have you.

And finally, let's checkout that repo we made :)

svn co svn+ssh-onassar://ubuntu@1.1.1.1/srv/svn/{repo_name}

In the above case:

Yup :)

I was getting a strange Killed by signal 15. error upon svn up, svn add * and svn ci *

This Server Fault post I get Killed by signal 15. when I'm using svn reported that it was a fix to an earlier bug, so I just needed to update the tunnel I created in my ~/.subversion/config file to have the -q flag (to suppress the notice).

The above tunnel became:

ssh-onassar = ssh -q -i /Users/onassar/Keys/ec2.pem -p 1234

Yup :)

Now to test out Cornerstone. It should just work, right?

When you open up Cornerstone, hit the Add Repository link, and tab over to the SVN Server option, you can choose from the drop-down list the tunnel you created. Just fill in the Server, Repository path, Port and Name parameters respectively with your IP/hostname, repo path (in my case, /srv/svn/{repo_name}, port, and username (in my case, ubuntu).

That should be it, right?

When I tried connecting, I got the following:

Description : The connection was dropped by the server for the item at "svn+ssh-onassar://ubuntu@{ip}:{port}/srv/svn/{repo_name}".
 Suggestion : Check that the repository URL is correct.

Technical Information
=====================

      Error : V4ConnectionClosedError
  Exception : ZSVNConnectionClosedException

Causal Information
==================

Description : To better debug SSH connection problems, remove the -q option from 'ssh' in the [tunnels] section of your Subversion configuration file.
     Status : 210002
       File : subversion/libsvn_ra_svn/client.c, 516

Description : Network connection closed unexpectedly
     Status : 210002
       File : subversion/libsvn_ra_svn/streams.c, 75

Ha. I could check out and commit and add and everything from the command line, but couldn't get access to the project from the application. According to the Stackoverflow post xcode - SVN+SSH Connection Giving Error 210002, Network Connection Closed Unexpectedly, the problem lies in the fact that I'm using a non-traditional or non-standard port. SSH doesn't like that. The suggestion?

Create a config file at ~/.ssh/config, with the following details:

Host {ip}
User ubuntu
Port {port}

Save. Then try again, but omitting the port parameter (since this is bound in your ssh configuration file now). The result?

Yup :)

There's my experience with setting up an svn server on my EC2 instance. It took a descent amount of time to find my way to the end, and to write this post coherently even, but I think it was worth it :)

ps. If you're using a traditional port (22, I would imagine), I hope you find yourself with a slightly less-complicated process near the end of this informal-tutorial. I'll update this post once I find the time to try out the process on a box without custom ssh settings like that.

Follow Up

After adding that configuration file for my ssh install, I realized two things:

  1. Now when I ssh into my instance, I no longer need to specify the port. ssh -i ~/Keys/ec2.pem ubuntu@{ip} will do
  2. I can change the tunnel I created above to exclude the port. It can now read: ssh-onassar = ssh -i /Users/onassar/Keys/ec2.pem

That keeps things a little cleaner and simpler. Always a plus :)

Follow Up #2

This will bind all changes to the ubuntu user in the SVN logs. Not the most ideal, but works for me as I'm the only developer on most projects. Both sad face and smile face worthy!

Tip

If interested in a clean-process for deploying with Git, check out this recent post on how to deploy with git.

The nice thing there (as I'm sure is also possible with svn), is the possibility of applying pre and post git pull/push hooks, so that you can hit an endpoint (to, for example, put your site into read-only mode during the pull) before and after the action.