Drupla, Mod Rewrite, Subdirectories, and NGINX
==============================================
:author: Aaron Ball
:email: nullspoon@iohq.net
A few days ago I started dabbling with nginx (many thanks for the
http://arstechnica.com/business/news/2011/11/a-faster-web-server-ripping-out-apache-for-nginx.ars[article]
from http://arstechnica.com/[arstechnica]) knowing I was getting myself into a
world without htaccess files. They say that Nginx is easier to configure than
Apache, but oh contraire! If you're doing a simple setup, yes, Nginx is much
easier than Apache. If you're even doing a slightly more complicated virtual
host setup, Nginx is definitely much easier. However, if you do much with
mod_rewrite in Apache, you'll likely find yourself confused a bit with all
kinds of 404s on your subdirectories. Believe it or not though, with Nginx it
is actually easier to configure URI rewriting as well, provided you know what
you're doing...which I do not.
My current setup has Drupal at the root directory, and various other tidbits
hosted in subdirectories. These aren't anything fancy like subdomains, just
directories beneath /.
Pretty much any CMS/blog these days uses the .htaccess file to perform URI
rewrites for search engine friendly URIs, which causes some complications for
Nginx since you have one config file to set up all of that for your entire
domain, rather than a config file per directory (if you wish) defining rewrite
rules for each one. To get my Drupal instance back up and running, I took the
location directive from the http://drupal.org/node/110224[Drupal Support page]
for this issue. Specifically I used the following lines...
----
location / {
root /path/to/drupal;
index index.php index.html;
if (!-f $request_filename) {
rewrite ^(.*)$ /index.php?q=$1 last;
break;
}
if (!-d $request_filename) {
rewrite ^(.*)$ /index.php?q=$1 last;
break;
}
}
----
The problem with using that configuration is that any time you try to hit a
legitimate sub directory, you receive a 404. The reason for this is because the
request_filename will end up going to
http://yoursite.com/index.php?q=request_filename. An example
of this would be... Say you go to your site at the following URI:
http://blerdibler.com/chips. The previous configuration would
send the request to http://blerdibler.com/index.php?q=chips,
which of course doesn't exist, so we receive a 404. The fix for this is
relatively simple, which is very unfortunate because I spent a long time
finding this face-palmingly simple solution (mostly because once again, I do
not know what I'm doing).
The fix is to move the Drupal rewrite stuff to its own named location
directive (I'll show what that looks like in a few), and reference that for the
last case scenario. So, here's what my location directives look like that allow
for me to hit up my sub directories as well as my rewritten Drupal pages.
----
location / {
index index.html index.htm index.php;
try_files $uri $uri/ @drupal;
}
location @drupal {
rewrite ^(.*)$ /index.php?q=$1 last;
break;
}
----
So what we're doing here is trying all requests at face value. This means that
Nginx tries to load http://blerdibler.com/anchovies when
http://blerdibler.com/anchovies (a file called anchovies, not the directory) is
called.
If it can't load that, it tries http://blerdibler.com/anchovies/ (the directory
called anchovies...consequently it searches for index.html/htm/php).
Finally, if neither of those work, it calls the location directive called
drupal (@drupal) which sends the request to
http://blerdibler.com/index.php?q=anchovies. If that doesn't work, you're hosed
and hopefully you've got an attractive 404 page set up. Incidentally, this also
works for all nested Drupal/Wordpress instances as well (say, a drupal instance
located at http://blerdibler.com/drupal2.
Hopefully that helped someone out because I can't write anymore on this topic
as I am now out of coffee. Sorry. If however, you have questions/comments/etc.,
please leave them in the comments section and I will go brew up another cup o'
joe and help you out (if I can...yet again...I still don't know what I'm
doing).
Thanks for reading!
Category:nginx
Category:Apache
Category:Drupal
// vim: set syntax=asciidoc: