Drupal+nginx: this works => using try_files

The following has been tested in Nginx 0.7.42 + Drupal 6.10 + Ubuntu
8.10.

M.

The tests included calls to:

http://clinica.0/index.php # ok

http://clinica.0 # ok

http://www.clinica.0 # ok

http://clinica.0/user/password # ok

http://clinica.0/test # Page not found

http://nonexistant.clinica.0/ # Address Not Found

http://clear.clinica.0/ # redirect to [clear.]clinica.0

http://clinica.0/scripts/drupal.sh # 403 Forbidden

http://clinica.0/scripts/code-style.pl # 403 Forbidden

http://clinica.0/sites/default/settings.php # 403 Forbidden

http://clinica.0/sites/all/README.txt # show README.txt

http://clinica.0/sites/default/files/README.txt # show (*1)

http://clinica.0/nice ports,/Trinity.txt.bak # Page not found

http://www.clinica.0/benchtest.php # show a timed phpinfo (*2)

http://www.clinica.0/somefile.php # No input file specified.

http://127.0.0.1/ # redirect to clinica.0

#(*1) this README.txt is a copy made from sites/all/README.txt
#(*2) see at the end of this email how benchtest.php was created

The file bellow does not fully take care of:
^/system/test/(.)$ => /index.php?q=system/test/$1,
^/([^.?]
)?(.)$ => /index.php?q=$1&$2,
^/([^.?]
)$ => /index.php?q=$1
^/search/node/(.*)$" => /index.php?q=search/node/$1

drupal-cgm file follows:

— cut here —

nginx - /etc/nginx/sites-available/drupal-cgm

server {
listen 80 default;
server_name _; # non defined server
return 444; # silently drop request
}
server {
listen clinica.0:80;
server_name www.clinica.0;
rewrite ^(.*) http://clinica.0$1 permanent;
}
server {
listen clinica.0:80;
server_name clinica.0;

access_log /var/log/nginx/drupal-cgm.access.log;
error_log /var/log/nginx/drupal-cgm.error.log;

root /var/www/drupal-cgm;

restrict request methods to: GET|HEAD|POST

if ( $request_method !~ ^(GET|HEAD|POST)$ ) {
return 444;
break;
}

hide drupal system files

location ~*
((cron.php|settings.php)|.(htaccess|engine|inc|info|install|module|profile|pl|po|sh|.sql|theme|tpl(.php)?|xtmpl)$|^(Entries.|Repository|Root|Tag|Template))$
{
deny all;
}

# rewrite domain name without the leading www.

if ($host ~* ^www.(.*)) {

set $host_without_www $1;

# bellow $1 contains ‘/foo’, not ‘www.mydomain.com/foo

rewrite ^(.*)$ http://$host_without_www$1 permanent;

}

location / {
index index.php index.html;
try_files $uri $uri/ @drupal;
}

location @drupal {
# clean url rewrite for Drupal
rewrite ^/(.)$ /index.php?q=$1 last;
#rewrite ^/(\w
)/(.*)$ /$1/index.php?q=$2 last;
}

location ~ .php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/tmp/php-fastcgi.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}

— cut here —

benchtest.php file follows:

— cut here —

sudo tee /var/www/drupal-cgm/benchtest.php <<-\EOA

<?php // /var/www/drupal-cgm/benchtest.php $start = microtime(true); ob_start(); //Turn on output buffering phpinfo(); $info = ob_get_clean(); echo "phpinfo() run time: "; printf("%0.1f ms\n", (microtime(true)-$start)*1000); echo $info; ob_end_flush(); ?>

EOA

— cut here —

2009/3/17 Mark A. [email protected]:

The following has been tested in Nginx  0.7.42 + Drupal 6.10 + Ubuntu 8.10.

M.

Seems to me that

a) drupal should not include scripts/etc. that should not be ran via
the web -in- the webroot, or
b) they should be localized to only one directory

   # hide drupal system files
   location ~*

((cron.php|settings.php)|.(htaccess|engine|inc|info|install|module|profile|pl|po|sh|.sql|theme|tpl(.php)?|xtmpl)$|^(Entries.|Repository|Root|Tag|Template))$
{
deny all;
}

