Centos – .htaccess ignored, SPECIFIC to EC2 – not the usual suspects

.htaccessamazon ec2apache-2.2centosmod-rewrite

I run 8-10 EC2 based web servers, so my experience is many hours, but is limited to CentOS; specifically Amazon's distribution. I'm installing Apache using yum, so therefore getting Amazon's default compilation of Apache.

I want to implement canonical redirects from non-www (bare/root) domain to www.domain.com for SEO using mod_rewrite BUT MY .htaccess FILE IS CONSISTENTLY IGNORED.

My troubleshooting steps (outlined below) lead me to believe it's something specific to Amazon's build of Apache.

TEST CASE

  1. Launch a EC2 Instance, e.g. Amazon Linux AMI 2013.03.1
  2. SSH to the Server
  3. Run the commands:

    • $ sudo yum install httpd
    • $ sudo apachectl start
    • $ sudo vi /etc/httpd/conf/httpd.conf
    • $ sudo apachectl restart
    • $ sudo vi /var/www/html/.htaccess

In httpd.conf I changed the following, in the DOCROOT section / scope:

AllowOverride All

In .htaccess, added:

(EDIT, I added RewriteEngine On later)

RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^/(.*) http://www.domain.com/$1 [R=301,L]

Permissions on .htaccess are correct, AFAI can tell:

$ ls -al /var/www/html/.htaccess -rwxrwxr-x 1 git apache 142 Jun 18 22:58 /var/www/html/.htaccess

Other info:

$ httpd -v
Server version: Apache/2.2.24 (Unix)
Server built:   May 20 2013 21:12:45

$ httpd -M
Loaded Modules:
 core_module (static)
     ...
 rewrite_module (shared)
     ...
 version_module (shared)
Syntax OK

EXPECTED BEHAVIOR

$ curl -I domain.com
HTTP/1.1 301 Moved Permanently
Date: Wed, 19 Jun 2013 12:36:22 GMT
Server: Apache/2.2.24 (Amazon)
Location: http://www.domain.com/
Connection: close
Content-Type: text/html; charset=UTF-8

ACTUAL BEHAVIOR

$ curl -I domain.com
HTTP/1.1 200 OK
Date: Wed, 19 Jun 2013 12:34:10 GMT
Server: Apache/2.2.24 (Amazon)
Connection: close
Content-Type: text/html; charset=UTF-8

TROUBLESHOOTING STEPS

In .htaccess, added:

BLAH BLAH BLAH ERROR
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^/(.*) http://www.domain.com/$1 [R=301,L]

My server threw an error 500, so I knew the .htaccess file was processed.

As expected, it created an Error log entry:
[Wed Jun 19 02:24:19 2013] [alert] [client XXX.XXX.XXX.XXX] /var/www/html/.htaccess: Invalid command 'BLAH BLAH BLAH ERROR', perhaps misspelled or defined by a module not included in the server configuration


Since I have root access on the server, I then tried moving my rewrite rule directly to the httpd.conf file. THIS WORKED. This tells us several important things are working.

$ curl -I domain.com
HTTP/1.1 301 Moved Permanently
Date: Wed, 19 Jun 2013 12:36:22 GMT
Server: Apache/2.2.24 (Amazon)
Location: http://www.domain.com/
Connection: close
Content-Type: text/html; charset=UTF-8

HOWEVER, it is bothering me that it didn't work in the .htaccess file. And I have other use cases where I need it to work in .htaccess (e.g. an EC2 instance with named virtual hosts).

Thank you in advance for your help.

Best Answer

You can put RewriteRules in the server config, or in .htaccess. There are however differences that mean that a rule that works in a server config will not necessarily work in .htaccess context or vice versa. RewriteRules in .htaccess files (and directory context) are matched against relative URLs, so your rule starting with / is never matched. Enable rewritelog and you'll see.

So for asume docroot is /var/www and you request http://myserver.com/foo/bar.html

A rewrite rule in your server config will be matched against /foo/bar.html

A rewrite rul in a context, or in a .htaccess file in /var/www/foo will be matched against just bar.html. So if it starts with a / it will not match ever.

It is important to be aware of this, and one of the reasons I generally consider rewriterules in .htaccess files a bad idea. I usually advise strongly against having rewriterules in .htaccess files if you can avoid it (and you have access to httpd.conf so you can). RewriteRules in .htaccess files often lead to hard to diagnose behavior, and are a huge performance hit.

See also the apache documentation: http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule

"In Directory and htaccess context, the Pattern will initially be matched against the filesystem path, after removing the prefix that led the server to the current RewriteRule (e.g. "app1/index.html" or "index.html" depending on where the directives are defined)."