The Right Way to Optimize Apache’s .htaccess Files
While researching Magento performance optimizations you have probably already read about how to optimize Apache’s configuration by moving your configuration directives into the configuration files and out of the .htaccess files. Of course you need root to do this, but assuming you can, there are still very very wrong ways to do this that will result in no real performance gains, leave gaping security holes, and consume more time than necessary. Read on, a handy script for solving these problems and before and after performance benchmarks to prove the gains are included.
If you move your .htaccess contents into the apache config files that is great, but if you forget to disable .htaccess files using
AllowOverride None then you’ve entirely defeated the purpose! The reason this technique can result in performance gains is that it allows the server to ignore the .htaccess files which means fewer directory traversals and fewer file reads with each request. One page load probably results in 20-100 HTTP requests to your Apache server. If you have deeply nested files (all of those cached product images and skin images come to mind) then this results in a lot of disk access. So, you must disable the .htaccess files completely with
AllowOverride None! Which brings me to the second major mistake that people can make…
Now that you’ve disabled .htaccess, guess what? Those .htaccess files had a purpose.. For example, to deny access to your
app/etc/local.xml config file!! Great way to expose your database password, let’s just hope the user is a localhost-only user and you don’t re-use passwords… Also, in
downloader/.htaccess for example, compression is disabled so that the Magento Connect console can circumvent Apache’s buffering to display the console output as it occurs. There are others as well. Point is, now you have to move all of these .htaccess files into your apache config. Ugh.. Which brings me to my last point…
It doesn’t have to be difficult! I’ve written a bash script (buildhtaccess.sh, see below) which provides you an easy way to benefit from this tweak. In essence the following script will find all of your .htaccess files and compile them into one file which can then be included in your Apache config with only a few lines. If you modify an .htaccess file or a new one is installed by an extension, re-run the script and reload the apache config.
First, download and run the script to generate your .htaccess-combined file.
$ cd <webroot> $ wget http://gist.github.com/raw/459311/buildhtaccess.sh $ bash buildhtaccess.sh
Next, edit your apache config file. Find the
<VirtualHost> directive and at the end of it add the following:
# Include combined Magento .htaccess files <Directory /your_webroot_here> AllowOverride None </Directory> Include /your_webroot_here/.htaccess-combined
Lastly, run a graceful reload of the Apache config. A full restart is not necessary. Now you’re done.
And here is the code for generating the .htaccess-combined file:
For my benchmark I ran “ab” (apache bench) since it is quick and easy but admittedly not the best for benchmarking overall site performance. In this case apache bench is going to under state the value of this tweak since one page load in a browser will result in repeated hits on the webserver, all of which will be affected by this optimization. So, I benchmarked on /errors/503.php so that the database is not factored but PHP code is still run. Specifically, I used
$ ab -n 1000 -c 20 .../errors/503.php.
Before: ~3000 requests per second (3018 max)
After: ~4600 requests per second (5030 max)
That’s a pretty nice improvement. Unfortunately it is only substantial with fast requests such as the error pages and static files but it should definitely reduce disk contention on a busy server and increase scalability, but probably not do a whole lot for user-experience on a low-contention server.