That is ugly as sin to me, and could change at any given time. Is
there a true need to protect all of these? Is it only a specific
folder?You could always use location /folder { internal; } then too.

you can add these to fastcgi_params, no need for repetition:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;

I’m just trying to approach this from a purely KISS perspective. I
hate seeing denormalized/excessive configs. Especially since I host a
drupal instance I want the cleanest possible :wink:

and actually, since drupal has nothing really specific besides a
single line, you could get away with:

try_files $uri $uri/ /index.php?q=$request_uri; ($uri might
work too - might warrant testing the two, I’m trying to find the
difference between the two on the wiki)

I also have an open question to the list about using try_files with
multiple prefixes… i.e.:

location /drupal {
try_files $uri $uri/ /drupal/index.php?q=$request_uri
}

wordpress, for example

location /blog {
try_files $uri $uri/ /blog/index.php?q=$request_uri
}

I don’t really like the current wiki examples either. It’s got a mix
of parsing php and try_files and other wacky stuff that will just lead
to confusion.

On Tue, Mar 17, 2009 at 10:15 AM, mike [email protected] wrote:

try_files $uri $uri/ /index.php?q=$request_uri; Â Â Â Â Â Â ($uri might
work too - might warrant testing the two, I’m trying to find the
difference between the two on the wiki)

found it.

http://wiki.nginx.org/NginxHttpCoreModule

$document_uri
The same as $uri.

$uri
This variable is equal to current URI in the request, it can differ
from initial, for example by internal redirects, or with the use of
index it is file with internal redirects.

So it is the same. Could just keep it $uri then for simplicity. $uri
$uri/ /index.php?q=$uri

mike wrote:

a) drupal should not include scripts/etc. that should not be ran via
the web -in- the webroot, or
b) they should be localized to only one directory

Those were/are options of the Drupal Development Team.

((cron.php|settings.php)|.(htaccess|engine|inc|info|install|module|profile|pl|po|sh|.sql|theme|tpl(.php)?|xtmpl)$|^(Entries.|Repository|Root|Tag|Template))$
That is ugly as sin to me, and could change at any given time. Is
there a true need to protect all of these?

Yes

Is it only a specific folder?

No.

You could always use location /folder { internal; } then too.

That is an interesting idea, but the level of complexity would be quite
the same.

you can add these to fastcgi_params, no need for repetition:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;

In what way would that contribute to reduce complexity, or better
document the procedure?

and actually, since drupal has nothing really specific besides a
single line,

On the contrary, it has.

you could get away with:
try_files $uri $uri/ /index.php?q=$request_uri;

That does not work. You could at least have tried it…

I don’t really like the current wiki examples either. It’s got a mix
of parsing php and try_files and other wacky stuff that will just lead
to confusion.

I am sure that you will provide a couple of cleaner examples to help us
all.

M.

On Tue, Mar 17, 2009 at 12:57 PM, Mark A. [email protected]
wrote:

mike wrote:

a) drupal should not include scripts/etc. that should not be ran via
the web -in- the webroot, or
b) they should be localized to only one directory

Those were/are options of the Drupal Development Team.

I’ve got a bone to pick …

That is an interesting idea, but the level of complexity would be quite the
same.

Ideally it would be

location /drupal {
try_files $uri $uri/ /drupal/index.php?q=$uri;
}

location /drupal/protected {
internal;
}

pretty simple (ideally)

In what way would that contribute to reduce complexity, or better document
the procedure?

Both. Why have duplication in configuration files (especially common
things such as that) if unnecessary?

On the contrary, it has.

location @drupal just has the rewrite to /index.php?q=$uri

This was what I meant. The other “block these scripts” stuff… I
would like to pick a bone with the drupal folks for not localizing
those into at least a single directory.

you could get away with:
try_files $uri $uri/ /index.php?q=$request_uri;

That does not work. You could at least have tried it…

I swear Igor said it should work.

I am sure that you will provide a couple of cleaner examples to help us all.

This sounds kind of sarcastic; but yes, I would like to. A lot of
people’s nginx configurations they post when they have questions are
littered with extra stuff which just leads to confusion or
confliction.