Hosting an svn server on Mac OS X

Over the past few years I’ve tried Beanstalk, Assembla and several other svn hosts for some of my projects. They all worked great, and none of them gave me reason for concern, but in the end I’m just more comfortable hosting my source internally.

I have a Mac Mini that serves as a Media Center in my living room. I also use it for some home server tasks since it’s always on and well backed up. I’ve setup svn + apache servers on Linux before, and I figured it should be easy to do the same thing on OS X since it ships with all of the necessary components. Apple makes it easy to configure OS X Server for svn hosting, but it can also be configured on standard OS X with a little command line work.

To get started, open Terminal and execute the following commands. Note that you’ll need to execute all of the commands as sudo since they’re operating on protected directories.

1: Create a repository

First you’ll need to create a repository. I created the repository in /usr/local, but the location doesn’t matter (just make sure you edit the location in Step 2 if you choose something else).

sudo mkdir /usr/local/svn; sudo svnadmin create /usr/local/svn/repo

After you’ve created the repository, you’ll need to change the owner to www so that Apache has permission to access it.

sudo chown -R www /usr/local/svn

2: Configure Apache for SVN Access

Next you’ll need to define the configuration that tells Apache that it should provide WebDAV access to your repository. This can be done by adding a new configuration file in /etc/apache2/other. The default Apache configuration automatically includes any supplemental configuration files from this location.

echo "LoadModule dav_svn_module /usr/libexec/apache2/mod_dav_svn.so
<Location /svn>
  DAV svn
  SVNParentPath /usr/local/svn
  AuthType Basic
  AuthName \"Subversion repository\"
  AuthUserFile /etc/apache2/svn-auth
  Require valid-user
</Location>" | sudo tee -a /etc/apache2/other/svn.conf

3: Create a User Account

Next you’ll need to define a user account for accessing Subversion via Apache. This can be done by running the following command (replace YOUR_USERNAME with your chosen username).

sudo htpasswd -c /etc/apache2/svn-auth YOUR_USERNAME

You may be asked for several passwords here:

  • If prompted for Password: then enter your Mac OS X password. This is being requested because you’re running the command with sudo. You may not be prompted if you’ve run another sudo command in the last few minutes.
  • When prompted for New Password: it’s asking for a new svn password for the account you’re creating
  • When prompted for Re-type Password: it’s asking for you to confirm your new svn password

4: Restart Apache

Once this is done, the only remaining step is to restart Apache. You can do this by restarting the Web Sharing service in System Preferences (or starting it if it’s not running). To do this, go to System Preferences > Sharing > Web Sharing and deselect / re-select the checkbox to restart.

Once this is done, you should be able to access your svn repository at: http://localhost/svn/repo. You will be prompted to enter a username and password. Use whatever you provided in step 3. Enjoy your new repository!


App Engine + JSP + Jersey Viewable Example

I’m putting together a simple App Engine webapp that’s using Jersey as the controller and JSP for the view. Wrapping a Jersey Viewable in a Response, provides a clean way to do this, but I had a bit of trouble getting everything wired up properly. After a little googling I found a post over at Don Park’s Daily Habit that helped me get things right. Here’s a full working example for anyone who’s trying to do the same thing:

Required JARs

I’m using Jersey 1.11

  • asm-3.1.jar
  • jersey-core-1.11.jar
  • jersey-server-1.11.jar
  • jersey-servlet-1.11.jar


<!--?xml version="1.0" encoding="utf-8"?-->

JAX-RS Application

package example;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class JaxRsApplication extends Application {
	public Set&gt; getClasses() {
		Set&gt; classes = new HashSet&gt;();
		return classes;

Root Resource

package example;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import com.sun.jersey.api.view.Viewable;
public class HomeResource {
	public Response get() {
		Map model = new HashMap();
		model.put("word", "World");
		return Response.ok(new Viewable("/home", model)).build();


<!--?xml version="1.0" encoding="UTF-8"?-->
Hello ${it.word}