svn+ssh

August 21st, 2008 by bodhi.zazen

This is a (brief) tutorial walking through svn+ssh. This tutorial assumes :

  1. You are familiar with basic ssh and svn commands.
  2. Subversion (svn) is already installed on the server.
  3. Your project is also alrady set up.
  4. The user svn already exists on the server.
  5. You know how to obtain a root shell.

If you need a crash course on subversion, here is a nice cheat sheet :

The goal of this tutorial is to show how to set up a subversion server to allow users to access the server over ssh.

The setup is a little complex in that :

  1. On the server, there is a single account, svn.
  2. Users (clients) log into the server, using ssh, as the user svn.
  3. With the use of a key, once a client logs in, svnserve is run on the server.
  4. Again, with the use of a key, the name of the user making a commit is preserved.
  5. svnserve uses a chroot to increase security.
  6. The user svn uses a (very) restricted shell (rbash).

This means that although all clients log into the server as the user svn, their identy is preserved in the subversion data base. The use of a chroot and a restricted shell increases security.

============================

Server side :

In this tutorial, ALL COMMANDS SERVER SIDE ARE RUN AS ROOT.

To become root :

Ubuntu : sudo -i
Fedora : su -

Configure/secure the user svn. This is an important step as users will log into your server as svn.

First change the shell to rbash (I could not get svn+ssh to work with a shell of /dev/null or /bin/true).

chsh svn

Enter /bin/rbash

—————————-

Secure rbash

cd ~svn
mkdir -p usr/bin
chown -R root.svn usr/
chmod -R 550 usr/
ln -s /usr/bin/svnserve usr/bin/svnserve
echo “PATH=’/home/svn/usr/bin’” > .bashrc
echo “” > .bash_history

—————————-

Secure /home/svn

Change ownership of the configuration files ( .bashrc .bash_history .bash_logout and .profile) to

chown root.svn .bash* .pro*
Change permissions to 440
chmod 440 .bash* .pro*

—————————-

Set up ssh

Keep ownership of .ssh/ svn.svn, change permissions to 700

chmod 700 .ssh

Change ownership of .ssh/authorized_keys to root.svn

chown root.svn .ssh/authorized_keys
chmod 440 .ssh/authorized_keys

Keep ownership of .ssh/known_hosts (svn.svn)
but change permissions to 600

chmod 600 known_hosts

—————————-

Make a unique ssh key for each user

ssh-keygen -t dsa -f user1

-f flag sets the name of the key, change “user1″ to the name of the user you wish to authorize access.

-t dsa generates a dsa key.

For example :

ssh-keygen -t dsa -f bodhi

Enter your desired password. This will create two files, user1 and user1.pub

(The names are a little confusing, and the way I remember it is that if I make a pair of keys I keep the key “bodhi” as a private key, and give the public key, bodhi.pub, to the server.)

Transfer your user.pub to the server, place it in /home/svn/.ssh

Now add it to authorized keys :

cat user1.pub >> authorized_keys

Now edit authorized keys to make the magic happen.

nano -w authorized_keys

—————————-

Side track / time out

The format of authorized_keys is the same as the key itself :

[Type]  [Key]  [user]

    Type = type of key, ssh-dds in this example.
    Key = the key itself (long line of random numbers and letters)
    user = who made the key (user@hostname)

—————————-

Magic

The trick we are going to use is to specify a command to run when a user logs in via ssh. We do this by adding a command to the start of the key :

[command]  [Type]  [Key]  [user]

Edit the file with nano

nano -w authorized_keys

The -w flag is important here, and keeps nano from inserting line breaks

First, lets comment the file :

#user1
[command]  [Type]  [Key]  [user1]

#user2
[command]  [Type]  [Key]  [user2]

Now add a command (all one line), DO NOT change the type, key, or user

command=”svnserve -t -r /var/svn/project/ –tunnel-user=user1″,no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty

That is all one line and you must keep all of this information on a single long line

Note: There are two – at the start of “–tunnel-user” (Wordpress is rendering two — as a long —- )

Lets break that down :

svnserve -t -r /var/svn/project/ –tunnel-user=user1

svnserve = When we ssh into the server, svnserve is launched on the SERVER.
Keep in mind, we are in rbash and svnserve is on our path.
If you use /usr/bin/svnserve it will not work
rbash prevents users from running a command with a /

-t = Allow to tunnel a user
–tunnel-user=user1 => This identifies the user.
Without these options commits would be made to the user svn
tunneling a user preserves the user name,
so commits are under user1
Note: There are two – at the start of “–tunnel-user” (Wordpress is rendering two — as a long —- )

-r = This causes svnserve to run in a chroot
/var/svn/project is the full path to your project
You may need to change to /home/user1/svn/project
* this has the added benefit in that clients
do not need to specify the full path on your server.

