1 Sep 2011

Lion Server and SVN

Whether you upgraded your server and suddenly found your apache configuration eaten by the allegorical Lion and your Subversion Repository inaccessible or whether you’re running Lion Server from fresh and want to get an HTTP or HTTPS based SVN server set up and running you’ll want to read this. I’ll proceed to save you hours of looking through Lion Server’s new readme files and man pages for scarce morsels of information on the new web configuration interface. Lets begin.
vhost or not vhost
Server admin wasn’t great for Apache configuration, but Lion Server App isn’t anything. 

The red light green light thing shows whether the domain points to your computer or not and is quite cool if your DNS system isn’t too exotic but adding a site seemed maddeningly broken. I read something about adding manually to your apache configs to fix it but that seemed stupid as server.app will happily blow away all your changes in a heartbeat. It so happens that Server only adds the right lines to /etc/apache2/sites/virtual_host_global.conf if you bind the site to a particular IP address. Unlike on snow leopard the order of the vhosts can’t be specified and can be loaded in any order. There is no way to define the same kind of complex configuration you could before.

You need to set up a website here which you will use to access your SVN server. You need the DNS for the domain you specify to point at your server. I settled on something like http://svn.example.com.

EDIT: This broken behaviour is fixed in 10.7.3, and, even more frustratingly, if you do bind your new host to an IP address it will break profile manager as your configuration will override the default one! So in 10.7.3 you need to make sure the IP address box is set to "any".
Plist to meet you
Now comes the fun part. Lion server’s web configuration backend has a cool new plugin type architecture. Its reminiscent of Objective-C’s delegate callback system in as much as they are offering a clearly defined point to insert your own configuration without having to interfere too much in the magic Apple is trying to conduct in the /etc/apache2 directory. It also keeps your special configuration around even after server.app blows away and recreates the /etc/apache2/sites directory for the hundredth time.
man webapp.plist shows you what it can do, which includes adding configuration to a vHost, setting SSL policy, making sure another launchd process is running (e.g. Making sure that if your config is active so is an SQL server) or even requiring another webapp. Web apps are simple to define and follow Apple’s XML property list standard. You don’t need to include all the directives, making them easier to read. Here’s one I made for my subversion server.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!-- See man pages for webapp.plist(5) and webappctl(8) for information about this example webapp.plist -->
<plist version="1.0">


        <array>         <!-- Include files are activated in virtual host when webapp is started -->
        <key>sslPolicy</key>    <!-- Determines webapp SSL behavior -->
        <integer>1</integer>    <!-- 0: default, UseSSLWhenEnabled -->
                        <!-- 1: UseSSLAlways -->
                        <!-- 2: UseSSLOnlyWhenCertificateIsTrustable -->
                        <!-- 3: UseSSLNever -->
                        <!-- 4: UseSSLAndNonSSL -->
The included file referenced is exactly the same file from my Snow Leopard server SVN post that defines the /svn/ part of the domain to present an SVNParentPath.
Contents of /etc/apache2/svn_configs/subversion.conf

        <Location "/svn/"> 
                AuthType Basic 
                        Require group  developers 
                AuthName "svn_auth" 
                SVNParentPath /Groups/developers/repos
                DAV svn

As before this file is set to restrict access to users in the "developers" group by http digest auth.
Web apps can be “started” and “stopped” in a way analogous to a launchd service. There can be a process which is spawned, as chosen in the webapp.plist, and as far as I can tell what starting and stopping a webapp does is alter some config files and reload apache. You can also specify a webapp to attach to a certain vhost only. Using the webappctl tool you can, for example, confine the wiki service to only one vhost
webappctl start com.apple.webapp.collab wiki.example.com

Errors fail with the message web:state = "STOPPED".  This can also mean your server has started successfully. There is no reason given for any error and no hints as to how to fix it so if you can't start a web app you need to look through all your configuration files and try again. Check you apache config files with apachectl configtest and then go though your webapp.plist to make sure all the tags are balanced and that there is no invalid data or syntax errors.

Check which web apps are currently running with
webappctl status -

Final Bits and Pieces
Unfortunately it looks like you can't complete this elegant process without editing httpd.conf manually. No matter how i tried to require the dav svn modules they still needed to be loaded specifically in the httpd.conf file. So crack out your favourite editor and dive in. I added my lines just under loading the dav module.

LoadModule dav_svn_module libexec/apache2/mod_dav_svn.so
LoadModule authz_svn_module libexec/apache2/mod_authz_svn.so

SSL certificates for all services are now defined in one place, in the Hardware section on the Settings Tab of Server.app. 
This is that place
Certificates. I mange them. Get a free certificate from startSSL.com

However I've been getting SSL errors in Xcode (which uses the command line svn tool) but that seems to be a separate issue in that the svn command isn't talking to keychain anymore about which certificates to trust. sigh. Time to move to git? 

In the end it was a bit of a slog but at least I can commit without having been committed.