Despite the fact that I have set up quite some Subversion servers in the past 15-20 years, I still need to turn to the documentation for the details each time I do it. So, to save myself some time searching and filtering next time, I decided to document it here this time.
Open door: if you don’t know what a Subversion server is, you don’t need this post.
And why Subversion and not Git? Because I prefer having a central repository, so I always know where to find the most recent versions of my files. And you’ll find some more reasons here.
Naturally, to get a good understanding of what you’re doing, and to make decisions that fit your requirements, I’d advise you to read the SVN book instead of this post.
But then again, I’m writing this post mainly for me, so do as you please.
Okay, with that out of the way, let’s set up this server.
I’ll create a single repository, and each user will have access to all of the data it contains; if you need more access restrictions, you can create multiple repositories or have a look at the documentation for Subversion.
The server is Gentoo, but this setup should be the same or very similar for other Unices.
If you’ve read my post about setting up a mail server, you’ll remember that our server is called yellow.example.com.
Make sure the Subversion package is installed.
First, create a group. For now, this group will have only 1 member, but if you decide some day that you need a second repository, the account you create for that repository will be a member of this same group.
root# groupadd svngroup
Second, create a user. This account will be used by everyone who accesses the repository, but don’t worry: users will not share this account’s password. Actually, this account won’t even have a password; users will be accessing the account using SSH keys, so we won’t set a password, thereby eliminating one important risk of security breach. (Actually, I have disabed password authentication altogether.)
root# useradd -c "Account for SVN access" -G svngroup -m -s "/bin/bash" -U svnuser
Now, collect SSH public keys from everybody who needs access to the repository.
To generate such key, a Linux or BSD user would execute
user$ ssh-keygen -f ~/.ssh/svn_rsa
and then send you the file ~/.ssh/svn_rsa.pub.
Windows/PuTTY users check out this page on the PuTTY website for more info.
Obviously, no matter how the key was generated, you call the users on the phone or speak to them in person to verify the fingerprint of their public key, before you accept said key.
While your users are generating their keys and trying to figure out where the f**k they may find those fingerprints, you continue setting up your repository.
Start by creating a directory /srv, if it doesn’t exist yet. Not every distribution includes this directory, but it is defined in the Filesystem Hierarchy Standard, and I actually think that it is a good idea to collect all world-facing services in a single directory (eases security, backup, etc.). Ideally this directory resides on a separate partition or disk.
root# mkdir -m 755 /srv
Create a directory where the repository will resign.
root# mkdir -m 710 /srv/subversion root# chgrp svngroup /srv/subversion
Now, create the repository in that directory.
root# svnadmin create /srv/subversion/repository root# chown -R svnuser:svnuser /srv/subversion/repository root# chmod o-rwx /srv/subversion/repository
Attention: the above is not a typo. The ‘-U‘ switch to the ‘useradd‘ command created a group with the same name as the user, and it’s this group the repository belongs to. The group ‘svngroup‘ was created to limit access to the parent directory.
If you ever need to create a second repository, you can create it in this same directory.
By now you should have received and verified at least some of the SSH public keys, so let’s reward these users with acces to our newly created repo.
An SSH public key looks roughly like this
ssh-rsa AAAAB3NzaC1...hkXm7 user@host
But then way longer. (That’s what the 3 dots mean: ‘and then some‘.)
To give a user normal SSH access, you would copy this key in it’s entirety to /home/svnuser/.ssh/authorized_keys. But since we want to limit the access to Subversion-only, we prepend a command.
This would be the line we add to /home/svnuser/.ssh/authorized_keys for our friend George:
command="/usr/bin/svnserve -t --tunnel-user=george -r /srv/subversion/repository",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB3NzaC1...hkXm7 george@foobar
Once we have this in place, George can connect to the Subversion repository using the address ‘svn+ssh://yellow.example.com/‘ with username ‘svnuser‘. He will not need a server password because he has an SSH key (for which hopefully he does have a password). This SSH key will also tell the server that it’s actually George who is connecting, and George’s name will be added to the Subversion logs for the commits he makes. The name george does not need to exist as a user account at the server.
If George connects from a Linux/BSD/Mac, he could type
user$ svn help
on the command line to get going.
For brevity, he would add these lines to ~/.ssh/config:
Host svnserv HostName yellow.example.com User svnuser IdentityFile /home/george/.ssh/svn_rsa
With that, his Subversion commands would look like
user$ svn ls svn+ssh://svnserv/
If he prefers Windows, he could have a look at TortoiseSVN.
You now have a running and usable Subversion server, but what I’ve told here is not even 1% of what Subversion is capable of, so go read the book.
Changed directory /service back to /srv to comply with the Filesystem Hierarchy Standard.
Changed shell for user svnuser to /bin/bash; access to the repo is refused with /sbin/nologin.
Changed directory /srv to /service for conformity with other blog posts.