The rest secures ssh yet a little more

no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty

TIP : Keep in mind this results in a single long line :

[command]  [Type]  [Key]  [user]

============================

Client side:

Fortunately this section is short.

Configure subversion :

svn+ssh will not take options for log in user or port, so we must edit ~/.subversion

nano ~/.subversion/config

Under the [tunnels] section add (all 1 line):

jedi = /usr/bin/ssh -l svn -p 2244 -i /home/user1/.ssh/user1

** General syntax **

  • jedi     = name of protocol for svn, you may use any name you wish.
  • -l svn = log in to the svn server as svn.
  • user1  = user on the client making commits to the server (user1 in this example).
  • -i        = ssh key used to access the server (/home/user1/.ssh/user1 in this example).
  • permissions of key  == 400

Note: you can user any name you wish for the protocol.

—————————-

To check out (co) a project :

svn co svn+jedi://svn.bodhizazen.net/project

** General syntax : svn co svn+foo://server/project **

  • foo     =  name of protocol (jedi in this example).
  • server  =  svn server.
  • project = name of project to checkout.

—————————-

To check in a project :

ssh-agent :

When a user commits s/he will be asked for the ssh password multiple times. Easiest solution is to use ssh-agent.

Either add ssh-agent to your login profile, or in a terminal, start ssh-agent with :

ssh-agent

Then add your key :

ssh-add ~/.ssh/user1

This will keep the key and password in memory

Making changes :

Add changes to the project , edit/add files or directories. If you add files, notify subversion with:

svn add /path/to/project

View changes :

svn status

Commit changes :

commit adds your changes back to the server

svn commit

Note: You do not need to specify a protocol , svn track this for you.

StumbleUpon

Posted in Linux

9 Comments »

  1. [...] If you do not understand this, see my blog on svn+ssh. [...]

    Pingback by Shadows of epiphany » Blog Archive » Shared Terminal Sessions over SSH — January 20, 2009 @ 1:08 am

  2. Thanks for the tips, this was a huge help.

    A couple of small points:

    a) You do have to create the svn user, its not present by default on a Ubuntu box.

    b) The ownership of ~svn/usr… should be root.svn, otherwise you cannot excute the chrooted svnserve file with the permissions (550 and root.root) you give.

    c) The quotes in the text you add to authorized keys are in the wrong place; with the way you state you get the the string user1,no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty as the last author; the added text should be:

    command=”svnserve -t -r /var/svn/project/ –tunnel-user=user1″,no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty …. (ignoring page breaks of course)

    Comment by Andrew Canuck — March 25, 2009 @ 8:41 am

  3. [...] If you do not understand this, see my blog on svn+ssh. [...]

    Pingback by Shadows of epiphany » Blog Archive » Shared SSH Sessions, Update for Jaunty (Ubuntu 9.04) — March 28, 2009 @ 12:29 am

  4. Thank you Andrew Canuck for pointing out those “small points”, your feedback is greatly appreciated.

    My post has been updated.

    Comment by bodhi.zazen — March 28, 2009 @ 10:18 pm

  5. Bodhi, can this approach be used with Tortoise SVN from a Windows client? If so, any pointers for such configuration? I’ve tried a number of things, but can’t get past a login on the server.

    Comment by Dale — November 15, 2009 @ 11:50 am

  6. Dale: I have no experience with Tortoise SVN, but looking on the home page :

    http://tortoisesvn.tigris.org/

    They claim “All Subversion protocols are supported”, and they list svn+ssh

    So my guess would be you will be fine. Set up the SVN server as above, and configure your Tortoise client to use svn+ssh .

    See: http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-ssh-howto.html

    Comment by bodhi.zazen — November 15, 2009 @ 11:53 pm

  7. Hello,

    Thanks for the tips. But I don’t understand :
    [...] svn+ssh will not take options for log in user or port, so we must edit ~/.subversion [...]

    “svn checkout svn+ssh://user@host/” works for me… What is the difference ?

    Comment by 1 — November 30, 2009 @ 5:11 am

  8. Your command did not specify any options. You did not specify a port for example.

    You can not (or at least at the time I wrote the tutorial) :

    “svn -p 8822 checkout svn+ssh://user@host/”

    Comment by bodhi.zazen — November 30, 2009 @ 1:39 pm

  9. I would write :
    “svn checkout svn+ssh://user@host:8822/”
    I not have the time to test :(, but if it works for the host.
    My point is that by this way you may not have to configure the client. It’s always a good point ;)

    Comment by 1 — December 1, 2009 @ 2:10 am

RSS feed for comments on this post. TrackBack URL

Leave a comment