I finally got sick enough of GoDaddy to buy a Dreamhost account and transfer (nearly) everything over to that account. Although I've only been using it for a few hours, I know I'm going to be far happier with it... especially the Subversion support. Setting up a post-commit hook as described below has made maintenance a lot easier.
Writing off the $50 or so I spent on my GoDaddy account doesn't make me cry, and thanks to a handy coupon code, the new account only cost me about $90 for two years.
My main reasons for transferring over are:
- Subversion support
- SSH shell access
- rsync support
I am so sick of running a slow and crappy ftp mirror to update my files, and a tedious process to upgrade Wordpress and other packages. With the above features, this is going to be a lot easier.
Dreamhost's web admin interface could be a bit quicker, but it's cleanly organised and full-featured. Everything operates as expected, and it didn't take me long to get set up.
The only thing that took me more time than I would have liked is getting post-commit hooks set up on Subversion, so my web projects are kept up-to-date. All I wanted was a simple svn update run in a few directories of the web tree whenever a commit is performed. As this seems to be a frequently asked question, here's what I encountered:
- Errors don't seem to be logged, so it's mainly just fumbling in the dark.
- When accessed through http: (rather than file: or svn+ssh:), the hooks are run as
dhapache, the web server user. - Simply tweaking the permissions of the checkouts to 777 doesn't seem to help that much.
- The hook is going to be chown'ed to you, rather than to dhapache. You could rename post-commit.tmpl, but then you'd have trouble chmod'ding it +x.
- Running setuid (yick!) would get around that problem...
- ...if you could run scripts (as opposed to binaries) setuid'ed. (Yep, I forgot that one)
- ...or if you could be bothered to write them in C, or at least wrapper them with C.
- It's all a moot point, because Dreamhost seem to be undoing setuid flags on a cron, or something similar. Possibly on some form of pre-execution check by dhapache. Not sure.
I tried putting the updates in post-commit itself, but found instead that it's far easier to put them in a CGI script and just use curl inside the post-commit instead. I suspect the post-commit execution has a bogus environment in some way, so I hand it off to the CGI, which is easier to debug.
#!/bin/sh /usr/bin/curl -O http://mywebhost.dreamhosters.com/_svn_update.cgi
The CGI is going to run as you, rather than as dhapache, so the setuid isn't necessary. My CGI looks something like:
#!/bin/zsh
set -f
echo Content-type: text/plain
echo
foreach f (/home/mywebhost/svn/_live/*) {
/usr/bin/svn update $f
}
Now all I need to do is put a bunch of checkouts into ~/svn/_live, and symlink them into my web directories where necessary. I've also thrown in my zshrc file for luck.
I've chosen to use file:/// checkouts rather than http:// for performance, so it's probably best not to try to use them as read-write checkouts... mixing protocols when using hooks is not fun in my experience. Currently, this updates all checkouts if one of them changes, which isn't particularly efficient. I'm going to rewrite it using $1 instead.
I'm sure there's probably a better way of doing all of this, without the intermediate kerfuffle, but this works fine for now.
UPDATE (March 16, 2007): I had another play with it. I think it's possible to get the apache user (dhapache) to correctly perform an svn update on a checkout owned by dhapache, but it doesn't do exactly what I want... I really want the checkouts executed by my user, for various reasons. I also tried some other approaches.
Anyway, I reverted back to the old idea: that of using CGIs, and using $1 to determine the repository in question. I've rewritten the script in Perl (and the corresponding hook), so I can use regular expressions to untaint the parameters. I'd usually pick Perl for an obvious scripting job like this, but PHP would work fine too.
The real overhead is filesystem performance, rather than the CGI call. As DreamHost uses an (obviously overloaded) NFS setup internally, Subversion updates are slowwww (at least this week), even when using file:///. So, fixing the script to only update the specific repository has sped it up a bit.
Incidentally, this script could easily fail dirtily if run at the same time as other stuff going on. I've had to manually run 'svn cleanup' on the _live checkouts. Maybe locking will help...
UPDATE (March 24, 2007): One other thing I forgot to do first time round is disable access to the .svn directories created by the checkout. This would potentially expose stuff to a malicious user. There are several ways of doing this, but I've found the easiest is by adding an appropriate .htaccess file to the project. The standard