I had to setup some SVN repositories in a quite restrictive network today: HTTP works through proxy, and SSH is available.

Options:

  • Setup web access (downside: harder to manage with write access)
  • Use svn+ssh protocol (downside: spawns a separate server process that tries to use the repo)
  • Use ssh port forwarding (downside: SSH must be started before)
  • Do it properly!

I opted for "properly", and here's how:

  1. Make sure, netcat exists on the server
  2. Make sure, ssh access to the server exists (can be a limited ssh account that can only run a single command, and SSH is not used for svn authentication at all)
  3. Create a script on the client calling ssh $1 netcat localhost 3690
  4. Set up a tunnel in ~/.subversion/config, eg. (in section [tunnel]) tunnel = /path/to/clientscript
  5. Access the repo with svn-tunnel://host/path

And that's all there is to it: svn-tunnel gets routed to the tunnel = line, so svn calls the client script with arguments $host svnserve -t, so the client script creates an ssh connection to the server $host, with the command netcat localhost 3690 to be run on the server.

The server calls netcat localhost 3690, providing the svnserve protocol to stdin/stdout like any good tunnel should do, and svn authenticates over it.

For larger deployments, there could be a special ssh user available to all (no auth at all) providing SSH tunneled access to svnserve.

If only subversion knew some substitution syntax, the client side script could be dropped, too (eg. tunnel = ssh %h netcat localhost 3690)