Subverting Apache 2
Once again I'm trying to make Apache 2 do my bidding. For non-development web serving I'm still running Apache 1.3; last time I experimented with 2.x I had problems even getting it to build and run properly. Back then (I can't even remember what version it was) it really didn't feel stable enough, certainly not with the modules and functionality I needed.
Why would I want Apache 2 when I already have a 1.3 setup that's working well? I'm not the only web server administrator to ask myself that question, and the slow adoption rate of Apache 2 indicates that most of us have found no compelling reasons to switch. That doesn't necessarily mean we're ignoring it:
- Apache 2 looks like a cleaner, better architecture. A less patchy server, if you will. That's good: it should mean more flexibility and less problems in the long run.
- All new development and improvement are obviously focused on the 2.x versions. Long-standing 1.3 problems and limitations are being fixed in Apache 2.
- Apache 1.3 is a maintenance branch and even though bug fixes will probably be provided for a long time, it won't last forever. The upgrade (or replacement) needs to be done at some point, better do it while there's still plenty of time to prepare and learn.
- There are useful modules that require Apache 2, e.g. mod_dav_svn for the Subversion version control system. I already need mod_dav_svn for remote access to my project repository.
- The threaded MPMs can be expected to be more efficient at serving content. I'm always looking for efficiency improvements.
There is the PHP problem, of course. A threaded MPM means not using mod_php, because not all PHP extensions are thread safe. But I'd like to get rid of mod_php anyway; it's a security liability on servers shared with other users. I think there's a way to solve both problems at the same time, but it remains to be seen if the solution I have in mind is feasible.
So far I have at least managed to get Apache 2 with mod_dav_svn up and running. Until now I've been using svnserve on a local server, which was extremely easy to set up and has worked well. The only problem was that I couldn't connect directly to it from remote locations – there's no built-in encryption in the svnserve protocol to protect passwords and other potentially sensitive data.
The Subversion client has support for connecting to svnserve via SSH tunnels (using svn+ssh:// repository URLs), but by default that will spawn a second svnserve process which will then access the repository directly as the authenticated user. That's not an acceptable solution for my situation.
To minimize the risk for permission problems and repository corruption I want the repository files to be owned and modified by a dedicated Subversion user only. I'd also like to be able to grant repository access without creating new system accounts. I think it might be possible to make the svn client do the right thing, but I want to avoid requiring a complex client setup.
I'm not entirely comfortable with WebDAV either, but mod_dav_svn certainly looks like an attractive way to solve the problem: only the web server have direct access to the repository, remote connections can be encrypted with SSL/TLS, and the module cooperates nicely with the regular HTTP authentication mechanisms, avoiding the need for additional system accounts. As an added benefit, read-only access is possible with just a web browser.
Setting this up was easier than expected. First I compiled Apache 2 with the worker MPM and a fairly standard set of modules including mod_so, mod_ssl, and mod_dav. I explicitly omitted mod_dav_fs because I have no use for it and accidentally enabling it could have serious security implications. Then I built the Subversion Apache modules and configured Apache to load them:
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
mod_authz_svn is an optional authentication extension that makes it easier to control access to directories within a repository. There were some segfaulting initially, caused by compiling the Subversion modules and Apache with slightly different flags. The culprit turned out to be LFS defines – once Apache and mod_dav_svn had been compiled with the same defines (-D_LARGEFILE_SOURCE and -D_FILE_OFFSET_BITS=64) there were no more crashes.
A drawback of mod_dav_svn is that it will access repository files using the main Apache account. There's no way to change that since the module is part of the server, so I'll need to work around this disadvantage by having a web server dedicated to Subversion serving. I created a copy of my current Subversion repository and let mod_dav_svn have a go at it on an SSL-enabled VirtualHost:
<VirtualHost *:443>
ServerName svn.trilithium.net
SSLEngine on
SSLCertificateFile /path/to/certificate
SSLCertificateKeyFile /path/to/keyfile
SSLCertificateChainFile /path/to/ca-certificate
<Location />
DAV svn
SSLRequireSSL
SVNPath /path/to/repository
SVNIndexXSLT /stylesheet/uri
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/htpasswd
AuthGroupFile /path/to/htgroup
AuthzSVNAccessFile /path/to/accessfile
Satisfy any
Require valid-user
</Location>
</VirtualHost>
I need to test it more thoroughly, but so far it has worked beautifully. On the client side pretty much all that needs to change is that repository URLs now have a https:// prefix rather than svn://. There's even support for repository browsing using a web browser, through XSL-styled XML repository directory listings.
The repository browsing via mod_dav_svn is extremely primitive – showing only the youngest revision without any meta-data – and I don't plan to use this feature much, although it might come in handy for casual browsing. I did play with it for a while and created a simple style sheet which you can see in action if you browse my copy of the Linux kernel source code. Most of this repository is still private, and it's a slow server so please be kind to it.
One Apache 2-specific lesson learned by this exercise was that httpd -F is now spelled httpd -DFOREGROUND. I need this rather poorly documented flag to run the Apache daemon under process supervision, ensuring a clean execution environment and automatic restarts on crashes.
Next I need to look into PHP support for threaded Apache 2. I have a feeling that won't be quite as easy.
22 March, 2005
Feedback
Feedback is closed for this entry.