While the WordPress upgrade system is great, sometimes people prefer to use command line tools or similar to manage their sites.
I hadn’t done this much until recently, but when I was at #wptybee, Matt asked me to set up a site using SVN externals. This turned out to be easier than expected, and a great way to keep a site up-to-date and easy to manage. So I thought I’d document the process a little bit here.
This is actually not an uncommon way of creating sites and maintaining them. I’d just never seen it documented anywhere before. If you know SVN, you probably already know how to do this.
Prerequisites
First, you’ll need to have a website on a host. Obviously.
You’ll also need shell access on that host. SSH will do fine.
Next, you’ll need that host to have SVN. Easy way to check: just run “svn –version” at the command line.
Finally, you’ll need an SVN server. A central place to store your files. Some hosts let you set these up easily. Sometimes you’ll have to set one up yourself. How to do this is slightly outside the scope of this article.
Create the SVN environment
The first thing you’ll want to do is to check out your SVN area into a directory on the machine. You can do this part on either your local machine, or on the server. I did it on my Windows 7 laptop, using TortoiseSVN.
The basic idea here is that this site will become your new public_html directory. Alternatively, you can make it a subdirectory under that and use .htaccess rules or any form of rewriting to change where the root of your website is. Regardless, the directory as a whole will be your main website directory.
SVN Externals
Now, we’re going to get WordPress installed into your SVN. To do that, we setup the WordPress SVN to be an external of the SVN root.
If you use TortoiseSVN, then you’re going to right click inside the root of your checkout, then select TortoiseSVN->Properties. In the dialog that follows, you’ll create a new property named “svn:externals” and give it a value of “wp http://core.svn.wordpress.org/trunk/“. Hit OK to make it stick (note, do not select the recursive option).
Note, if you’re using the command line, a guide on svn externals is here:Â http://beerpla.net/2009/06/20/how-to-properly-set-svn-svnexternals-property-in-svn-command-line/.
What this does is simple, really. It tells the SVN that the contents in the “wp” directory will come from http://core.svn.wordpress.org/trunk , which is the main trunk version of WordPress.
Alternatively, if you’re not brave enough to run trunk all the time, you could use http://core.svn.wordpress.org/branches/3.0, which would make it get the latest 3.0 version at all times (which is 3.0.4 right now). And if you wanted to use a directory name other than “wp”, you could change that as well.
The point being that instead of having to manually update WordPress, you’re telling your SVN server that the contents there actually come from another SVN server. So when you do an “update”, it will go and grab the latest version of WordPress directly, without having to updated by hand.
After you’ve modified the externals setting for that root directory, you have to do a commit, to send the new property to the SVN server. Then you can do an update and watch it go and grab a copy of WordPress and put it into your directory directly.
Custom Content
So now we have a WordPress setup, but it’s not installed. No worries, but we’re going to make a custom installation here, so we’ll hand edit the wp-config file eventually.
Why are we doing this? Well, we want our wp-content folder to live outside of the WordPress directory. It’s going to contain our custom plugins and themes and so forth. That way, no changes to WordPress’s files in their SVN can ever touch our own files.
So we need to make a folder in the root called “custom-content”. Or whatever you want to call it. Since this name will be visible in your HTML, you might want to choose a good one.
Now inside that folder, make a plugins and a themes directory. For the themes, you’re probably using a custom theme for your site, and you can just put it in there directly.
Plugins are a different matter.
Plugins as Externals
I assume that whatever plugins you are using are coming from the plugin repository. Or at least, some of them are. For your custom ones, you can do pretty much the same as the themes and just drop the plugins into your plugins directory. But for plugins from the repo, there’s a better way.
In much the same way as we made the wp directory an external pointer to the core WordPress SVN, we’re now going to do the same for our plugins.
So step one, choose a plugin you want. Let’s choose Akismet for a demo.
Step two, in your plugins directory, do the SVN Properties thing again, and this time, add this as an svn:externals of
“akismet http://plugins.svn.wordpress.org/akismet/trunk/” to get the akismet trunk.
Step three, commit and update again, and voila, now you have Akismet.
But wait, we might want more than one plugin. Well, we can do that too. Let’s add the stats plugin.
Step one, go back to the SVN->Properties of the plugins directory.
Step two, edit the existing svn:externals setting. This time, we’re going to add “stats http://plugins.svn.wordpress.org/stats/branches/1.8/” on a new line. Basically, you can have as many externals you want, just be sure to put each one on a new line.
Step three, commit and update and it’ll download the stats plugin.
Repeat for all the plugins you want to keep up-to-date.
You’ll note that I used a branch of the stats plugin instead of the trunk. That’s because the trunk isn’t the latest version in the case of the stats plugin. Not every plugin author treats the trunk/tag/branch system the same, so you should investigate each plugin and see how they keep things up-to-date with their setup.
Theme note
Note that I am using a wholly custom theme, but you might not be. Maybe you’re using a child theme of twentyten. Themes exist inside an SVN too, and you can create externals to them in the same way.
For example, in the themes directory, you could set svn:externals to  “twentyten http://themes.svn.wordpress.org/twentyten/1.1/” and get the twentyten theme for use. Any theme in the Themes directory should be available in this way.
Custom wp-config.php
Now we need to create our wp-config.php file. Grab a copy of the sample wp-config file and put it in the root. Yes, not in the wp directory. WordPress looks in both its own directory and in one directory above it, so having it in the root will still allow it to work and will keep the wp directory untouched.
Edit the file, and go ahead and add all the database details. Then add these lines:
define( 'WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/custom-content' );
define( 'WP_CONTENT_URL', 'http://example.com/custom-content');
You’ll need to use your own directory names and URL, of course. The purpose here is to tell WordPress that the wp-content directory isn’t the one to use anymore, but to use your custom content directory instead.
Special .htaccess
Because we’ve installed wp in a subdirectory off of what will be the root of the site, it would normally be referenced as http://example.com/wp/ which is undesirable. So I crafted some simple .htaccess rules to move the “root” of the site into the /wp directory, and still have everything work.
Options -Indexes
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteCond %{REQUEST_URI} !^/wp/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /wp/$1
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteRule ^(/)?$ wp/index.php [L]
The Options -Indexes just turns off the normal Apache directory indexing. I don’t like it when people try to look through my files. 🙂
The rest basically rewrites any URLs for directories or files that don’t exist into calls to the /wp directory, without actually modifying the URL. The rewrite is internal, so the URL remains the same. This has the effect of moving the root to the /wp directory, but still allowing calls to the custom content directory to serve the right files.
After you’re done, save the file, and commit everything you’ve done so far.
Running it on the site
At this point, you should be capable of going to the site and loading up all that you’ve done onto it. So SSH in (or whatever) and do a checkout of your new SVN setup into the proper location for it. You may need to rename your existing public_html directory and/or set proper permissions on it and such.
If you’re setting up a new site, you’ll be able to go to it and have it create the database tables and such as well.
What’s the point?
Okay, so you may have read through all this and wondered what the point was. Well, it’s simple, really.
Go to your server, and do “svn up public_html”… and then watch as it proceeds to update the entire site. WordPress, plugins, themes, your custom files, everything on the site. The externals makes WordPress and the plugins and such all update directly from the WordPress SVN systems, allowing you to do one command to update them all.
If you didn’t use trunk, then updating is only slightly harder. Basically, you just change the externals to point to the new version, then commit and do an svn up.
In fact, if you want to live dangerously, you can hook everything to trunk and then have it automatically do an svn up every night. Not many people recommend running production sites on trunk, but for your own personal site, why not? You’ll always get access to the latest features. 🙂
An additional thing to keep in mind is that with a system like this, the files on the site are always backed up on the SVN server. For things like inline file uploads, you’ll need to log in every once in a while and do “svn add” and “svn commit” to send the new files to the SVN server, but for the most part, everything on the site will be in your SVN and you can work with it locally before sending it to the site proper.
And it’s expandable too. You can get your sites files from any host that has svn on it. You could run more than one webserver, and have them on a rotation or something. There’s a lot of possible configuration methods here.
It sure is a nice way to update though. 😀