Installing Subversion on BlueHost

This was a rather challenging task that I recently took on in order to setup code versioning for some WordPress Themes and plugins that I have been working on. There were plenty of articles explaining how to compile a Subversion to the $HOME directory on a BlueHost account, but due to a recent OpenSSH update on the BlueHost servers, connections over svn+ssh were failing.

After hours of searching and testing possible workarounds, I found that the best way to resolve the issues with svn+ssh was to use a customized public/private key pair for SVN connections. The following is a step-by-step guide to setting up Subversion on a shared host (BlueHost).

1. Download and Compile Subversion

Downloading and compiling is as simple as copy-and-pasting the following commands:

# mkdir ~/src && cd ~/src
# wget http://subversion.tigris.org/downloads/subversion-deps-1.6.11.tar.gz
# wget http://subversion.tigris.org/downloads/subversion-1.6.11.tar.gz
# tar -xzvf subversion-deps-1.6.11.tar.gz
# tar -xzvf subversion-1.6.11.tar.gz
# cd subversion-1.6.11
# ./configure --prefix=$HOME --without-apxs
# make && make install

Subversion nicely handles all the dependencies, so you won’t have to compile each one individually as long as everything is unzipped into the same directory.  The only thing left to do is modify our $PATH variable so that bash can find the Subversion commands. Edit your ~/.bash_profile script and make sure that you add ~/bin to your path.

~/.bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:~/bin

export PATH
unset USERNAME

Let’s test our installation by attempting to create our repository in the ~/svn directory.

# cd ~ && svnadmin create svn

If everything was installed properly, the commands above should have created a directory at ~/svn.  The structure of the directory will look something like this:

drwxr-xr-x  2 wemaziec wemaziec 4096 Apr 22 19:36 conf/
drwxr-sr-x  6 wemaziec wemaziec 4096 Apr 22 19:36 db/
-r--r--r--  1 wemaziec wemaziec    2 Apr 22 19:36 format
drwxr-xr-x  2 wemaziec wemaziec 4096 Apr 22 19:36 hooks/
drwxr-xr-x  2 wemaziec wemaziec 4096 Apr 22 19:36 locks/
-rw-r--r--  1 wemaziec wemaziec  229 Apr 22 19:36 README.txt

Before moving on to the next step, try issuing an svn list command from your client.

# svn list svn+ssh://user@hostname/home/user/svn

This will most likely fail with a bash: svnserve: command not found error.  This comes about due to a recent update to BlueHost’s OpenSSH services which disabled execution of the .bash_profile script for non-interactive logins, hence the svnserve command cannot be found when connecting with svn+ssh.  Luckily, there is a workaround that will solve this problem.

2. Setup Public/Private Key for SVN

On your BlueHost server, generate a public/private key for use with SVN.  Place the public key in your authorized_keys file with the syntax ‘command=”~/bin/svnserve -t” ‘ at the beginning of the entry for your public key.  The terminal commands below will do this for you automatically.

# ssh-keygen -f ~/.ssh/id_rsa_svn -N '' -q
# echo 'command="~/bin/svnserve -t" ' | cat - ~/.ssh/id_rsa_svn.pub >> ~/.ssh/authorized_keys

Copy the private key to your local ~/.ssh folder

# scp username@hostname:~/.ssh/id_rsa_svn ~/.ssh/

Now, just edit your ~/.subversion/config file and customize the ssh tunnel so that it uses your new private key.

~/.subversion/config

...
### Section for configuring tunnel agents.
[tunnels]
### Configure svn protocol tunnel schemes here.  By default, only
### the 'ssh' scheme is defined.  You can define other schemes to
### be used with 'svn+scheme://hostname/path' URLs.  A scheme
### definition is simply a command, optionally prefixed by an
### environment variable name which can override the command if it
### is defined.  The command (or environment variable) may contain
### arguments, using standard shell quoting for arguments with
### spaces.  The command will be invoked as:
###   <command> <hostname> svnserve -t
### (If the URL includes a username, then the hostname will be
### passed to the tunnel agent as <user>@<hostname>.)  Here we
### redefine the built-in 'ssh' scheme to avoid an unfortunate
### interaction with the "ControlMaster auto" feature (for
### details, see Debian Bug #413102):
#ssh = $SVN_SSH ssh -o ControlMaster=no
ssh = ssh -i ~/.ssh/id_rsa_svn
... 

Now, your client should be able to connect properly, as long as you specify the private key file to use when connecting via svn+ssh:

# svn list svn+ssh://user@hostname/home/user/svn

Update: On some clients you may get a message like “Warning: Identity file ~/.ssh/id_rsa_svn not accessible: No such file or directory.”  If this is the case, try specifying the full path to your private key file in ~/.subversion/config.  For example:

ssh = ssh -i /home/franklin/.ssh/id_rsa_svn

Further Reading