Drupal, Mod rewrite, Subdirectories, and Nginx

A few days ago I started dabbling with nginx (many thanks for the article from 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 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!