Monday, 29 November 2010

Installing svn (over SSH) on Debian and OS X

This a quick Howto for installing a Subversion server on Debian/Ubuntu and OS X client to use it. My goal is to use svn over ssh for added security (communication is encrypted and I don't need to open another port).

I assume you have a SSH server already installed and running, plus root access. The svn clients will need an account on the server and read/write access to the svn repository (we'll see how to do that below).

(Don't enter the Debian$ part, it represents the prompt)

Server side
Installing svn:
Debian$ sudo aptitude install subversion
[ Side track:
If you don't do regular maintenance on your server, why don't you do it now:
Debian$ sudo aptitude update
Debian$ sudo aptitude safe-upgrade

Check if you need to restart any deamons/services to use the latest updates:
Debian$ sudo checkrestart
Check out this post!

Preparing the repository:
Debian$ sudo mkdir /var/svn-repos
Debian$ sudo svnadmin create --fs-type fsfs /var/svn-repos/myproject1

  • You don't have to use "svn-repos" or the /var directory.
  • You'll execute the last command for every project you have.

Debian$ sudo groupadd subversion
Debian$ sudo addgroup user1 subversion (repeat for every user, you want to have access)
Debian$ sudo chown -R root:subversion /var/svn-repos/*
Debian$ sudo chmod -R 770 /var/svn-repos/*

At this time, if you're connected through ssh as user1, you may need to reconnect to make that groupadd command effective for your session.

That's it, you'll now be able to access your repository in svn+ssh:// form. Let's see how do do that on OS X (mostly the same for all other OS):

Client side:
Open a Terminal window and run:
Mac$ svn
If the command is not found, you'll need to install it. (The openCollabNet package is probably the easiest way, you'll need to register but you want to keep your email private you can always use services like to do so).

Now that svn is installed on your Mac, let's try to populate our project:
Mac$ mkdir svn
Mac$ cd svn
Mac$ mkdir trunk
Mac$ mkdir branches
Mac$ mkdir tags
Mac$ echo "test only" > trunk/test.txt
Mac$ svn import . svn+ssh:// -m "Test import"

Now unless your Mac username is the same as your Debian account name, and you are using the default ssh port the connection won't work. You'll need to tell svn how to connect with ssh:
Mac$ nano ~/.subversion/config
Go to the [tunnels] section (Ctrl-W in nano) and add the line:
myssh = ssh -p 55555 -l debian_username
Replace 55555 with your own sshd server port and debian_username with your own login name on the server.
(Note: If you never connect to other svn server through ssh, you can use ssh instead of myssh)
Save and exit (Ctrl-X, y).
Let's try again:
Mac$ svn import . svn+myssh:// -m "Test import"
You will be asked for your debian password and you should see the list of files/folders being imported into svn.

You may need to enter svn commands often or one command may generate multiple connections and ssh will ask for your password each time. You can use ssh-agent to provide automatically provide ssh with your credentials:

On your Debian server, check that ~/.ssh exists and if not:
Debian$ mkdir ~/.ssh

Back in OS X:
Create your public/private keys (by default, it will use RSA, 2048-bit encryption):
Mac$ ssh-keygen
(Just follow the prompt, choose the defaults. You don't have to choose a passphrase, but if you do make it greater than 3 chars. You will have to enter your passphrase each time you start ssh-agent. I prefer to have one.)
Copy your public key over to the server:
Mac$ cat ~/.ssh/ | ssh -p 55555 "cat - >> ~/.ssh/authorized_keys"
Test it:
Mac$ ssh -p 55555
In OS X or other X environments a login box should be displayed asking for your passphrase.

ssh-agent can now use your key to log on automatically when it needs to. To go back to our example:
Start ssh-agent like this:
Mac$ eval `ssh-agent -s`
Mac$ ssh-add
(It will ask for your passphrase)
Check out your code:
Mac$ svn co svn+myssh:// .

You can add the ssh-* commands to your .profile, but since I don't connect to svn that often I have put it a separate file that I can just source.
Add this to your ~/.profile or a separate file:

function start_agent {
     echo "Initialising new SSH agent..."
     /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
     echo succeeded
     chmod 600 "${SSH_ENV}"
     . "${SSH_ENV}" > /dev/null
# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
     . "${SSH_ENV}" > /dev/null
     ps ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {

For code that will work in other environment (like cygwin), see this post.

If you put it in your .profile, you'll need to enter your passphrase the first time you open up a Terminal window in a session. If you chose not to have a passphrase, .profile is the perfect place to put this. If you put it somewhere else (let say ssh_cmd), just do this when your ready to connect:
Mac$ source ssh_cmd
Mac$ svn ...


There is a lot of way to setup svn+ssh access, the steps above were the ones I used based on my own needs. You can also have your users connect through the same account while still keeping track of who's changing what and being able to control access with svnauth, check the offcial documentation here.

I will soon be posting about svn on https which is a better setup for most cases.