Sunday, October 26, 2008

SVN & MySQL

Just a week ago, my company migrated to SVN from CVS. I won't go into a discussion of why or what the differences are, but I thought it would be worth writing about our configuration of SVN. Before getting started, I should point you to the free, excellent SVN book found at http://svnbook.red-bean.com/. If you wanted to know about any of the features or configuration options available in Subversion, that's a great place to look.

There were three things that I wanted to accomplish with SVN:

1. Authentication using a MySQL database
2. The ability to manipulate access control at any level in the repository using the MySQL authentication (ie. Only allow access for a user to /client/trunk/project, not to the whole trunk)
3. The connection had to be HTTPS. I don't want our source code going over the internet in plain text.

First, let's cover the basics. Since I'm coming at this from the point of view of a Gentoo installation, I'll cover what's needed for that. The "dev-libs/apr-util" package must be compiled with the "mysql" USE flag enabled. As for apache, I just compile it with all modules enabled. This is easy to accomplish by setting APACHE2_MODULES="*" in /etc/make.conf. As for the MPM to use for Apache, we've been using the "prefork" one. I can't really give an argument for any given MPM since I don't know enough about performance of them to argue a point.

The second step is fairly obvious. You have to compile Apache. It should drag in the apr-util package as a dependency, but if it doesn't for some reason, make sure you compile that package as well. A simple "emerge apache" will do the trick.

The third and final step is to set up the configuration. I'll step through the configuration for our server to give a flavor of what it could look like. You can throw this stuff into a Virtual Host if that is what you want. It's what I did.


#I realize that the document root points to somewhere other than the SVN repositories. This is intentional. It's the only way I could get Subversion to work the way I wanted it to.
DocumentRoot /var/www/localhost/htdocs/

#Enable SSL. It's as simple as turning the engine on and providing the paths to the cert and the key
SSLEngine On
SSLCertificateFile /etc/apache2/ssl/domain.crt
SSLCertificateKeyFile /etc/apache2/ssl/domain.key

#This is the real meat and potatoes of the whole thing.

#This enables the mod_dbd MySQL driver
DBDriver mysql

#This causes mod_dbd to maintain the MySQL connection after every query instead of reconnecting for every MySQL call.
DBDPersist On

#These are the basics for a MySQL connection. Notice that the whole line is surrounded in quotes. See http://httpd.apache.org/docs/2.2/mod/mod_dbd.html for other parameters that can go on this line.
DBDParams "host=mydatabase.server.com user=myuser pass=mypassword dbname=mydatabasename"


# The location "/" causes SVN to interpret anything that follows the "/" as a repository path
<location />
DAV svn #Treat the location as a subversion repository
SVNParentPath /var/svn/ #This treats any directory under "/var/svn/" as the root of a repository
Allow from all #Allow access from anywhere
AuthName "Login" #The title of the authentication window
AuthType Basic #Not quite sure what this does, but it's necessary
AuthBasicAuthoritative Off #Tells Apache to try other authentication methods if this one doesn't work
AuthBasicProvider dbd #Tells Apache to try mod_dbd authentication first
</location>

#A regex that is used to determine the query to use for my current location
<locationmatch ^/client/trunk|tags|branches/project>
# This location requires an authenticated user. AuthDBDUserPWQuery determines how apache decides if the user is valid. The password in MySQL must be stored using the ENCRYPT() function. The supplied password must mach the stored ENCRYPT() password.

Require valid-user
AuthDBDUserPWQuery "SELECT password FROM users WHERE user=%s"
</locationmatch>


That's about it! Not the neatest write-up, but I hope this helps someone. I know I had a heck of a time trying to get it all working correctly. You can add as many locations as you want for different clients and/or subdirectories.

Edit: Something I found out later is that apr-util v1.3.x compiled with MySQL support and PHP compiled with MySQL support don't mix. It will cause Apache to segfault and puke all over the place. Use apr-util v1.2.x to avoid this problem (see https://bugs.gentoo.org/show_bug.cgi?id=240264 for details on the issue).

Thursday, October 9, 2008

Fun With Apache Fix

About a month ago I wrote about a weird problem that I was having with Apache in regards to mod_dbd and the MySQL driver. I never did write about what was causing the problem. After much troubleshooting, I discovered that Apache did not like the mod_dbd driver to be used with PHP if PHP had been compiled with MySQL support. I never could figure out why it was a problem, only that it was the cause of the segmentation fault.

Luckily, my company just recently started using VMware ESX server for virtualization, so I simply made another virtual machine to use for Apache with mod_dbd. SVN uses mod_dbd as a backend for authentication and it works beautifully. Come to think of it, I probably should write up an entry on how to configure SVN to work the way I did. It took me long enough to figure it out, that's for sure.