Moving WP .htaccess rules to httpd.conf

Apache HTTP Server LogoRecently, in one of my clients’ server, we decided to move to the traditional Apache with mod_php instead of Nginx with php-fpm, after going through the pros and cons of each setup. If you are not aware already that AllowOverride All brings a major performance lag into the whole setup. To overcome this, we can move the rewrite rules written on any part of your site into Apache’s configuration file (apache.conf or httpd.conf or any other name depending on the distribution you use). By moving the rewrite rules into the httpd.conf, we could disable AllowOverride altogether for a particular site and make this Apache with mod_php server stack a bit faster than Nginx with php-fpm stack. Here is how you can move all the rewrite rules into your server’s config…

Combining Apache VirtulHost and WordPress Permalink Rewrite Rules

Here is the traditional virtual host configuration in Apache…


    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/dummy-host.example.com
    ServerName dummy-host.example.com
    ErrorLog logs/dummy-host.example.com-error_log
    CustomLog logs/dummy-host.example.com-access_log common

And here is the traditional rewrite rules for pretty permalinks


# BEGIN WordPress

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

So, let’s combine this…


    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/dummy-host.example.com
    ServerName dummy-host.example.com
    ErrorLog logs/dummy-host.example.com-error_log
    CustomLog logs/dummy-host.example.com-access_log common

    # BEGIN WordPress

    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]

    # END WordPress

Finally, lets test the configuration and reload the Apache server…

httpd -t && service httpd reload
> Syntax error on line 1037 of /etc/httpd/conf/httpd.conf:
> RewriteBase: only valid in per-directory config files

Oops. :) It turns out that we have to use “Directory” to insert the rewrite rules. So, here is the modified version…


    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/dummy-host.example.com
    ServerName dummy-host.example.com
    ErrorLog logs/dummy-host.example.com-error_log
    CustomLog logs/dummy-host.example.com-access_log common

    <Directory "/www/docs/dummy-host.example.com">
        # BEGIN WordPress

        RewriteEngine On
        RewriteBase /
        RewriteRule ^index\.php$ - [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.php [L]

        # END WordPress
    </Directory>

Let’s see, if we could succeed this time…

httpd -t && service httpd reload
> Syntax OK
> Reloading httpd: [OK]

That’s it. Now, you can be proud to say that your Apache server with mod_php is faster than Nginx with php-fpm.

Let’s do more: Akismet .htaccess code in httpd.conf

Since version 2.5.7, Akismet introduced a new .htaccess file to block direct access to files. Let’s dive in and see what’s in it…


Order Deny,Allow
Deny from all

<FilesMatch "^akismet\.(css|js)$">
    Allow from all
</FilesMatch>

Pretty simple? Yeh. Let’s put it in Apache config file…


    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/dummy-host.example.com
    ServerName dummy-host.example.com
    ErrorLog logs/dummy-host.example.com-error_log
    CustomLog logs/dummy-host.example.com-access_log common

    <Directory "/www/docs/dummy-host.example.com">
        # BEGIN WordPress

        RewriteEngine On
        RewriteBase /
        RewriteRule ^index\.php$ - [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.php [L]

        # END WordPress
    </Directory>

    <Directory "/www/docs/dummy-host.example.com/wp-content/plugins/akismet">
        Order Deny,Allow
        Deny from all

        <FilesMatch "^akismet\.(css|js)$">
            Allow from all
        </FilesMatch>
    </Directory>

Final Stack

We deployed Nginx to serve the static files and Varnish to cache the dynamic content. We were still not satisfied with the performance of our server. Upon troubleshooting, we noticed that we had forgotten to remove AllowOverride All. :)

15 Replies to “Moving WP .htaccess rules to httpd.conf”

    1. Good question and a nice tip! By not parsing htaccess files, there is a slight increase in security as well. Even if a hacker can modify the htaccess file, that wouldn’t be parsed by Apache, while using the method mentioned in the post.

    2. +1. You sir, are a gentleman and a scholar. If this was reddit, I’d give you gold.

      That means the ‘apache’ user will need to have read access (to the file/s being included) that is, kind of, unnecessary, due to security reasons.

      Yea, let’s not give ‘apache’ read access to the folder it was configured to serve. This made my week.

      1. Hi James,

        That made my day as well. :) Realized it only when you quoted it. Updated my other reply now for better clarify.

        Thanks for pointing it out.

        Pothi

  1. Just a small remark: I see you use the directory “/www/docs/dummy-host.example.com/wp-content/akismet” for protection of Akismet files, but this should be “/www/docs/dummy-host.example.com/wp-content/plugins/akismet” (so in the plugins subdirectory of wp-content, not directly under it).

  2. This solved my LONG TIME problem of getting apache re-write to work! Thank you!!! Here was my final solution that your comments inspired (in case anyone is interested).

    ServerAdmin webmaster@aeonscience.com
    DocumentRoot /var/www/html
    ServerName www.aeonscience.com
    ErrorLog logs/error_log
    CustomLog logs/_log common
        
    # BEGIN WordPress
    RewriteEngine On
    RewriteBase /imaging/
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /imaging/index.php [L]
    # END WordPress
       
    # Begin OpenCart ecommerce plateform
    RewriteEngine On
    RewriteBase /cart/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]
    
  3. While there’d be no difference in terms of performance, here’s why (I think) it’s even better to add all your .htaccess rules in /etc/apache2/sites-available/example.com instead of httpd.conf:

    Apache’s main configuration file is apache2.conf (located in ‘/etc/apache2’ directory). On Ubuntu this file has a directive like Include httpd.conf, so you can simply add all your rules in ‘/etc/apache2/httpd.conf’ and it’ll work.

    But that isn’t the case on Debian (even in Wheezy). For your httpd.conf rules to work, you’d first have to add the line Include httpd.conf in ‘/etc/apache2/apache2.conf’.

    I am saying this ’cause I had a hard time figuring out why the same rules placed in httpd.conf were working on Ubuntu Server, but not on Debian!

    But… there’s always a Include sites-enabled/ directive in apache2.conf. So, you can safely call ‘/etc/apache2/sites-available/example.com’ home for your site’s Virtual Host configuration as well as all the .htaccess rules (because they’ll all take effect when you do a2ensite example.com).

    That’s something I learnt today. (Any thoughts against it are welcome!)

    1. I have no thoughts on your point (because I never followed the standard directory / file name schemes; I always compile from source). However, it is interested to see your analysis on this situation.

      Thanks for the comment and sharing your thoughts.

      Pothi

  4. Great solution! Thanks for share this with the word, but when i implement this on my server the CPU reaches 100%.

    Sorry for my bad english., but, do you know what problem is this?

  5. Hi Pothi,

    thanks for your inspiration. I have two things to add that took me hours for finding the misconfiguration (or it is a bug in Apache 2.2.22).

    This line did not work in my configuration, it caused a http 302 redirect.
    RewriteRule . /index.php [L]

    I had to enter the complete path to fix it
    RewriteRule . /www/docs/dummy-host.example.co/index.php [L]

    And I noticed that a RewriteEngine On in a .htaccess file did result in a 404 error. So first delete the .htaccess or comment rewriting stuff out.

    Hope this helps others who are having the same problem.

    Christian

Leave a Reply

Your email address will not be published. Required fields are marked *