Rolling Your Own SVN Server

It finally dawned on me that using one subversion repository for all my projects was silly. If each project has its own repository, there are some benefits:

  1. My revision comments make lots of sense and follow a logical path.
  2. My revision numbers are more meaningful, and pertain to each project directly.
  3. I can easily share access to one project with someone else if I need to, without exposing all of my work or potentially sensitive information.
  4. I can join the rest of the world that’s using subversion properly.

So why wasn’t I doing this sooner? I learned to use subversion this way, and it actually helped when I decided to use Beanstalk. Beanstalk is awesome, provides lots of hooks and cool features, and is just lovely. The obstacle in my repository-for-every-project quest was Beanstalk’s limit on repositories. With the $15/month account, I could only have 10 repositories. I could pay more for additional repositories, but I’m cheap and ambitious and there seemed like there had to be a better way. And there was. Here’s how I set up stylish subversion hosting with unlimited repositories for $19.95 a month.

Step 1: Sign up for Linode account.

I loved Slicehost but was always curious about Linode; you get just a little bit more for a teeny bit less, and like Slicehost they seem to have a great reputation. I signed up for a Linode 360 account, which gets me blazing fast access to 16GB of storage, 360GB of memory, and 200GB of transfer per month.

Step 2: Prep Linode account.

Linode’s control panel makes it easy to get set up quickly. I installed Ubuntu 8.04 LTS (free). Done.

Step 3: Set up the server.

Equally brainless was installing VirtualMin GPL (free) using the install script, which is designed to work with Ubuntu 8.04. VirtualMin makes it easy to set up virtual hosts and repositories with a web-based GUI. I love the shell, but I find it easier to administer the web server with a GUI like VirtualMin. My brain only has room for about 10 terminal commands before I have to start looking things up. I then followed PickledOnion’s iptables setup instructions (scroll down to find it) to secure things a bit.

Step 4: Make some test repositories.

Log into VirtualMin, set up a virtual server, and add some repositories. Ridiculously easy. I access my subversion repositories via a URL like Tested connecting with Versions, and everything worked just fine and very quickly. I dumped my Beanstalk repository, then imported it to the new server using VirtualMin.

Step 5: Split projects from old setup into their own individual repositories.

I was sailing along feeling clever and upbeat, and then this step was like a punch below the belt. For your benefit, dear reader, I’ll share what worked rather than the grim tale of how I got there.

  1. SSH’d into server via Terminal.
  2. Dumped my current repository.

    svnadmin dump /home/domain/svn/oldrepo > oldrepo.svndump
  3. Split off a single project into its own dump, dropping unrelated revisions and renumbering them. (Note: folder structure is important here, and you should know that a project in my old repository had a path like “/projects/projectname/trunk/”.

    cat oldrepo.svndump | svndumpfilter --drop-empty-revs --renumber-revs include /projects/projectname > projectname.svndump
  4. Keep filtering dumps until your paths work for a new repository. You’ll know if this isn’t working because you’ll get import errors. Long story short: view the dump source with a text editor and make sure that no paths are committed to the new repository that reference non-existing folders. My three steps basically create a tags folder and make sure that trunk gets moved back one level.

    cat projectname.svndump | sed -e 's,^Node-path: projects/projectname,Node-path: tags,' > projectname2.svndump
    cat projectname2.svndump | sed -e 's,^Node-path: tags/trunk,Node-path: trunk,' > projectname3.svndump
    cat projectname3.svndump | sed -e 's,^Node-copyfrom-path: projects/projectname/trunk,Node-copyfrom-path: trunk,' > projectname4.svndump

If you’ve lived through step 4, now all you have to do is create a repository for your project and import your last filtered dump (projectname4.svndump).

Step 6: Add a touch of awesomeness with Warehouse.

Beanstalk is sexy and made it easy for me to share code with others. At this point I was thrilled to have unlimited repositories, but resigned to say goodbye to Beanstalk’s good looks and friendliness. Then Warehouse brought sexy back. I just happened upon Warehouse, a web-based subversion browser that’s built on rails. And it just happened to go open source!

I deployed a few Ruby on Rails apps in the past, and all I remembered was that it wasn’t as easy as plopping PHP and MySQL somewhere. Ultimately the setup was simple, thanks to the last step:

  1. Add a subdomain wildcard for the server in the DNS manager.
  2. Create a MySQL database for Warehouse, upload everything to the server’s web root, and run the installer.
  3. Update Ruby, Rails, and Gems.
  4. Install Phusion Passenger alongside Apache so there aren’t any more steps to install this app. (This is awesome, by the way.)

You can figure out the rest on your own. Enjoy your new repositories, your web-based browser, and your awesome new subversion hosting!


Update: For the hordes of people who followed these instructions and ended up with frustrating blank pages in Safari after multiple page refreshes, there’s a fix:

* * *