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:
- I have a micro EC2 instance hosted with Amazon.
- I used a non-standard port for
ssh
access - I have a
pem
file provided by Amazon for access through ssh - I run Ubuntu 11.10 Server on my EC2 instance
- On the client side, I'm running Apple OSX Lion
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:
- It needs to be the full path to the
pem
file. You can't use the~
here. - 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:
ssh-onassar
is the name you gave to your tunnelubuntu
is the username for your EC2 connection (although I believeubuntu
is the default now)1.1.1.1
is the IP address (or host if you want) of your EC2 instance{repo_name}
is your repository's name
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:
- Now when I
ssh
into my instance, I no longer need to specify the port.ssh -i ~/Keys/ec2.pem ubuntu@{ip}
will do - 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.