Subversion over SVN+SSH on Debian
Posted: | 2007-12-04 17:02 |
---|---|
Tags: | Debian, Hosting |
The traditional way of setting up subversion is via Apache but what if you don't want to install Apache? In that case you can use svnserve but what if your host won't let you run a persistant server? In that case you can create a linux system account for every user and give them induvidual SSH logins. You then give your users a URL starting svn+ssh:// instead of the usual http://. The Subversion client recognises this form of URL and invokes a local ssh process, connecting to the host, authenticating as the user, then spawning a private svnserve process on the remote machine running as that user. The svnserve command is being invoked in tunnel mode (-t) and its network protocol is being tunneled over the encrypted connection by ssh, the tunnel-agent. svnserve is aware that it's running as the user, and if the client performs a commit, the authenticated username will be attributed as the author of the new revision.
This is all well and good but you might not wa nt to have to create user accounts for each of the users you want to give access to subversion. In this case you can create one system user account and use a different SSH private key for each user you want to grant access to. You then setup the ~/.ssh/authorized_keys file so that each user only has access to svnserve and that each svnserve process is started with their particular username so that all the commits are handled correctly. This is only possible with subversion 1.1.0 and above.
This is what we are going to do for two users, james and mike. james is a linux user, mike is a Windows user.
First let's setup the server:
sudo apt-get install subversion openssh-server
Then create a subversion user svn, a home directory, an .ssh directory and finally set the correct permissions:
sudo useradd svn sudo mkdir /home/svn sudo mkdir /home/svn/.ssh sudo chown -R svn:svn /home/svn
If you intend to be able to login as svn for testing purposes later you should set a password:
sudo passwd svn
Create the directory for the repositories:
sudo mkdir /var/svn
Setup a repo repository and commit the first import:
sudo mkdir /var/svn/repo sudo mkdir /tmp/repo sudo mkdir /tmp/repo/branches sudo mkdir /tmp/repo/tags sudo mkdir /tmp/repo/trunk sudo svnadmin create /var/svn/repo sudo svn import /tmp/repo file:///var/svn/repo -m "initial import" sudo rm -rf /tmp/repo
Change the permissions so that the svn user and svn group have access:
sudo chown -R svn:svn /var/svn/repo
Set the permissions to 770 and the umask to 2 so that any files are created have the correct permissions:
sudo chmod 2770 -R /var/svn/repo
At this point you can test the setup manually. As a user other than svn try this:
svn co svn+ssh://svn@localhost/var/svn/repo .
This should prompt you for the password a couple of times and then checkout the repository.
We are half way there, next we need to set up two SSH public-private key pairs, one for Mike, one for James. As the svn user run:
ssh-keygen -t rsa -b 1024 -f mike.key ssh-keygen -t rsa -b 1024 -f james.key
With each command you can just press <Enter> twice unless you want to set a password. You will now have the files mike.key, mike.key.pub, james.key and james.key.pub in the current directory. The .key files are the private keys. They should be given securely to Mike and James repsectively. Anyone who gets hold of the files will have the same permissions to the repository as James and Mike so they should be treated with the same respect as a password and not posted online!
Since Mike is on Windows he will need WinSCP, PuTTY, PuTTYgen and TortoiseSVN (the latter requires adminsitrator access to install).
Here's what he does:
Use WinSCP to copy the mike.key file to his desktop if he didn't recieve it any other way
Open PuTTYgen and from the Conversions menu, select Import, then browse to and select mike.key. Leave the passphrase boxes blank and select Save private key. Click Yes on the confirmation box, and save the key with a .ppk extension, like mike.ppk. This is now a key that PuTTY can use.
Start PuTTY again. Fill out the hostname box, then scroll down to SSH > Auth. Browse for the mike.ppk file. Then go back up to Sesson, give the session a name (for example mike) and save it. Test by logging in with the username ssh. You should see something like this:
login as: svn Authenticating with public key "imported-openssh-key" ( success ( 1 2 ( ANONYMOUS EXTERNAL ) ( edit-pipeline svndiff1 absent-entries ) ) )
With this in place you can set up TortoiseSVN with the key, [I haven't tested this next bit yet] First, create a new folder, then right-click it and select SVN Checkout. In the dialog box, enter this in the URL field svn+ssh://svn@mike/var/svn/repo. svn+ssh is how TortoiseSVN will access your server, svn@mike is your credentials for logging in (mike is the session we set up using the keys in PuTTY), and /var/svn/repo is where the repository is located on the server. Later on in this tutorial we'll configure the server so this can be accessed as svn+ssh://svn@mike/repo.
From James's point of view the process is a bit simpler becasue on Linux the .key file doesn't need to be converted to a .ppk file:
Create a ~/.ssh directory:
mkdir ~/.ssh
Copy the private key to ~/.ssh/id_dsa you don't already have it:
scp svn@example.com:/home/svn/james.key ~/.ssh/id_dsa
Now that the private keys are set up it is time to setup the public keys on the subversion server. Copy the contents of mike.key.pub and james.key.pub to /home/svn/.ssh/authorized_keys so that the each publick key is on a separate line:
touch .ssh/authorized_keys cat mike.key.pub >> .ssh/authorized_keys cat james.key.pub >> .ssh/authorized_keys
It should look something like this but with lots of characters in place of ...:
ssh-rsa AAA...acFHU= svn@example ssh-rsa AAA...acBDH= svn@example
The three columns are TYPE KEY COMMENT. Since the last part is a comment it makes sense to change it to the names of the users so you remember which line referrs to who:
ssh-rsa AAA...acFHU= mike ssh-rsa AAA...acBDH= james
This is all well and good but at the moment Mike and James can also SSH directly into the svn account so we want to restrict their access. Each line in the authorized_keys file can also have a command="COMMAND" section at the start. The subversion client executes svnserve -t when it SSHs in but you can also specify the executable to use explicitly:
command="/usr/bin/svnserve -t" ssh-rsa AAA...acFHU= mike command="/usr/bin/svnserve -t" ssh-rsa AAA...acBDH= james
Now you might want to limit the users to a particular repository, you can do this with the -r option:
command="/usr/bin/svnserve -t -r /var/svn/" ssh-rsa AAA...acFHU= mike command="/usr/bin/svnserve -t -r /var/svn/" ssh-rsa AAA...acBDH= james
James and Mike can access the repo repository with svn+ssh://svn@localhost/repo instead of svn+ssh://svn@localhost/var/svn/repo
You will probably want to limit the other things the users can do with the svn account so you'd probably add no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding to the command like this:
command="/usr/bin/svnserve -t -r /var/svn/",no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAA...acFHU= mike command="/usr/bin/svnserve -t -r /var/svn/",no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAA...acBDH= james
So far, the svnserve command still doesn't know which username it is supposed to be using so we add the --tunnel-user option to tell it explicitly:
command="/usr/bin/svnserve -t -r /var/svn/ --tunnel-user=mike",no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAA...acFHU= mike command="/usr/bin/svnserve -t -r /var/svn/ --tunnel-user=james",no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAA...acBDH= james
At this point everything should now work as expected. Both James and Mike should be able to access and commit to the repository without needing a password and their commits should be logged as james and mike respectively because they are using different private keys and we are using the --tunnel-user approach. No other users should be able to access the repository except the svn user if you know the password.
Further reading:
http://svnbook.red-bean.com/en/1.1/ch06s03.html http://allyourtech.com/content/articles/23_12_2005_setting_up_subversion_and_tortoisesvn.php http://allyourtech.com/content/articles/24_12_2005_ditching_the_password_prompts_in_tortoisesvn.php http://svn.collab.net/repos/svn/trunk/notes/ssh-tricks http://svn.haxx.se/dev/archive-2004-03/0253.shtml http://bitworking.org/news/Getting_subversion_svn_ssh____to_work_with_PuTTY http://www.linuxfromscratch.org/blfs/view/svn/server/svnserver.html
For testing it is also possible to set the $SVN_SSH variable specifying the private key to use with -i so that you can try connecting as different users. For example:
export SVN_SSH="ssh -i /home/james/.ssh/mike.key