Roll your own Subversion server, Roll-out Part 2

To take full advantage of Warehouse’s features, we now weave it into svnserve and get both systems working together. First we will make svnserve hooks that update our warehouse repositories and then we will have Warehouse create our authz and passwd files for svnserve to use.

Hooks

Svnserve has a nice system of hooks that let you execute any script you want at certain moments of a commit. Warehouse has a set of command line actions that let you synchronize the changesets so let’s make a hook which happens after a commit to synchronize the latest changes.

post-commit file

Let’s create the post-commit script:

cd ~/repositories
nano post-commit

Here’s the contents of the script:

#!/bin/sh
cd /home/demo/public_html/warehouse
rake warehouse:post_commit RAILS_ENV=production REPO_PATH=$1 REVISION=$2

As long as the repository and the subfolder have the same name, the repo is automatically chosen by Warehouse so to make things easy and to be able to use this same post-commit file everywhere, let’s keep those names consistent.

Now make the script executable:

chmod +x post-commit

hook your repositories

Finally, we’ll make a symbolic link to the post-commit hook from each of the repos’ hooks directories just like we did with the svnserve.conf files. Be sure to do this for any future repos you create.

ln -fs /home/demo/repositories/post-commit project1/hooks
ln -fs /home/demo/repositories/post-commit project2/hooks

Test it out

Let’s give the automatic syncing a try. Make some changes to your local copy of the repository and make a commit. This should behave normally but now when you revisit your repo in Warehouse, it will have magically been updated with the latest changes. Neat!

SVN Access Files

Let’s get Warehouse to create both our SVN access files (authz) and user/password files (passwd) automatically when changes are made from the web interface. Let’s start with the easy one…

Build authz configuration file

Warehouse let’s you set per-directory access rules on every repo it manages. This allows you to fine tune access for any and all of your users easily. It will also output these rules to a file which svnserve can read and understand to limit access for commits and checkouts, etc.

Let’s set this up, visit the admin settings tab at http://code.example.com/admin/settings. Set the “Shell command to run when permissions are updated” to:

rake warehouse:build_config RAILS_ENV=production CONFIG=/home/demo/repositories/authz

All this does is tell Warehouse to write the permissions we configure in Warehouse to the authz file in our repositories folder.

Re-enable authz-db in svnserve

Now we must tell svnserve to actually use this authz file so hop back into the svnserve.conf file and make the change by uncommenting the authz-db line. It should now look like this:

[general]
anon-access = none
auth-access = write
password-db = /home/demo/repositories/passwd
authz-db    = /home/demo/repositories/authz
realm       = Example Repository

That’s it! Now you can manage repository access right from the Warehouse GUI. Give it a try by changing a permission from the Access pane and seeing if the authz file gets updated correctly.

Note that the default access for new repos in Warehouse is read-only for the primary user so be sure to update that as needed.

Write the passwd file

Warehouse has a mechanism to write to htpassword files (appropriately called rake warehouse:build_htpasswd). These files look just like the passwd file we created in Act I except they don’t include the [users] header. The [users] header is necessary for svnserve to read the file so we must coax Warehouse to add this header. Additionally, Warehouse is configured to write passwd files in a hashed form but svnserve requires plaintext files. So let’s fix this.

Enable Plain Text passwords

Hop back into the Settings pane of the Admin page. Click on “More settings…” at the bottom left and look for the “Authentication Scheme” drop down under the Password Settings section. Choose “Plain” from the drop down and save the new settings. Now you must change your user passwords to make sure they are saved in plain text this time around.

Change Warehouse’s htpasswd method

Now we will actually edit the Warehouse app to get the functionality we want. This isn’t too hard, but unfortunately any updates will temporarily break the password mechanism. So be sure to change this file again if you ever update/change Warehouse. Let’s get to the right file first:

cd ~/public_html/warehouse
cd lib/warehouse

edit command.rb file

Open up the command.rb file:

nano command.rb

and look for the following method (line 98):

def write_users_to_htpasswd(users, htpasswd_path = nil)
    if htpasswd_path.nil?
        htpasswd_path = users
        users         = connection[:users]
    end

    users = users.select(:login, :crypted_password) if users.is_a?(Sequel::Dataset)
    open htpasswd_path, 'w' do |f|
        users.each do |user|
            next if user[:login].to_s == '' || user[:crypted_password].to_s == ''
            f.write("%s:%s\n" % [user[:login], user[:crypted_password]])
        end
    end
    puts "Wrote htpasswd file to '#{htpasswd_path}'"
end

This baby handles the writing of the htaccess file so we simply tell it to write a [users] line before cycling through each user and password. Simply add the following code:

f.write("[users]\n")

To the “open htpasswd_path” loop like this:

open htpasswd_path, 'w' do |f|
    f.write("[users]\n")
    users.each do |user|
        next if user[:login].to_s == '' || user[:crypted_password].to_s == ''
        f.write("%s:%s\n" % [user[:login], user[:crypted_password]])
    end
end

save and restart

Now save the file and restart Warehouse.

sudo /etc/init.d/thin restart

test it out

And that’s it. Let’s give it a try by running the following command:

cd ~/public_html/warehouse
rake warehouse:build_htpasswd RAILS_ENV=production CONFIG=/home/demo/repositories/passwd

Now check the passwd file and ensure that it is written correctly with the [users] header and that your username and password appear:

cat ~/repositories/passwd
...
[users]
admin:password

All together now

Sweet! Warehouse can now dynamically write our authz and passwd files in a format that svnserve understands. This means svnserve is “receiving” instructions from Warehouse on how to behave and is securing your repositories as needed.

The final step is to tell Warehouse to execute that htpasswd command when users are modified. Go back into the Settings of the Admin tab and add the command:

rake warehouse:build_htpasswd RAILS_ENV=production CONFIG=/home/demo/repositories/passwd

to the “Shell command to run when someone’s password is updated.” option. From now on, when you add or update a user, the passwd file will be changed accordingly.

Finale

Phew! That was some decent work up there. But it is worth it. Your Subversion slice is running smoothly with no user/repository restrictions. You have about 8 GB of usable space for your content which is more than any of the SVN hosts out there provide. And with bandwidth cheaper than ever, you shouldn’t break more than $15 a month.

In general, this system covers the needs of the majority of users out there, but for the rest there are a couple of tweaks that might be helpful. In future parts, I will detail how to switch from Nginx to Apache and serve SVN through mod_svn which will increase our security options. There’s also a few other Warehouse tricks that might be helpful to some users. Stay in tune!


blog comments powered by Disqus