<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Steve Taylor &#187; Apache</title>
	<atom:link href="http://sltaylor.co.uk/blog/category/apache/feed/" rel="self" type="application/rss+xml" />
	<link>http://sltaylor.co.uk</link>
	<description>Freelance WordPress developer in London - XHTML, CSS &#38; design</description>
	<lastBuildDate>Mon, 19 Jul 2010 09:39:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>WordPress server requirements</title>
		<link>http://sltaylor.co.uk/blog/wordpress-server-requirements/</link>
		<comments>http://sltaylor.co.uk/blog/wordpress-server-requirements/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 14:59:43 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=224</guid>
		<description><![CDATA[WordPress has famously low-level basic server requirements. However, most projects I deploy&#8212;because of plugins I rely on and other aspects&#8212;usually need a little more for &#8220;ideal&#8221; hosting. Someone else used to maintain a really good &#8220;ideal&#8221; WP requirements page, but it seems to have vanished from their site. I thought I&#8217;d start my own, for [...]]]></description>
			<content:encoded><![CDATA[<p>WordPress has famously low-level <a href="http://wordpress.org/about/requirements/">basic server requirements</a>. However, most projects I deploy&#8212;because of plugins I rely on and other aspects&#8212;usually need a little more for &#8220;ideal&#8221; hosting.</p>
<p>Someone else used to maintain a really good &#8220;ideal&#8221; WP requirements page, but it seems to have vanished from their site. I thought I&#8217;d start my own, for my reference, to point potential clients to, and maybe of use to others.</p>
<p><span id="more-224"></span></p>
<p>The server should be running:</p>
<ul>
<li>Linux</li>
<li>Apache</li>
<li>PHP 5+</li>
<li>MySQL 4+</li>
</ul>
<p>Also, these factors are very important:</p>
<ul>
<li>The <code>mod_rewrite</code> Apache module should be installed and enabled.</li>
<li>PHP <code>safe_mode</code> should be OFF. Turning it on is a bad attempt to manage security on shared hosting.</li>
<li>The PHP <code>memory_limit</code> should be 32 MB at least. If it&#8217;s not at least this by default, it should be possible to increase it to at least this.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/wordpress-server-requirements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Detecting WordPress login via htaccess</title>
		<link>http://sltaylor.co.uk/blog/detecting-wordpress-login-via-htaccess/</link>
		<comments>http://sltaylor.co.uk/blog/detecting-wordpress-login-via-htaccess/#comments</comments>
		<pubDate>Wed, 01 Jul 2009 12:37:39 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=154</guid>
		<description><![CDATA[I just had to come up with a quick bit of .htaccess code to very basically protect PDFs on a client&#8217;s site from being downloaded by people who aren&#8217;t logged into WordPress. I thought I&#8217;d share the code, specifically to highlight the way to detect if someone&#8217;s logged into WP through Apache&#8217;s directives. Here&#8217;s my [...]]]></description>
			<content:encoded><![CDATA[<p>I just had to come up with a quick bit of <code>.htaccess</code> code to very basically protect PDFs on a client&#8217;s site from being downloaded by people who aren&#8217;t logged into WordPress. I thought I&#8217;d share the code, specifically to highlight the way to detect if someone&#8217;s logged into WP through Apache&#8217;s directives.</p>
<p><span id="more-154"></span></p>
<p>Here&#8217;s my code:</p>
<pre name="code" class="php">RewriteCond %{SCRIPT_FILENAME} /wp-content/uploads/.*\.pdf$ [NC]
RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in_.*$
RewriteRule .* http://domain.com/ [F,L]</pre>
<p>The first line matches requests for PDF files in the uploads folder. You can change that however you want. The key is the second line, which is the match for the WP cookie you&#8217;ll have if you&#8217;re logged in.</p>
<p>Note that the name of the actual cookie has a string of random characters at the end, which I assume WP generates to make the login cookie hard or impossible to fake. I don&#8217;t know a way to access this value outside WP. I&#8217;d be interested if anyone knows how; I&#8217;d also suspect this would be a security hole in WP!</p>
<p>In the above example, if someone knew the PDF&#8217;s URL, didn&#8217;t have a login to your site, and <em>really</em> wanted to download the file, I&#8217;m sure they could fake the login cookie easy enough. If you need tighter security than this on downloads, you should probably look at a plugin like <a href="http://wordpress.org/extend/plugins/download-monitor/">Download Monitor</a>, which provides &#8220;mask&#8221; URLs for files, and thus can process login checks via PHP code from within the WP framework before returning the download.</p>
<p>Note also that I&#8217;m not sure that <code>http://domain.com/</code> is necessary in the last line. The <code>F</code> flag after it returns a 403 status code, so you get the browser&#8217;s &#8220;Forbidden&#8221; page instead of any URL that you specify as the redirect.</p>
<p>Any suggestions for improvement to this quick-and-dirty trick welcome!</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/detecting-wordpress-login-via-htaccess/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ignoring internal rewrites in .htaccess</title>
		<link>http://sltaylor.co.uk/blog/ignoring-internal-rewrites-in-htaccess/</link>
		<comments>http://sltaylor.co.uk/blog/ignoring-internal-rewrites-in-htaccess/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 01:17:45 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=76</guid>
		<description><![CDATA[mod_rewrite is a notoriously fiendish chunk of software, almost legendarily so among web developers. I&#8217;ve got by with snippets in my .htaccess file, stuff that makes sure there&#8217;s no &#8220;www&#8221; in the URL, and managing holding pages. I absorbed a lot of how it works, but I couldn&#8217;t readily construct my own rewrites. Until tonight. [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-117" title="mod-rewrite" src="http://sltaylor.co.uk/wp-content/uploads/2009/02/mod-rewrite.jpg" alt="mod-rewrite" width="240" height="240" /><a href="http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html">mod_rewrite</a> is a notoriously fiendish chunk of software, almost legendarily so among web developers. I&#8217;ve got by with snippets in my <a href="http://corz.org/serv/tricks/htaccess.php">.htaccess</a> file, stuff that makes sure there&#8217;s <a href="http://no-www.org/">no &#8220;www&#8221;</a> in the URL, and <a href="/blog/2007/04/503-holding-page/">managing holding pages</a>. I absorbed a lot of how it works, but I couldn&#8217;t readily construct my own rewrites.</p>
<p>Until tonight.</p>
<p>I was forced to solve a situation involving a WordPress site which had some legacy flat HTML content. Way back when, I hacked it to use <code>.html</code> suffixes on the WP URLs, so we didn&#8217;t lose any search engine juice for the old URLs. This necessitated changing core WP code&#8212;always a bad idea&#8212;and thus blocked any automatic WP upgrade process. Which is a pain.</p>
<p>So, I&#8217;ve removed the <code>.html</code> hack, and tried to pull flat HTML content in for the old stuff, under the guise of smooth new <code>.html</code>-free URLs.</p>
<p><span id="more-76"></span></p>
<p>Say we have something that was at <code>/news_2004_09.html</code>. First, we redirect to new URLs:</p>
<pre name="code" class="php">RewriteRule ^news_([0-9]{4})_([0-9]{2})\.html$ /news/$1/$2/ [R=301,L]
RewriteRule ^(.*)\.html$ /$1/ [R=301,L]</pre>
<p>The first bit redirects (301 = permanently) pages with the format <code>news_[year]_[month].html</code> to <code>news/[year]/[month]/</code>. The second line deals with all other pages that used to have <code>.html</code> endings.</p>
<p>Now to pull in flat HTML:</p>
<pre name="code" class="php">RewriteRule ^news/([0-9]{4})/([0-9]{2})/$ /html-news/news_$1_$2.html [L]</pre>
<p>Note the absence of the <code>R=301</code> flag. Without this, an &#8220;internal rewrite&#8221; instead of an &#8220;external redirect&#8221; happens. For the end user, what this amounts to is that the URL you typed in or clicked on will stay the same&#8212;just the way the resource used by the server for that request will alter. <code>R=301</code> (or any other <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP status code</a>) will make the URL in the browser change&#8212;meaning this URL will get bookmarked, indexed, etc.</p>
<p>All well and good, <em>but</em> (and this is where my last couple of hours have gone)&#8230; Even though no <code>R</code> flag means it&#8217;s an &#8220;internal rewrite&#8221;, and the <code>L</code> flag indicates this is the <em>last</em> rule to be processed, Apache <em>still</em> effectively &#8220;makes another request&#8221;.</p>
<p>I don&#8217;t think this involves more traffic between the server and browser, and I think it&#8217;s related to the fact that the rewriting is being set up in <code>.htacccess</code> (rather than at the server level, in <code>httpd.conf</code>). I&#8217;m not quite sure.</p>
<p>The end result is, <em>all your other rules get processed again, even though you gave it that <code>L</code> flag</em>! So for me, the old URL was going through the following rewrites:</p>
<ol>
<li><code>http://example.com/news_2004_09.html</code> (initial URL)</li>
<li><code>http://example.com/news/2004/09/</code> (permanent redirect)</li>
<li><code>http://example.com/html-news/news_2004_09.html</code> (&#8220;internal rewrite&#8221;, not visible to browser)</li>
<li><code>http://example.com/html-news/news_2004_09/</code> (another permanent redirect)</li>
</ol>
<p>See what happened? My catch-all code for changing old <code>.html</code> URLs was processing the &#8220;internal rewrite&#8221; URL. That last step shouldn&#8217;t have happened. The browser&#8217;s URL should have stopped at stage 2, with the content coming from the rewrite in stage 3. Instead, I got the URL in stage 4, with no content at all.</p>
<p>The solution? Well, thanks to <a href="http://forum.modrewrite.com/viewtopic.php?p=18628">Richard K on the Mod_Rewrite forums</a>, here it is:</p>
<pre name="code" class="php">RewriteRule ^news_([0-9]{4})_([0-9]{2})\.html$ /news/$1/$2/ [R=301,L]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)\.html$ /$1/ [R=301,L]
RewriteRule ^news/([0-9]{4})/([0-9]{2})/$ /html-news/news_$1_$2.html [L]</pre>
<p>I worked out a while ago that I needed a <code>RewriteCond</code> before my catch-all rule, but I couldn&#8217;t for the life of me find the condition to test if the current request is a result of an internal rewrite already.</p>
<p><code>ENV:REDIRECT_STATUS</code> is my new best friend.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/ignoring-internal-rewrites-in-htaccess/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Asus Eee PC, Ubuntu, LAMP &amp; ColdFusion</title>
		<link>http://sltaylor.co.uk/blog/asus-eee-pc-ubuntu-lamp-coldfusion/</link>
		<comments>http://sltaylor.co.uk/blog/asus-eee-pc-ubuntu-lamp-coldfusion/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 21:40:32 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[hardware]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/?p=34</guid>
		<description><![CDATA[I recently got an Asus Eee PC 1000H. For writing, travel, and learning Linux. I wanted to get Ubuntu working on it (a friend recommended it), the Apache/MySQL/PHP trinity (essential for work), and ColdFusion (not essential for work these days, but a few little apps I&#8217;ve written&#8212;for use locally&#8212;use CF). There&#8217;s been a whole series [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://sltaylor.co.uk/wp-content/uploads/2008/10/asus-eee.jpg" alt="asus-eee" title="asus-eee" width="200" height="200" class="alignright size-full wp-image-122" />I recently got an Asus Eee PC 1000H. For writing, travel, and learning Linux. I wanted to get Ubuntu working on it (a friend recommended it), the Apache/MySQL/PHP trinity (essential for work), and ColdFusion (not essential for work these days, but a few little apps I&#8217;ve written&#8212;for use locally&#8212;use CF).</p>
<p>There&#8217;s been a whole series of hoops to jump through. I&#8217;m no tech novice, but Windows and occasional Mac use has been my staple thus far. Of course you can&#8217;t do much in web development without knowing a bit of Linux at least; still, wrangling with various desktop issues can be a chore.</p>
<p>The web, or Google (if there&#8217;s a difference) is your friend. Finding a comprehensive tutorial that covers your precise situation is rare if not impossible; you need that familiar net skill of cobbling together varying perspectives and bits of advice into something that works for you. That said, I&#8217;ll point to <a href="http://www.iknowkungfoo.com/blog/index.cfm/2008/6/6/The-ACME-Guide-64bit-Ubuntu-804-Edition-Part-1">this ACME Guide</a> up-front as a fantastic source of information on getting web development stuff going.</p>
<p>I also picked up <a href="http://oreilly.com/catalog/9780596006280/">the O&#8217;Reilly <i>Linux Pocket Guide</i></a>. It&#8217;s a good little intro to the Linux environment as well as a useful reference point.</p>
<p>Anyway, here&#8217;s my summary of what I&#8217;ve learned. Hope it&#8217;s useful for you! (As ever, this information is used at your own risk. I can&#8217;t support you if stuff goes wrong&#8212;but do let me know if you know for sure I&#8217;ve, for example, mis-typed commands!)</p>
<p><span id="more-34"></span></p>
<h2>Ubuntu Eee</h2>
<p><img src="http://sltaylor.co.uk/wp-content/uploads/2008/10/ubuntu-eee.png" alt="ubuntu-eee" title="ubuntu-eee" width="130" height="130" class="alignright size-full wp-image-124" />I got a 40GB Eee with Linux pre-installed. Knowing I was going to shift to Ubuntu anyway (the default version of Linux on the Eee is the clunky Xandros), I probably should have gone for the 80GB Windows version&#8212;it&#8217;s cheaper!</p>
<p>Anyway, in either case, the good news for people wanting Ubuntu is that there&#8217;s a special distribution of this system especially tailored for the Eee: <a href="http://www.ubuntu-eee.com/">Ubuntu Eee</a>. Follow <a href="http://www.ubuntu-eee.com/wiki/index.php5?title=Get_Ubuntu_Eee">their instructions</a>.</p>
<p>My only real sticking point here was that the <a href="http://www.ubuntu-eee.com/wiki/index.php5?title=How_to:_Using_Unetbootin">UNetbootin</a>-created USB installation drive didn&#8217;t boot. The Eee doesn&#8217;t have a CD/DVD drive, so this utility unpacks the disk image (ISO) of the Ubuntu system onto a USB stick, making it bootable. I only solved this by getting a new USB stick for this purpose. The first one was oldish, and only 1GB. This is theoretically enough, but they say a 2GB stick is recommended. Indeed.</p>
<h3>The /home directory</h3>
<p>The Ubuntu Eee install is pretty slick. The only thing I think I missed was relocating the <code>/home</code> directory. This is where most user files are kept in Linux. The Eee seems to come with its main hard disk (actually a solid-state disk) partitioned into two&#8212;mine had one with around 8GB, one with around 32GB. I wiped the Xandros installation off the smaller one and installed Ubuntu there. It was only after installation that I got round to thinking my <code>/home</code> should be on the big partition for all my data&#8230;</p>
<p>There are other options of course&#8212;search and you&#8217;ll find myriad opinions. If you end up in my position, here&#8217;s what to do. I waded through a number of ad-riddled blog posts and forum threads, but <a href="https://answers.launchpad.net/ubuntu-eee/+question/46718">this one</a> seemed to nail it in the end.</p>
<p>Be aware that some of this can go wrong. I managed to make some drastic mistakes here, but Linux is quite sturdy and I managed to recover OK. This definitely isn&#8217;t for total beginners.</p>
<ol>
<li>Close all applications. Print this out or write it down.</li>
<li>Open a command line terminal.</li>
<li><code>sudo su</code><br />
This shifts the session to &#8220;root&#8221; or &#8220;super-user&#8221; (after you enter the password for your own user account). You can prefix individual commands with <code>sudo</code> to temporarily shift from your own user account that was created with the Ubuntu installation to the root account, needed for many system operations. But it can get tedious. This trick keeps you operating as root until you type <code>exit</code>.</li>
<li><code>cd /media/HOME</code><br />
This shifts you into the large partition, which, in the default Ubuntu-Eee install, is mounted with the label &#8220;HOME&#8221;. Linux devices (like disks and drives) are generally registered in the <code>/dev</code> directory. My boot partition is <code>/dev/sda</code>, and my O&#8217;Reilly guide says <code>sda</code> is usually the &#8220;First SCSI&#8221; device (whereas the master hard disk should be <code>hda</code>). I guess this is down to the Eee having solid-state disks instead of hard disks? A detail to watch for. Anyway, this large partition&#8217;s mount is here in the <code>/media</code> directory, usually for external devices&#8212;there&#8217;s a <code>/mnt</code> directory for usual hard disk partition mounts.
</li>
<li>Now, there&#8217;s probably some user directories in <code>/media/HOME</code> left over from Xandros. Obviously grab what you might need, but I felt like a clean slate. Beware, this next command will wipe that partition:</li>
<li><code>rm -r *</code><br />
Remove (<code>rm</code>) recursively (<code>-r</code>)&#8212;that is, all sub-directories and contents&#8212;everything in the current directory (<code>*</code>).</li>
<li><code>unmount /media/HOME</code><br />
Pretty self-explanatory. A useful command you can check this with is <code>df</code>&#8212;it&#8217;ll list all mounted filesystems.</li>
<li><code>mv /home /home.bak</code><br />
<code>mv</code> &#8220;moves&#8221; (actually renames) a file or directory. Here, it basically backs up the <code>home</code> directory by renaming it.</li>
<li><code>mkdir /home</code><br />
This creates a new <code>/home</code> directory.</li>
<li><code>mount -t ext3 /dev/sdb1 /home</code><br />
Now this re-mounts the large partition, <code>/dev/sdb1</code>, under the new <code>/home</code> directory. So now <code>/home</code> points to the partition. Do double-check the partition&#8217;s reference first. Use <code>fdisk -l</code>, which will (for root) show all connected disks, mounted or not, with their details. <code>/dev/sdb</code> is the second (&#8220;b&#8221;) SCSI device, and <code>/dev/sdb1</code> is its first partition. It&#8217;s usually easy to identify drives and partitions by their sizes. Note that <code>ext3</code> is the filesystem format (like NTFS in Windows).</li>
<li><code>cp -a /home.bak/* /home</code><br />
This copies the contents of the old <code>/home</code> into the new partition.</li>
<li>You should be up and running now with <code>/home</code> located on the large partition. The only thing left to do is make sure this mount happens each time you boot up. This sort of stuff is managed by the <code>/etc/fstab</code> file. If you&#8217;re still root in the terminal, you can open it for editing by entering:<br />
<code>gedit /etc/fstab</code><br />
This will open the file in the text editor, with root permissions (essential for saving it!). If you&#8217;re not root anymore, just prefix the above with <code>sudo</code> (you&#8217;ll get used to this).</li>
<li>At the bottom, add the line:<br />
<code>/dev/sdb1	&nbsp;&nbsp;/home &nbsp;&nbsp;ext3 &nbsp;&nbsp;nodev,nosuid &nbsp;&nbsp;0 &nbsp;&nbsp;2</code><br />
By now I imagine you&#8217;ll roughly see what&#8217;s going on in this.</li>
</ol>
<h3>Automounting the USB stick</h3>
<p>That&#8217;s hopefully it for moving <code>/home</code>. But while we&#8217;re editing <code>fstab</code>, there&#8217;s another thing. I found after installing Ubuntu, the USB stick I&#8217;d successfully used was no longer &#8220;automounting&#8221; when I plugged it in. After a bit of searching, someone suggested commenting out the lines referring to <code>/media/cdrom</code>. Just put a <code>#</code> at the start of each line. Seems to be something to do with how the system has to recognize the stick as a boot device initially, which is no longer the case. Anyway, worked for me.</p>
<h2>LAMP</h2>
<p>After all that, LAMP (or AMP at least&#8212;Linux is done!) brings good news.</p>
<p>In Ubuntu, open up Synaptic Package Manager. This is basically a nice GUI for the &#8220;Advanced Packaging Tool&#8221;. You&#8217;ll see plenty of command line examples for installing software (&#8220;packages&#8221;) on Linux with the <code>apt-get</code> program&#8212;the part of the APT family that grabs software from remote repositories. Synaptic makes it all a breeze.</p>
<p>Select <b>Edit &gt; Mark Packages by Task</b>, and from that list select LAMP Server. This will check all the components of the LAMP bundle of packages. You may as well also search (with the Synaptic search tool) for &#8220;phpMyAdmin&#8221; (the trusty web interface for MySQL)  and/or &#8220;mysql-admin&#8221; (the MySQL desktop GUI), and check one or both of those. Just click the box at the left of the package listing and select <b>Mark for Installation</b>.</p>
<p>If you want to install ColdFusion, too, search for &#8220;sun-java6-bin&#8221;. CF&#8217;ll need it.</p>
<p>Any time you use Synaptic, once you&#8217;ve selected everything you want (a process that might also auto-select other packages that the ones you&#8217;ve chosen are dependent on), click <b>Apply</b>.</p>
<p>One of the nicest parts of getting all this going was, after installing LAMP, opening up a browser and going to <i>http://localhost/</i>. In big letters I found that &#8220;It works!&#8221;. Hope you do too.</p>
<p>For more details, do refer to that great <a href="http://www.iknowkungfoo.com/blog/index.cfm/2008/6/6/The-ACME-Guide-64bit-Ubuntu-804-Edition-Part-1">ACME Guide</a> (though you might need to ignore the stuff about 64-bit versions).</p>
<h3>Keeping www somewhere else</h3>
<p>As I&#8217;d decided to keep all my data on that other partition, I also wanted to keep my <code>www</code> directory, for all the local files of websites I&#8217;m developing, there too. I was kind of dreading some trawl through Apache configuration, but thankfully Linux offers a simple solution: a <a href="http://en.wikipedia.org/wiki/Symbolic_link">symbolic link</a>.</p>
<p>Also known as a symlink or soft link, symbolic links are just small files that direct operations from one part of the filesystem to another.</p>
<ol>
<li>Create your web files directory in your user folder, e.g. <code>/home/steve/www</code>.</li>
<li>Apache&#8217;s default web directory is <code>/var/www</code>. If there&#8217;s anything in there you want, copy it to the new one. Then delete the directory.</li>
<li>In a terminal, as root (or using the <code>sudo</code> prefix), enter:<br />
<code>ln -s /home/steve/www /var/www</code><br />
Obviously, change the <code>steve</code> bit! The <code>-s</code> specifies a symbolic link. The next bit is the target directory to point to, and the bit after that effectively recreates <code>/var/www</code> as a link to it.</li>
</ol>
<p>Now you can keep your web files in <code>/home/[wherever]/www</code>, and anything referencing anything starting with <code>/var/www</code> will point there.</p>
<p>Oh, if you&#8217;ve wondered, in looking in the <code>www</code> folder, where the heck phpMyAdmin is&#8212;you&#8217;re not alone. Mine works fine at <i>http://localhost/phpmyadmin/</i>, but I&#8217;ve no idea how this is so, or where it points. Ah well.</p>
<h2>ColdFusion</h2>
<p>There&#8217;s not much I can add to <a href="http://www.iknowkungfoo.com/blog/index.cfm/2008/6/8/The-ACME-Guide-64bit-Ubuntu-804-Edition-Part-2">the ACME Guide&#8217;s lowdown</a> on this. It&#8217;s a good brief education in some basic Linux concepts, too. Thanks to Adrian J. Moreno.</p>
<h2>Fonts</h2>
<p>I&#8217;ve still got loads to learn, but one final tip that will hopefully help you enjoy Ubuntu more. <a href="http://mondaybynoon.com/2007/04/02/linux-font-equivalents-to-popular-web-typefaces/">This page</a> pointed me to <a href="http://corefonts.sourceforge.net/">Microsoft&#8217;s core fonts for the web</a>. They should make browsing a little more pleasant. You can install them from Synaptic (of course)&#8212;search for &#8220;msttcorefonts&#8221;.</p>
<p>That&#8217;s it for now. Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/asus-eee-pc-ubuntu-lamp-coldfusion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The holding page and the 503 status code</title>
		<link>http://sltaylor.co.uk/blog/503-holding-page/</link>
		<comments>http://sltaylor.co.uk/blog/503-holding-page/#comments</comments>
		<pubDate>Wed, 04 Apr 2007 19:54:48 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/04/503-holding-page/</guid>
		<description><![CDATA[NOTE: I&#8217;ll leave the information here for reference as it&#8217;ll probably still be useful to some. But for anyone using WordPress who wants a convenient way of putting up a holding page without confusing search bots and without blocking yourself from using the site while it&#8217;s &#8220;down&#8221;, I&#8217;ve just found the very neat Maintenance Mode [...]]]></description>
			<content:encoded><![CDATA[<p class="alert"><strong>NOTE:</strong> I&#8217;ll leave the information here for reference as it&#8217;ll probably still be useful to some. But for anyone using WordPress who wants a convenient way of putting up a holding page without confusing search bots <em>and</em> without blocking yourself from using the site while it&#8217;s &#8220;down&#8221;, I&#8217;ve just found the very neat <a href="http://sw-guide.de/wordpress/plugins/maintenance-mode/">Maintenance Mode plugin</a>. Seems to work like a treat. <i>14/2/08</i></p>
<p>Ever wanted to have a system in place that allows you to easily &#8220;switch on&#8221; a holding page for the whole of your site for when you need to do some maintenance? Well, that&#8217;s relatively easy to do; but what about bots? Even if you&#8217;re only down for 10 minutes, what if your luck is such that <a href="http://www.google.com/support/webmasters/bin/topic.py?topic=8843">Googlebot</a> makes its random rounds at precisely that time? Depending on how you&#8217;re holding page works, it might register a load of &#8220;404 &#8211; Not Found&#8221; errors, or replace your indexed content with your holding page&#8230; Who knows? Not I.</p>
<p><span id="more-19"></span></p>
<p>Well, with yet another WordPress upgrade (2.1.3) just out, I thought I would try to get to the bottom of this holding page issue. WordPress upgrades might be made smoother in a future version; but for now, it&#8217;s a slightly brutal case of deleting your live files and replacing them. Even without discovering some hair-tearing plugin incompatibilities along the way, or accidentally overwriting a crucial hack you&#8217;ve coded into your installation, a proper upgrade can take 10-20 minutes.</p>
<p>The only really useful page I found on the issue of bots and holding pages was over at <a href="http://www.askapache.com/htaccess/instruct-search-engines-to-come-back-to-site-after-you-finish-working-on-it.html">AskApache.com</a>. You can head over there and work out your own adaptation; I thought I&#8217;d document mine here for reference.</p>
<p>Note that the basics of this require PHP running on an Apache web server, with <code>mod_rewrite</code> enabled. The rest assumes you&#8217;re using WordPress.</p>
<h2>The holding page</h2>
<p>I created a file, <code>503.php</code>, sitting in my site&#8217;s root. The code looks something like this:</p>
<pre name="code" class="php">&lt;?php
header(&quot;HTTP/1.1 503 Service Temporarily Unavailable&quot;);
header(&quot;Status: 503 Service Temporarily Unavailable&quot;);
header(&quot;Retry-After: 3600&quot;);
?&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;html xml:lang=&quot;en&quot; lang=&quot;en&quot; xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;
&lt;title&gt;Site upgrade in progress&lt;/title&gt;
&lt;meta name=&quot;robots&quot; content=&quot;none&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Site upgrade in progress&lt;/h1&gt;
&lt;p&gt;This site is being upgraded, and can't currently be accessed.&lt;/p&gt;
&lt;p&gt;It should be back up and running very soon. Please check back in a bit!&lt;/p&gt;
&lt;hr /&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Those first two lines of PHP set the request&#8217;s HTTP headers to the &#8220;503 Service Unavailable&#8221; <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">status code</a>. HTTP headers are invisible when you&#8217;re browsing the web, but are read by the browser itself and by bots crawling around (and can be checked out via tools like <a href="http://web-sniffer.net/">Web-Sniffer</a> and the Firefox <a href="http://chrispederick.com/work/webdeveloper/">Web Developer Extension</a>). This status code means:</p>
<blockquote cite="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"><p>The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay.</p></blockquote>
<p>Just what we want.</p>
<p>The <code>Retry-After</code> bit is used to indicate how long you expect the site to be down for (in seconds). If you are hit by a search engine bot while down, it&#8217;ll probably understand this, but of course it doesn&#8217;t mean it&#8217;ll return as soon as that time&#8217;s elapsed. It&#8217;s probably got better things to do. At least it knows not to return too soon.</p>
<p>The rest is a plain page for humans, letting them know in English what&#8217;s going on. It needn&#8217;t be as minimalist as this; you can add branding if you want, and maybe a link to another site to be polite and give people a &#8220;way out&#8221;.</p>
<h2>Allowing yourself access</h2>
<p>The next step is to alter your <code><a href="http://httpd.apache.org/docs/1.3/howto/htaccess.html">.htaccess</a></code> file to make sure all requests go to the 503 page.</p>
<p>But hang on &#8211; what about your good self? How do you test out all the maintenance you&#8217;re doing if you&#8217;re just being sent to <code>503.php</code> with everyone else?</p>
<p>Basically, you filter requests by IP address. Assuming you have a static IP address, you can test that, and only let your own IP through.</p>
<p>Here&#8217;s the code for your <code>.htaccess</code> file:</p>
<pre name="code" class="php">Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REMOTE_ADDR} !^23\.23\.23\.23
RewriteCond %{REQUEST_URI} !^/503.php [NC]
RewriteRule .* /503.php [L]</pre>
<p>Just replace those numbers on the fourth line with <a href="http://www.whatismyipaddress.com/">your own IP</a>. (Keep the backslashes before each dot!)</p>
<p>Those two <code>RewriteCond</code> (&#8220;rewrite condition&#8221;) lines basically mean: <em>only apply the following rewrite if the IP of the request (REMOTE_ADDR) doesn&#8217;t match the one given, and the file requested (REQUEST_URI) isn&#8217;t <code>503.php</code> (preventing an infinite loop!)</em>. As long as it&#8217;s not you and they&#8217;re not already going to <code>503.php</code>, the <code>RewriteRule</code> kicks in and serves that page up. (Though note that the URL in the browser address bar doesn&#8217;t change for the user; this is rewriting, not redirecting.)</p>
<p>Note that last <code>[L]</code> in the code. That means, if this rewrite rule is processed, make it the last one. This is handy if you have other rewrites (e.g. your WordPress rewrites) that still need to work when you access the site, but which shouldn&#8217;t intefere with this rule for everyone else. Of course, for this reason, the above code should go right at the top of your file.</p>
<h2>The switch</h2>
<p>You may have your own technique. I keep <code>503.php</code> and <code>503.htaccess</code> in the web root. When I need to switch my holding page in, I just rename my usual <code>.htaccess</code> to something like <code>LIVE.htaccess</code>, and (quickly!) rename <code>503.htaccess</code> to <code>.htaccess</code>.</p>
<p>All should now be on hold for the rest of the world. Bots should be politely leaving your site be for the while. And you should be able to get in and muck around to your heart&#8217;s content.</p>
<h3>Looking through other&#8217;s eyes</h3>
<p>A pesky stumbling block I came up against developing this technique was my obvious inability to see what other people were seeing via all those other IP addresses. My friend <a href="http://numero57.net/">Jim</a>, ever abreast of tech developments, directed me to the <a href="http://www.torrify.com/software_torpark.html">Torpark</a> browser. Built on the Firefox shell, this browser is designed to anonymize your web surfing by routing your requests through a labyrinthine series of IP relays (or whatever they might call them).</p>
<p>It&#8217;s sluggish, but it works. Whatever your IP ends up being seen as by servers while browsing with this nifty tool, it won&#8217;t be your actual IP.</p>
<h2>Upgrading WordPress</h2>
<p>So, with these tricks ready to go, here&#8217;s my revised WordPress upgrade guide. (Do also check <a href="http://codex.wordpress.org/Upgrading_WordPress">the official guide</a> if you&#8217;re new to this though!)</p>
<p>One thing to bear in mind with more recent WordPress versions is that if the <code>.htaccess</code> file doesn&#8217;t contain WordPress&#8217; rewrite rules at the end, it may try to &#8220;fix&#8221; things &#8211; and break them. Make sure your 503 <code>.htaccess</code> file has your usual WordPress rewrite rules <em>at the end</em>.</p>
<ol>
<li>Backup all your files and your database.</li>
<li>Make sure you&#8217;ve a record of which files you&#8217;ve customized.</li>
<li>Do the 503 holding page switch.</li>
<li>De-activate all your plugins.</li>
<li>Delete all files apart from <code>wp-config.php</code>, the <code>wp-content</code> directory, and of course <code>.htaccess</code> and <code>503.php</code></li>
<li>Upload all files in the new version of WordPress (excluding the <code>wp-content</code> directory)</li>
<li>Run the upgrade script (e.g. <code>http://yourdomain.com/wp-admin/upgrade.php</code>)</li>
<li>Re-activate the plugins. Pray.</li>
<li>Check the site out, make sure it&#8217;s survived OK.</li>
<li>Revert to the original <code>.htaccess</code> file.</li>
<li>Done!</li>
</ol>
<h2 class="update">Update</h2>
<p>I&#8217;ve just tried implementing this technique to display a holding page for a site that&#8217;s yet to be launched. Pretty much the same situation, but an interesting issue came up when I tried to include an image on the holding page. The image wouldn&#8217;t appear. I spent a frustrating 5 minutes checking paths and files, but eventually it dawned on me: the browser&#8217;s request for the image file was returning a 503 error, not the image!</p>
<p>A little extra <code>.htaccess</code> magic remedies this. Insert the following line before your <code>RewriteRule</code> line:</p>
<pre name="code" class="php">RewriteCond %{REQUEST_FILENAME} !\.(gif|jpe?g|png)$</pre>
<p>Of course you may need to add <code>css</code> or <code>js</code> to that list of filetypes, depending on your holding page&#8217;s needs.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/503-holding-page/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress 2.1 and .htaccess files</title>
		<link>http://sltaylor.co.uk/blog/wordpress-21-and-htaccess-files/</link>
		<comments>http://sltaylor.co.uk/blog/wordpress-21-and-htaccess-files/#comments</comments>
		<pubDate>Wed, 07 Feb 2007 19:49:50 +0000</pubDate>
		<dc:creator>Steve Taylor</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://sltaylor.co.uk/blog/2007/02/wordpress-21-and-htaccess-files/</guid>
		<description><![CDATA[I&#8217;m building this site with WordPress 2.1, which has some great new features (such as post auto-saving and draft pages). I&#8217;ve heard there are significant teething problems with upgrading from a previous version &#8211; for instance, the new draft pages system means that pages are now flagged with the database field post_type being used instead [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m building this site with <a href="http://wordpress.org/development/2007/01/ella-21/">WordPress 2.1</a>, which has some great new features (such as post auto-saving and draft pages). I&#8217;ve heard there are significant teething problems with <em>upgrading</em> from a previous version &#8211; for instance, the new draft pages system means that pages are now flagged with the database field <code>post_type</code> being used instead of the <code>post_status</code> field being set to <code>static</code>. Much more logical, but it may break some of your page-related plugins.</p>
<p>Anyway, for new installs it seems like the way to go, with a few caveats. One involves the potent but potentially tricksy <code>.htaccess</code> file for Apache server configuration settings. If, like me, you prefer to maintain control over the file yourself instead of having WordPress automatically generate it, you might run into problems when 2.1 tries to &#8220;fix&#8221; it.</p>
<p>If you suddenly get a HTTP 500 error (Internal Server Error), it&#8217;s often due to slip-ups in <code>.htaccess</code>. If you&#8217;re using WordPress 2.1 and get this, download <code>.htaccess</code> and see if WP hasn&#8217;t slipped its mod_rewrite rules in at the end. If you&#8217;ve adapted the default mod_rewrite code, WP 2.1 thinks it&#8217;s not there at all, and slips the default in at the end again.</p>
<p>I&#8217;ve not found a way to stop WP doing this &#8211; there was a suggestion to change the write permissions on the file to stop WP accessing it, but you&#8217;d have to switch them back every time you re-uploaded the file. Pain in the arse. I&#8217;ve just reverted to keeping the default WP mod_rewrite at the end of the file, exactly as WP intends.</p>
]]></content:encoded>
			<wfw:commentRss>http://sltaylor.co.uk/blog/wordpress-21-and-htaccess-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
