So I recently moved to a VPS and now I'm running nginx to fit into my 256MB of RAM. I activated Boost yesterday, but it's not generating any cache files. The directory is set up correctly and is writable, and I'm not getting any errors in the log. Can the reason be that Boost sees only the query string with the ? and therefore ignores the request (not sure if Apache does this differently than nginx)? Does anybody have experience setting up Boost on nginx, or some way to find out if Boost is doing anything at all (and if not, why not)?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

eagereyes’s picture

*bump* Is nobody running Boost on nginx?

jensen0’s picture

Hi there,

There're several things you should take care of, as following:

1. cache fold should within your drupal folder;
2. Your PHP container should be mod-php for apache to take the advantages from Boost as it was writen focus on Apache;
3. You need to modify your .htaccess file with your drupal folder following the instruction stating in the README from Boost module.

For FastCGI with Lighttpd or Nginx, you need do some homemade scripting thing to make it working with Boost. It is quite simple though.

Go do some programming on Lighttpd or Nginx is fun.

wobbler’s picture

This request was a while ago so this may only be helpful to someone in the future.

I have boost running with nginx serving the static files, and apache doing the php. I tried briefly to get nginx doing everything using fastcgi, but couldn't get fast-cgi processes talking with nginx through unix sockets or tcpip. Didn't spend long on it though. btw You need to compile nginx with -- with-debug to make the debug infomation to be able to see the rewrite tests being processed in the log.

If it helps here is the setup I use for nginx to proxypass php requests to apache running on port 88. The virtual host on apache will only ever get php requests from this, as opposed to request for static files like the js and css files.
Comparative tests using ab with nginx serving static files showed it handled about twice as many requests per sec than apache

    server {
        listen       80;
        server_name  www.example.com _;
        root /usr/share/drupal-6.3;
        index index.php;
        access_log off;

        location ~ \.php$ {
            access_log logs/access.log;
            proxy_pass http://www.example.com:88;
        }

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

        location ~ \.\w\w\w?\w?$ {
            expires      epoch;
        }

        location / {
            if ( $http_cookie ~ "DRUPAL_UID" ) {
                rewrite ^/(.+)$ /index.php?q=$1 last;
            }
            if ( $query_string != "" ) {
                rewrite ^/(.+)$ /index.php?q=$1 last;
            }
            if ( $request_method != GET ) {
                rewrite ^/(.+)$ /index.php?q=$1 last;
            }
            if ( -f $document_root/cache/$host/0$request_uri.html ) {
                rewrite .? /cache/$server_name/0$request_uri.html break;
            }
            if ( -f $document_root/cache/$host/0/index.html ) {
                rewrite ^/$ /cache/$server_name/0/index.html break;
            }
            if ( -f $document_root/cache/$host/0$request_uri/index.html ) {
                rewrite .? /cache/$server_name/0$request_uri/index.html break;
            }
            if ( !-e $request_filename ) {
                rewrite ^/(.+)$ /index.php?q=$1 last;
            }
        }
    }
eagereyes’s picture

Since there is no 6.x version, I have basically given up on this and am simply running my site with aggressive caching. The VPS and the entire setup has been rock-solid for months now, so I'm confident this will keep working. If load becomes an issue, I'll probably try squid.

Arto’s picture

Title: Boost and nginx - how do I set it up correctly? » Nginx integration
Component: Miscellaneous » Nginx integration
zvikico’s picture

+1 For supporting Drupal 6 with Nginx.

dmuntean’s picture

The rules above are not working, they break everything when user logs in.

Here are the rules I developed to make boost work with Drupal 5, but I am pretty sure, they will work with version 6 too.

Following lines should be inserted under "location /". Remember that order is important here, last rule is default drupal rule for nginx.

        ## Boost rewrite rules
        set  $boost "";

        if ( $request_method = GET ) {
            set $boost G;
            }
        if ($http_cookie !~ "DRUPAL_UID") {
            set $boost "${boost}D";
            }
        if ($query_string = "") {
            set $boost "${boost}Q";
            }

        if ( -f $document_root/cache/$host/0/index.html ) {
            set $boost  "${boost}I";
            }

        ## GDQI, request is for main page
        if ($boost = GDQI) {
            rewrite ^/$ /cache/$server_name/0/index.html break;
            }

        if ( -f $document_root/cache/$host/0$request_uri.html ) {
            set $boost "${boost}F";
            }

        ## GDQIF, the request is for subpage
        if ($boost = GDQIF) {
            rewrite .? /cache/$server_name/0$request_uri.html break;
            }

        if ( -d $document_root/cache/$host/0$request_uri ) {
            set $boost "${boost}E";
            }
        if ( -f $document_root/cache/$host/0$request_uri/index.html ) {
            set $boost "${boost}F";
            }
        ## GDQEF, the request is for module main page
        if ($boost = GDQEF) {
           rewrite .? /cache/$server_name/0$request_uri/index.html break;
           }
        ## Boost rewrite rules end

        if (!-e $request_filename) {
            rewrite  ^/(.*)$  /index.php?q=$1 last;
            }

This is a crosspost from my blog (http://mechanix-tips.blogspot.com/2009/02/drupal-boost-rules-for-nginx.html)

dicreat’s picture

dmuntean, thanks for this rules!

I'm using Drupal-5 with clean urls (generated with Pathauto) + Global Redirect module (to prevent duplicate pages). In my case, last rule don't work and I've been change:

        if (!-e $request_filename) {
            rewrite  ^/(.*)$  /index.php?q=$1 last;
            }

to this:

        if (!-e $request_filename) {
            rewrite  ^/(.*)$  /$1 last;
            }

Second problem - nginx try looking cached pages in selft home directory, not in site home directory. I've been added:
root /path/to/site/home/directory;
in nginx config for my site above your rules and now it's work great.

Thanks!

P.S. Tell me please, do you cut Boost rewrite rules from .htaccess?

dmuntean’s picture

dicreat, having a root directory defined in "location /" is assumed.

Yes, the rules were transformed from Boost .htaccess file, taking in consideration that nginx can not handle multiple "if" statements (like, if a = b & c =d)

dicreat’s picture

Does anybody have worked configuration Nginx+FastCGI+Boost module?

jensen0, do You have any solution (maybe own homemade scripts) for FastCGI, as You talking above?

Thanks for any help.

dmuntean’s picture

dicreat, there is no need for any home-made scripts to run php (or any other language interpreter) in FastCGI mode with nginx. Boost rules are independent from this.

Grab spawn-fcgi daemon from here http://redmine.lighttpd.net/projects/spawn-fcgi , start it as follows:

 /opt/spawn-fcgi/bin/spawn-fcgi -s /tmp/fcgi.sock -C 15 -u nobody -g nobody -f /usr/bin/php-cgi

Add the following to nginx configuration:

    location ~ \.php$ {
        #fastcgi_pass   127.0.0.1:9000;
        fastcgi_pass    unix:/tmp/fcgi.sock;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME /var/www$fastcgi_script_name;
        fastcgi_param   QUERY_STRING    $query_string;
        fastcgi_param   REQUEST_METHOD  $request_method;
        fastcgi_param   CONTENT_TYPE    $content_type;
        fastcgi_param   CONTENT_LENGTH  $content_length;
        fastcgi_param   SCRIPT_NAME     $fastcgi_script_name;
        fastcgi_param   REQUEST_URI     $request_uri;
        fastcgi_param   DOCUMENT_URI    $document_uri;
        fastcgi_param   DOCUMENT_ROOT   $document_root;
        fastcgi_param   SERVER_PROTOCOL $server_protocol;
        fastcgi_param   SERVER_SOFTWARE nginx/$nginx_version;
        fastcgi_param   REMOTE_ADDR     $remote_addr;
        fastcgi_param   REMOTE_PORT     $remote_port;
        fastcgi_param   SERVER_ADDR     $server_addr;
        fastcgi_param   SERVER_PORT     $server_port;
        fastcgi_param   SERVER_NAME     $server_name;
        fastcgi_param   GATEWAY_INTERFACE       CGI/1.1;
    }

These examples are taken from production server, running php in fascgi mode with nginx and boost rules.

andribas’s picture

Thank you for config BOOST!!!

I have tested it for drupal 6.10 - works really fast as nginx should be.

mikeytown2’s picture

Issue tags: +Documentation

need to add documentation to module

George2’s picture

for 6 as of the current version of boost, you need to remove the 0 from the rewrite rules and the rules for checking from #7:

## Boost rewrite rules
## http://drupal.org/node/244072
set $boost "";

if ( $request_method = GET ) {
set $boost G;
}
if ($http_cookie !~ "DRUPAL_UID") {
set $boost "${boost}D";
}
if ($query_string = "") {
set $boost "${boost}Q";
}

if ( -f $document_root/cache/$host/index.html ) {
set $boost "${boost}I";
}

## GDQI, request is for main page
if ($boost = GDQI) {
rewrite ^/$ /cache/$server_name/index.html break;
}

if ( -f $document_root/cache/$host/$request_uri.html ) {
set $boost "${boost}F";
}

## GDQIF, the request is for subpage
if ($boost = GDQIF) {
rewrite .? /cache/$server_name/$request_uri.html break;
}

if ( -d $document_root/cache/$host/$request_uri ) {
set $boost "${boost}E";
}
if ( -f $document_root/cache/$host/$request_uri/index.html ) {
set $boost "${boost}F";
}
## GDQEF, the request is for module main page
if ($boost = GDQEF) {
rewrite .? /cache/$server_name/$request_uri/index.html break;
}
## Boost rewrite rules end

mikeytown2’s picture

just a heads up, I've been able to get this down to 2 rules - one for html, one for html.gz
http://drupal.org/node/428942#comment-1633210

Still testing it, but this is where boost is headed. Expect this in the next release which should be beta if I can get some bugs worked out.

scroogie’s picture

i don't understand mikey, which rules will be needed for nginx still?

mikeytown2’s picture

Version: 5.x-1.0 » 6.x-1.x-dev

Here is the bare minimum apache rules

  RewriteCond %{REQUEST_METHOD} ^GET$
  RewriteCond %{HTTP_COOKIE} !DRUPAL_UID
  RewriteCond %{DOCUMENT_ROOT}/cache/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}.html -f
  RewriteRule .* cache/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}.html [L]

To include Gzip these are the apache rules

  #gzip
  RewriteCond %{REQUEST_METHOD} ^GET$
  RewriteCond %{HTTP_COOKIE} !DRUPAL_UID
  RewriteCond %{HTTP:Accept-encoding} gzip
  RewriteCond %{DOCUMENT_ROOT}/cache/gz/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}.html.gz -f
  RewriteRule .* cache/gz/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}.html.gz [L]

  #normal
  RewriteCond %{REQUEST_METHOD} ^GET$
  RewriteCond %{HTTP_COOKIE} !DRUPAL_UID
  RewriteCond %{DOCUMENT_ROOT}/cache/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}.html -f
  RewriteRule .* cache/%{SERVER_NAME}%{REQUEST_URI}_%{QUERY_STRING}.html [L]

Here's my take on #14

## Boost rewrite rules
## http://drupal.org/node/244072 
set $boost "";

if ( $request_method = GET ) {
set $boost G;
}
if ($http_cookie !~ "DRUPAL_UID") {
set $boost "${boost}D";
}

if ( -f $document_root/cache/$host/$request_uri_$query_string.html ) {
set $boost "${boost}F";
}

## Normal Rewrite rules
if ($boost = GDF) {
rewrite .? /cache/$server_name/$request_uri_$query_string.html break;
}
## Boost rewrite rules end

Edit: Removed [OR] in the above apache rules.

mikeytown2’s picture

Status: Active » Needs work

Would someone mind writing in support for gzip?

brianmercer’s picture

This is working for me at the moment with version 0.7.61 (try_files and @locations are version 0.7.xx features):

...
        location / {
                try_files $uri @cache;
        }

        location @cache {
                if ( $request_method !~ GET ) {
                        rewrite ^/(.*)$ /index.php?q=$1 last;
                }
                if ($http_cookie ~ "DRUPAL_UID") {
                        rewrite ^/(.*)$ /index.php?q=$1 last;
                }
                try_files /cache/$host${uri}_$args.html @drupal;
        }

        location @drupal {
                rewrite ^/(.*)$ /index.php?q=$1 last;
        }

        location ~ \.php$ {
                try_files $uri @drupal;
                include /etc/nginx/fastcgi_params;
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
...

I've been stumped on how to serve the .html.gz file with this setup, but then I gave up and did it another way using the gzip_static module for nginx. The ubuntu versions don't have it compiled in (including the karmic 0.7.59 one), but if you compile nginx with --with-http_gzip_static_module and set gzip-static on, it will check for an .html.gz file any time it serves a .html file. It only checks the same directory as the .html file, so I had to change the module so it puts the html.gz files in the same directories as the .html files.

-     define('BOOST_GZIP_FILE_PATH',       str_replace(BOOST_ROOT_CACHE_PATH . '/', BOOST_ROOT_CACHE_PATH . '/gz/', BOOST_FILE_PATH));
+    define('BOOST_GZIP_FILE_PATH',       variable_get('boost_file_path',''));

and then it serves the html.gz instead. Nginx takes care of the browser compatibility checking and defaults to the .html file if the browser doesn't support gzip and follows your other gzip rules like not serving gzip files to MSIE 1-6 if you set that as well. I followed the guide for recompiling nginx into an updated .deb at http://ubuntuforums.org/showthread.php?t=1105902 so I could keep the init scripts.

mikeytown2’s picture

@brianmercer
What about query strings?

Would you like there to be a setting so one can place the gz and normal files in the same dir structure? Reason for the split in the first place has to do with #410730: System limits: Number of files in a single directory; didn't want to make that problem any worse.

brianmercer’s picture

OK, changed to

try_files /cache/$host${uri}_$args.html @drupal;

I can't say whether it's important enough to clutter the UI. Is there some way it could be put in settings.php for the few people using nginx and gzip_static?

And just curious, the module makes a static file for "example.com/forums/public-forums/general-discussion?sort=asc&order=Created" but not for "example.com/forums/public-forums/general-discussion?sort=asc&order=Last+reply"?

mikeytown2’s picture

Reason it doesn't do the second one has to do with the fact there is a + in the URL. You can make it cache pages like that by un-checking Only allow ASCII characters in path. It's found under "Boost advanced settings". Default is a super restrictive regular expression in boost_file_path() (line 988).

  // Don't cache path if it can't be served by apache.
  if (BOOST_ONLY_ASCII_PATH) {
    if (preg_match('@[^/a-z0-9_\-&=,\.:]@i', $path)) {
      return FALSE;
    }
  }

I should probably add in the + symbol so it would be this most likely.

  // Don't cache path if it can't be served by apache.
  if (BOOST_ONLY_ASCII_PATH) {
    if (preg_match('@[^/a-z0-9_\-&=,\.:\+]@i', $path)) {
      return FALSE;
    }
  }

Question is + also means a space so will the http server look for a " " or a "+" when looking for the file to serve.

Nigel Cunningham’s picture

subscribing

dropchew’s picture

subscribing

@brianmercer. I tried your rules and place the gz together with html in the same dir. But is there anyway to check if the server is retrieving the gz files instead of htmls? Thanks!

brianmercer’s picture

I deleted the gz file and then replaced it with a file of the same name that was empty and then reloaded to see if it went blank. (using rm and touch)

mikeytown2’s picture

@dropchew, @brianmercer

The YSlow Firefox add-on has a tab called components; you can check for gzip compression there. See YSlow User Guide -> Components View.

brianmercer’s picture

I've been messing around with it. Adding the GET and cookie checks for the css and js made me switch from rewrites to fake error codes. Might be better to just run the checks at the beginning and set a variable, but this works.

server {
    listen  80;
    server_name  example.com;
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;
    root /var/example.com;
    index index.php;

    if ($host !~* ^(example.com)$ ) { # deny illegal host headers
        return 444;
    }

    location / {
        rewrite ^/(.*)/$ /$1 permanent; # remove trailing slashes for SEO
        error_page 404 @drupal; 

        try_files $uri @cache;
    }

    location @cache {
        if ( $request_method !~ GET ) { 
            return 599;
        }
        if ($http_cookie ~ "DRUPAL_UID") {
            return 599;
        }
        error_page 599 = @drupal;

        expires epoch;
        add_header Cache-Control "must-revalidate, post-check=0, pre-check=0";
        charset utf-8;

        try_files /cache/$host${uri}_$args.html @drupal;
    }

    location @drupal {
        rewrite ^/(.*)$ /index.php?q=$1 last;
    }

    location ~ \.php$ {
        try_files $uri @drupal; #check for existence of php file
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include /etc/nginx/fastcgi_params;
    }

    location ~ \.css$ {
        if ( $request_method !~ GET ) {
            return 598;
        }
        if ($http_cookie ~ "DRUPAL_UID") {
            return 598;
        }
        error_page 598 = @x598;

        access_log      off;
        error_log /dev/null crit; # prevent debugging  if compiled --with-debug
        expires         max; #if using aggregator

        try_files /cache/$host${uri}_.css $uri @x404;
    }
    
    location ~ \.js$ {
        if ( $request_method !~ GET ) {
            return 598;
        }
        if ($http_cookie ~ "DRUPAL_UID") {
            return 598;
        }
        error_page 598 = @x598;

        access_log  off;
        expires  max; # if using aggregator

        try_files /cache/$host${uri}_.js $uri @x404;
    }

    location @x598 {
        access_log  off;
        expires  max; # max if using aggregator, otherwise sane expire time
    }

    location ~* ^.+\.(jpg|jpeg|gif|png|ico)$ {
        if ($http_referer !~ ^(http://example.com) ) { # prevent image hijacking
            return 444;
        }

        access_log      off;
        expires         45d;

        try_files $uri @x404;
    }

    location @x404 {
        return 404;
    }

    location ~ /\. {
        deny all;
    }

    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;
    }
}

brianmercer’s picture

Question is + also means a space so will the http server look for a " " or a "+" when looking for the file to serve.

You're right. Boost creates a file name with a space and neither nginx or apache serve it. But definitely not a big concern for me.

dropchew’s picture

@#25

I should have thought of that earlier, neat and simple lol. Unfortunately, my nginx is still retrieving the htmls instead of gzips. I felt that Yslow's report are quite inconsistent. Eg, in my scenario, yslow gives an 'A' for gzip compression but actual fact nginx is still retrieving htmls. Maybe its 2 separate matters?

this is part of nginx.conf

gzip  on;
gzip_comp_level 2;
gzip_proxied any;
gzip_types   text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

Maybe my nginx is not compiled with gzip-static in the 1st place?

Edit. I just did some simple enable/disabling boost's gzip settings and check YSlow's components and it seems to be working.

brianmercer’s picture

It looks like you have nginx configured to gzip the files on the fly as you serve them if they're un-gzipped. Set "gzip off" and "gzip-static on" (you need both directives) in your nginx.conf and then restart. (Without gzip_static compiled in you'll get an error) If you're set up correctly with gzip_static then YSlow will show gzipped files while logged out and un-gzipped files while logged in. That would apply only to the main document if you used my #19 config or to both the main doc and the js and css files if you are using my #27 config. My "Compress components with gzip" grade flips from A to D as I log in if I have "gzip off". (tho I have to refresh a couple times. something hinkey with YSlow and the login redirect) Then once you've confirmed that you're serving the .html.gz files you can restore "gzip on".

You didn't mention where you're getting your nginx. I run Ubuntu and I can tell you that the repository versions do not have gzip_static compiled in. You can do "nginx -V" (capital V) and it will show you the compile options. It has to show --with-http_gzip_static_module. I compiled a few different .debs of version 0.7.61. One --with-http_gzip_static_module, one --with-debug to track the redirects, and one lean and mean.

If you don't have gzip_static_module and recompiling sounds like a hassle, I wouldn't worry about it. I've been using apache bench and top to do some unscientific testing to compare the speed and load of allowing nginx to gzip on the fly versus serving the pre-gzipped files, and I can't see any difference. You would think that saving nginx the trouble of gzipping the files would make a difference in speed or CPU load, but apparently it's crazy efficient because I'm not seeing it. I'd be interested to know if anyone else here has an opinion or some real data.

mikeytown2’s picture

@brianmercer
Odds are it is using level 6 compression, Boost's default is level 9. Whats the filename of the config file (apache is .htaccess)? I would like to add the rules to the admin interface.

brianmercer’s picture

Nginx doesn't support .htaccess files in the htdocs directories. The rules go in the virtual server config files.

On ubuntu/debian they copy the apache2 layout and use /etc/nginx/sites-available/example.com and a symlink in /etc/nginx/sites-enabled with "include /etc/nginx/sites-enabled/*;" in the /etc/nginx/nginx.conf. But I don't know if other distributions do that. Other distributions might put virtual server config files in /etc/nginx/conf.d/ which also has an include statement in the default nginx.conf for ubuntu. Lemme see if I can peek into the nginx.conf files for a few distributions and see how they do it. I got the feeling from the mailing list that some think copying the apache2 layout is silly since there are no a2ensite-like scripts to make enabling and disabling easier.

At #27 I just copied my current config. Some of the settings in there are not related to boost and make assumptions like use of clean urls and css/js aggregation. I know that drupal's default .htaccess sets expires at 2 weeks and maybe that's a good default.

mikeytown2’s picture

Whats a good way to detect in php that it is Nginx not Apache?

brianmercer’s picture

I'm no programmer. Maybe $_SERVER['SERVER_SOFTWARE'].

About the configuration file, the source package puts the virtual server stuff right in the /etc/nginx/nginx.conf file. The Red Hat rpm puts a default config at /etc/nginx/conf.d/virtual.conf. So...depends on your distro and it requires editing the default location / {} that comes in the default file. Maybe just point them to this thread.

mikeytown2’s picture

What's the output of $_SERVER['SERVER_SOFTWARE'] on your setup? Going to use stristr().

scroogie’s picture

$_SERVER["SERVER_SOFTWARE"] is just "nginx" for me.

mikeytown2’s picture

thats a little short, but usable. I get this on mine

Apache/2.2.11 DAV/2 mod_ssl/2.2.11 OpenSSL/0.9.8i PHP/5.2.9

http://drupal.org/node/489824#comment-1702912

brianmercer’s picture

nginx/0.7.61

brianmercer’s picture

I posted the config to the nginx mailing list and I made a couple small changes based on recommendations.

server {
    listen  80;
    server_name  example.com;
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;
    root /var/example.com;
    index index.php;

    location / {
        rewrite ^/(.*)/$ /$1 permanent; # remove trailing slashes
        try_files $uri @cache;
    }

    location @cache {
        if ( $request_method !~ GET ) { 
            return 405;
        }
        if ($http_cookie ~ "DRUPAL_UID") {
            return 405;
        }
        error_page 405 = @drupal;

        expires epoch;
        add_header Cache-Control "must-revalidate, post-check=0, pre-check=0";
        charset utf-8;

        try_files /cache/$host${uri}_$args.html @drupal;
    }

    location @drupal {
        rewrite ^/(.*)$ /index.php?q=$1 last;
    }

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

    location ~ \.php$ {
        try_files $uri @drupal; #check for existence of php file
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include /etc/nginx/fastcgi_params;
    }

    location ~ \.css$ {
        if ( $request_method !~ GET ) {
            return 405;
        }
        if ($http_cookie ~ "DRUPAL_UID") {
            return 405;
        }
        error_page 405 = @uncached;

        access_log  off;
        expires  max; #if using aggregator

        try_files /cache/$host${uri}_.css $uri =404;
    }
    
    location ~ \.js$ {
        if ( $request_method !~ GET ) {
            return 405;
        }
        if ($http_cookie ~ "DRUPAL_UID") {
            return 405;
        }
        error_page 405 = @uncached;

        access_log  off;
        expires  max; # if using aggregator

        try_files /cache/$host${uri}_.js $uri =404;
    }

    location @uncached {
        access_log  off;
        expires  max; # max if using aggregator, otherwise sane expire time
    }

    location ~* ^.+\.(jpg|jpeg|gif|png|ico)$ {
        if ($http_referer !~ ^(http://example.com) ) { # prevent image hijacking
            return 444;
        }

        access_log      off;
        expires         45d;

        try_files $uri =404;
    }
}
mikeytown2’s picture

  if (stristr($_SERVER["SERVER_SOFTWARE"], 'apache')) {
    // print apache rules
  }
  elseif (stristr($_SERVER["SERVER_SOFTWARE"], 'nginx')) {
    // print nginx rules
  }
  elseif (stristr($_SERVER["SERVER_SOFTWARE"], 'lighttpd')) {
    // print lighttpd rules
  }
  else {
    // running unsupported server software
  }
mikeytown2’s picture

I see that you added in support for css/js. One problem I see is if the css/js files are not in the cache, it delivers a 404. This is not ideal, it should try the actual file as well. This is more of a hack so one can run update.php with the site offline and still have it serve correct pages to anonymous users (update.php kills aggregated css/js files). It also allows for things such as googles cache of your site to look correct, since those css files will still be there. This shouldn't break anything because the page doesn't get served until the css/js files have been copied; unless they have boost's caching of css/js switched off, then it might be an issue.

Is there anyway of supporting feeds and .xml files?

mikeytown2’s picture

forget the long statement above... I see how try_files works. It's all good.

brianmercer’s picture

        location ~ (/rss\.xml$|/feed$) {
                if ( $request_method !~ GET ) {
                        return 405;
                }
                if ($http_cookie ~ "DRUPAL_UID") {
                        return 405;
                }
                error_page 405 = @drupal;

                expires epoch;
                add_header Cache-Control "must-revalidate, post-check=0, pre-check=0";
                charset utf-8;

                try_files /cache/$host${uri}_.xml $uri @drupal;
        }
scroogie’s picture

Won't those rules about css, js, etc. slow down the machine? I imagine they are evaluated x times per page hit.

mikeytown2’s picture

@scroogie
Those rules are in there as a sorta bug fix... ideally I wouldn't need the css/js rules. #41 has some of my reasoning behind it. #413908: Cache js/css files, allow for a "static" site
I'm not sure how much it effects performance, my guess would be 0.1%; instead of 1000 transactions per second, now 999. Feel free to benchmark :)

Next step after incorporating the generation of these rules would be to make them conditional, if css caching is not checked then the css rules don't appear.

dicreat’s picture

Sorry for intervene - does somebody use Nginx Upload Progress Module with Drupal for upload progress bar? Do you know any working solution for upload progress bar on Nginx? Thanks!

brianmercer’s picture

Had to change #43

- location ~ (\.xml$|/feed$) {
+ location ~ (/rss\.xml$|/feed$) {

mikeytown2’s picture

@brianmercer
why not handle all *.xml files?

brianmercer’s picture

It was screwing up fckeditor. When you're logged in, it redirects fckstyles.xml to @drupal and rewrites it without checking for existence of the file first. Maybe if I stuck another try_files in there somewhere...but you can't put try_files within an if{}, would have to do another @location... mmm.

omega8cc’s picture

Just another full working example of Nginx configuration to use Boost in Drupal (Aegir). In this example Pathauto is used to define where Boost will work (by ending all boost-able URLs with .html)

http://groups.drupal.org/node/23907#comment-82841

HTH,
Grace

P.S. (July 7)
It is example for 5.x only (rules).
6.x version will be shared with community soon (we are just moving with Aegir to 6.x)

mikeytown2’s picture

FYI, the rules in the above link are for 5.x

omega8cc’s picture

Not sure how it works in 6.x, but in 5.x (hacked to allow caching this) I had to add in rss/feed location in Nginx:

default_type text/xml;

Best,
Grace

mikeytown2’s picture

@omega8cc
Sounds like you know how boost works. Would you be interested in this?
#454652: Looking for a co-maintainer - 5.x

brianmercer’s picture

@omega8cc

I only checked the feed in firefox live bookmarks, but it worked. I'll try it with some other feed readers.

Do you have

text/xml                              xml rss;

in your /etc/nginx/mime.types?

Thanks.

omega8cc’s picture

@mikeytown2

I can help, however I'm not a PHP coder, and co-maintainer role can be a bit over my competence.
What I know best is advanced VPS/OS/Web/Drupal setups and mostly Getting Things Done with Drupal.
Of course I managed to get Boost 5.x to work with caching feeds, but it was rather simple with Nginx.
If you believe it is enough to start with backporting Boost to 5.x - who knows, maybe I can do that?

Best :)
Grace

omega8cc’s picture

@brianmercer

Yes, I had it in the included mime.types, but slightly different:

    text/xml                              xml;
    application/atom+xml                  atom;
    application/rss+xml                   rss;

I remember I had default_type application/octet-stream; in the main http Nginx config section, so had to add correct default_type in feed/rss location. If I remember correctly, I tested it with online validators to find best match and found it was application/rss+xml working best.

It's possible you don't need this if you are just including mime.types, but without default_type global setting.

Thanks,
~Grace

[edit]
And one more thing: I had to force correct mime type because we had all feeds mapped to URLs from old app imported to Drupal so users didn't noticed any change in subscribed blogs/threads, and these old URLs were not compatible with mime ext. for rss.
[/edit]

brianmercer’s picture

I have "default_type application/octet-stream;" in my nginx.conf also. I switched to your mime.types config and tried Opera and Safari for feed readers and they all worked fine in Drupal 6.x. (Opera didn't pull the gzipped version, but Safari did.) It could be a Drupal 5.x thing, but I don't have it installed to test. Anyways, good info to have here in case someone runs into that problem.

mikeytown2’s picture

Could I get some comments on a proposal I have, as this will directly effect Nginx.
#537186: Better prevention of URL collisions.

mikeytown2’s picture

@omega8cc
Any word on your set of rules for Nginx? or should I go with brianmercer's #39

omega8cc’s picture

@mikeytown2

Didn't tried yet how === will work for try_files.

While I understand it's always better to have prevention of URL collisions, I'm not sure if this one is something worth to introduce maybe new problems with httpd servers compatibility.

What I mean is "less is more".

Are you sure it's worth to change something like that (no backward compatibility) just because of very rare theoretical problems with URL collisions?

I'm not sure, but will try how it works and will report the results here.

~Grace

-- Turnkey Drupal Hosting on Steroids -- http://omega8.cc

omega8cc’s picture

@mikeytown2

brianmercer's rules with try_files and error_page 405 tweak are good and it works.

My configuration includes also additional rewrite rules required in some of my custom setups, but not necessary in default Drupal on Nginx setup.

I will sort it out a bit to find if any of them would be useful in default and will share the results here.

~Grace

-- Turnkey Drupal Hosting on Steroids -- http://omega8.cc

brianmercer’s picture

Not related to Boost, but I also added

    location ~* /files/.*\.php$ { }

before the .php location to discourage code execution from the upload directory.

mikeytown2’s picture

#537186: Better prevention of URL collisions. is there... mainly for documentation. It's something I don't plan on committing any time soon. If I do, it would be a user editable thing, where the admin can choose what character(s) will be used to replace ?. Thus for linux, one can use ?.

omega8cc’s picture

@brianmercer

I think we don't need another location before .php for this security check.
For Nginx and Boost 5.x I have made it inside .php location:
http://groups.drupal.org/node/23907#comment-82841

Now it could be:

    location ~ \.php$ {
        if ( $uri !~ "^/files/") {
           try_files $uri @drupal; #check for existence of php file
           include /etc/nginx/fastcgi_params;
           fastcgi_pass 127.0.0.1:9000;
        }
    }

BTW: I prefer to have most of fastcgi_* in the included fastcgi_params but this is a side note only.

[EDIT] It doesn't work, try_files is NOT allowed in if {} - sorry for confusion, separate location is required here:

location ~* /files/.*\.php$ { }

omega8cc’s picture

@mikeytown2

That sounds perfect. Did I told you I'm impressed with the progress on this module? I remember when I used it in its early stage in 5.x and it's hard to compare how it is managed now. I can't keep up with this speed! :-)

~Grace

-- Turnkey Drupal Hosting on Steroids -- http://omega8.cc

jwxie’s picture

This is getting my nerve... so many recommendation and I don't know which one to go with
I actually followed this - now do I need BOOST?
I haven't do any rewrite rule for nginx.. actually nothing config has done for nginx to make it compatible to apache...
for example, rewrite rule and deny-all rule

omega8cc’s picture

@jwxie

You can use above Nginx configuration example also without Boost if you don't need Boost.
But in this case your Nginx configuration could be a lot simpler.
Some examples here: http://drupal.org/node/110224

HTH

~Grace -- Turnkey Drupal Hosting on Steroids -- http://omega8.cc

omega8cc’s picture

Another important detail when you are using ImageCache:

    location ~* ^.+\.(jpg|jpeg|gif|png|ico)$ {
        access_log      off;
        try_files $uri @drupal;
    }

Note - the last hop in try_files should be @drupal and not =404 in this case.

HTH

~Grace -- Turnkey Drupal Hosting on Steroids -- http://omega8.cc

brianmercer’s picture

I'm not using imagecache atm, but I've seen in other nginx/imagecache threads that folks limit it to a directory, i.e.

location ~* ^.*/files/imagecache/ {
     access_log      off;
     try_files $uri @drupal;
}
omega8cc’s picture

Another trick to redirect all requests from www to raw domain.

    ## www. redirect
    if ($host ~* ^(www\.)(.+)) {
        set $rawdomain $2;
        rewrite ^/(.*)$  http://$rawdomain/$1 permanent;
    }

You can add this before first location.

~Grace

brianmercer’s picture

If you're doing specific host names, Igor recommends using server blocks, i.e.

server {
     listen 80;
     server_name example.com;
     ...
}

server {
     listen 80;
     server_name www.example.com;
     rewrite ^ http://example.com$request_uri?;
}

but I dunno how to do your multisite config that way.

Edit: Mmmm... apparently the same way as you did it, just in a server block:

server {
        listen  80;
        server_name ~www\.(.*\..*);
        set $domain $1;
        rewrite ^ http://$domain$request_uri?;
}
omega8cc’s picture

Using separate server {} blocks makes your Nginx configuration much harder to manage, unless you need it to serve different kind of sites on the same machine, for example TextPattern and Digital Workroom requires completely different rewrites than Drupal, especially with enabled Boost.

But if you are using Nginx only for Drupal, there is no point to use separate server {} blocks or separate includes (per domain).

With Aegir we are using just one-for-all server {} block with wildcard config (it works behind proxy):

  server {
        limit_conn   gulag 5;
        listen       127.0.0.1:88;
        server_name  _;
        root         /data/u/$host/;
        index        index.php index.html;
        ...

Note the _; in server_name and $host in root.

The same setup can work for multisite and for just one site and allows to use one-for-all www redirect.

~Grace -- Turnkey Drupal Hosting on Steroids -- http://omega8.cc

brianmercer’s picture

I do like your Aegir setup. This should also work without adding much complexity, and would work, as you suggest, if you had other server blocks with different configurations (i.e. a wordpress blog):

server {
        listen       127.0.0.1:88;
        server_name ~www\.(.*\..*);
        set $domain $1;
        rewrite ^ http://$domain$request_uri?;
}

server {
        limit_conn   gulag 5;
        listen       127.0.0.1:88;
        server_name  _;
        root         /data/u/$host/;
        index        index.php index.html;
        ...

I don't know why Igor is militant about doing the host evaluation at the server block level. I assume it has something to do with optimizing the number of regular expressions to be evaluated, and perhaps would be counterproductive with just the one server block, as you say.

brianmercer’s picture

Also if you want to have domain.com redirect to www.domain.com but leave subdomain.domain.com alone and not add the www to it, you can do

server {
  listen 80;
  server_name ~^[^.]+\.[^.]+$; # domain.com
  rewrite ^ http://www.$host$request_uri?;
}

server {
  listen 80;
  server_name www.*; # www.domain.com
  server_name ~^[^.]+\.[^.]+\.[^.]+$; # sub.domain.com
  ...
}

which is straight from http://forum.nginx.org/read.php?2,2924,2936#msg-2936

omega8cc’s picture

Well, why to use server {} separate block for this fairly simple www rewrite?

Separate server {} block makes sense when you need to separate configurations listening on different ports or for individual domains, besides wildcard.

Furthermore, I believe you shouldn't use server {} block for this task because it forces you to use only wildcard setup and also breaks https if used (note we are rewriting here to http only).

server {} block level is too high for this type of task, I think.

If we want to redirect www also for https requests, we need only one more, cloned wildcard server {} block with different port and https used in rewrite. Pound can then simply use this separate port to proxy there https requests.

Simple and still flexible enough, I think.

HTH ~Grace -- Turnkey Drupal Hosting on Steroids -- http://omega8.cc

brianmercer’s picture

I don't know why, but that thread I linked is not the only time Igor's said it. He repeats it every couple weeks when someone uses $host in an if.

Since he single-handedly wrote the nginx web server, I assume he has a reason.

You shouldn't have any trouble with https since you can do

server {
  listen 80;
  server_name ~^[^.]+\.[^.]+$; # domain.com
  rewrite ^ $scheme://www.$host$request_uri?;
}
omega8cc’s picture

You are right with $scheme for https, however I think using server {} block for www redirect is good only when you want it to be global for all domains hosted. Let's call it my preference =)

As long as it works, I don't need separate server {} block in this case, just rewrite inside one server {} block.

~Grace

brianmercer’s picture

RC4 unusable on my testbed. Haven't looked into it yet. Anyone else tried it?

mikeytown2’s picture

@brianmercer
Your not the first one to report some issues with it... #566984: Crawler not working as expected
Any help on pinpointing the issue is greatly appreciated. The dir's are no longer hard-coded in so that could be part of the problem... but that also means you can put everything in 1 dir, no more gz dir; should make people's life easier in the long run who have to make the rewrite rules.

brianmercer’s picture

In nginx, boost-crawler is timing out with a 504 from php-cgi.

127.0.0.1 - - [03/Sep/2009:18:44:54 -0400] "GET /boost-crawler?nocache=1&key=6b16989e54f0bfb55b3174aaa2a54924 HTTP/1.0" 504 183 "-" "Drupal (+http://drupal.org/)"
mikeytown2’s picture

@brianmercer
does your php setup allow for ini_set to work from a script? Also are you running in safe-mode? http://php.net/set-time-limit. Try setting "Crawler Batch Size: " to something like 3.

brianmercer’s picture

Crawler Batch Size: 3 has no effect. Not safe-mode. Not sure how to verify ini_set, except that the memory size setting from settings.php seems to work.

This is with "Preemptive Cache" and "Crawl All URL's in the url_alias table" in their default unchecked state. Is there a way to disable boost-crawler?

It's doing something evil to php. It is making other direct scripts like phpsysinfo.php and apc.php take forever or time out.

Now I'm having trouble with Apache also.

I will uninstall and reinstall again and see what happens.

mikeytown2’s picture

It should only do the "evil" stuff if the crawler is running...

function boost_crawler_run() {
  // Set PHP INI Variables, try to prevent crawler from stalling.
  Global $base_url;
  ini_set('max_execution_time', 600);
  ini_set('output_buffering', 'off');
...
mikeytown2’s picture

I think I need to refactor the code so the "evil parts" only get called where it's needed. Looks like I need to call ini_restore before exiting as well, due to APC caching.

mikeytown2’s picture

omega8cc’s picture

I can confirm same problems with Boost Crawler on Nginx. It freezes cron etc. I had to disable Crawler completely. I don't use APC, but eAccelerator - not sure if this can be related in any way.

~Grace

[EDIT] Just tried with Boost dev from Sept 4, and so far the Crawler works again - thanks! =)

mikeytown2’s picture

@omega8cc, @brianmercer
Can you try the latest dev?

omega8cc’s picture

@mikeytown2

Just added [EDIT] above. It works! Thanks =)

~Grace

The only minor issue is reported error:

Details
Type	php
Date	Friday, September 4, 2009 - 19:51
User	Anonymous
Location	http://omega8.cc/boost-crawler?nocache=1&key=bdd5ff07c8e497e78df79432676b9092
Referrer	
Message	Cannot modify header information - headers already sent by (output started at /data/aegir/pressflow-ubercart/index.php:42) in /data/aegir/pressflow-ubercart/includes/bootstrap.inc on line 877.
Severity	error
Hostname	83.170.112.242
Operations	

And line nr 42 in my index.php is:

print theme('page', $return);
mikeytown2’s picture

FileSize
913 bytes

here's a patch that should prevent that... I hope.

brianmercer’s picture

I installed the 1.x-dev.

Anonymous is working fine. Authenticated user browsing content is fine. Node edit and POST is all fine. But I'm timing out on /admin and then fastcgi becomes very slow and must be restarted.

2009/09/04 20:58:37 [error] 2182#0: *148 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.1.101, server: home.brianmercer.com, request: "GET /admin HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "home.brianmercer.com:8080", referrer: "http://home.brianmercer.com:8080/blogpost/testing-inline-module"
2009/09/04 20:58:37 [error] 2182#0: *150 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 127.0.0.1, server: home.brianmercer.com, request: "GET /boost-crawler?nocache=1&key=a46c746555e28c91d2759d19faaabed2 HTTP/1.0", upstream: "fastcgi://127.0.0.1:9000", host: "home.brianmercer.com:8080"

This testbed is overdue for a wipe. It's had a jillion modules installed (included dev) and uninstalled (some not so cleanly) so perhaps it's not a good test. I'll wipe it tomorrow and see what happens.

I see the new checkboxes for "Preemptive Cache xxxx" but they're grayed out and I don't understand how to disable the whole pre-cache system to see if that's what's causing my hang.

Thx.

mikeytown2’s picture

FileSize
1.15 KB

further refinements for output buffer

omega8cc’s picture

With second patch applied it now returns error:

Cannot modify header information - headers already sent by (output started at /data/aegir/pressflow-ubercart/sites/all/modules/performance/boost/boost.module:2413) in /data/aegir/pressflow-ubercart/includes/bootstrap.inc on line 877.

But crawler works fine.

~Grace

omega8cc’s picture

@brianmercer

You should be able to turn off that Boost Crawler at: admin/settings/performance/boost

Look at the bottom, there is "Boost crawler" section and disable there "Enable the cron cralwer" (typo there!) and "Crawl All URL's in the url_alias table" - if you have them enabled.

~Grace

brianmercer’s picture

Thx, Grace. OK, I have those Boost Crawler checkboxes in their unchecked state, but now I think it may not have to do with the crawler or nginx. Since I'm the only one experiencing it and it also seems to slow my apache install of the same site, instead it has to do with the alternate setup that I use and has to do with something that boost is checking for status.

I created a fresh install and navigated around and it only hangs on the /admin page and the /admin/reports/status, which suggests some boost function for checking .htaccess or something similar is hanging me.

By alternate setup, I mean http://justinhileman.info/articles/a-more-secure-drupal-multisite-install where you put each site in its own directory and use php files with includes in them to the actual install. (for various reasons like each site can have its own .htaccess, robots and favicon, though those are solved with modules now, and so http://site1.com/files/site1.com/pic.jpg and http://site2.com/files/site1.com/pic.jpg don't both resolve to the same file and so that settings.php and private files are not in the web root)

I'm installing a fresh install with its own set of drupal core files now to test this theory.

Sorry, Mike. Thx.

mikeytown2’s picture

@omega8cc
If the headers are already sent, like in your case, the crawler take a longer time spinning up the threads because it now waits (3 seconds) for it time out, rather then the headers saying "all done".

@brianmercer
There was a dumb error on the status check page that was causing it to take forever. I forgot to add in &test=1 to the url, so the crawler thought it was running for real. It's in RC4 so I need to push out RC5 soon because it's a pretty crappy error.

New dev out today and dbeall confirms it's working. I knew there would be some growing pains with doing something that's never be done before, didn't expect it to hurt this much.

brianmercer’s picture

OK, cool. Yeah, my alternate config didn't matter.

I installed today's 1.x-dev and the fresh install works fine on Apache and gives the ".htaccess file does not contain the boost specific rewrite rules..." error instantly.

On nginx it still hangs. So it seems to be in the web-server/.htaccess checking somewhere.

Thanks for your hard work, Mike, and your attention to nginx specific issues.

I saw your comment on Dries' blog about sharing the Acquia Hosting nginx config. Let us know if he gets back to you. I wasn't sure from his statement "The web nodes are load-balanced with Nginx..." whether Acquia is using nginx as a front-end load balancer|static file server|cache (all of which it can do like Varnish or Squid) and then proxying at the back-end to apache, or whether he's proxying to fastcgi for dynamic requests and foregoing apache entirely. It'll be interesting to find out.

mikeytown2’s picture

@brianmercer
Would you mind commenting out the different parts of boost_requirements() to try and identify which ones cause nginx to hang.

Try these first:
Line 70: $crawler_response = drupal_http_request(BOOST_CRAWLER_SELF . '&test=1');
line 100-107: if ($htaccess && count(explode("%{REQUEST_URI}$char%{QUERY_STRING}\.html", $htaccess)) < 3) { ... }

brianmercer’s picture

Line 70: $crawler_response = drupal_http_request(BOOST_CRAWLER_SELF . '&test=1');

does it. If I comment out that one line, there's no hang.

And then there's two errors on the status page

Boost	.htaccess file
.htaccess file does not contain the boost specific rewrite rules, or the rewrite rules have changed and they need to be updated. Get rules: Boost Apache .htaccess settings generation.
Boost	Boost crawler did not get a 200 response.
returned. Crawler URL (http://test2.brianmercer.com:8080/boost-crawler) is not available, please report this issue
mikeytown2’s picture

odd... drupal_http_request() times out after 15 seconds; actually wrote a patch for that so it can last longer #156582: drupal_http_request() should support timeout setting. URL is built like this

define('BOOST_CRAWLER_SELF',         $base_url . '/' . 'boost-crawler?nocache=1&key=' . variable_get('boost_crawler_key', FALSE));

Separate note, I should put in a variable_set instead of FALSE, one less thing to worry about...

Does $base_url on your setup look odd?

mikeytown2’s picture

k so i need to do the server test, because drupal ships with .htaccess so it's presence to test for apache is a bad idea; see #40.

As for why this drupal_http_request() times out... thats interesting, to say the least. Is 404/403/503(maintenance mode) working on your setup?

brianmercer’s picture

How could I check that?

<?php
print $base_url;
?>

in a php-filtered node shows nothing.

Is there some way to list that stuff from the devel module? Sorry, I'm a newb.

mikeytown2’s picture

global $base_url;
print $base_url;
brianmercer’s picture

I should have known that. :)

Looks normal to me:

http://test2.brianmercer.com:8080

I have apache running on port 80 and nginx on port 8080 here at home on this testbed server.

mikeytown2’s picture

FileSize
838 bytes

here's the smarter apache test

brianmercer’s picture

I wonder if this has something to do with my nginx config since Grace doesn't seem to be having the same problem. Gotta run for now but I'll mess with it tonight.

mikeytown2’s picture

FileSize
1.91 KB

I'm assuming http://test2.brianmercer.com/ is set to 127.0.0.1 or something like that on your local box... but that could be the issue for some very strange reason.

Now it only tests if the crawler is turned on... not ideal since that url should work, but it does make sense.

This has been committed

omega8cc’s picture

Update: after I restarted php-fpm, all the "headers already sent" never happened again. It was related to old eAccelerator version (cache). Now it just works with patch:

http://drupal.org/files/issues/boost-ob.1.patch

Boost Crawler, cache expiration etc. - everything works as expected.

~Grace

omega8cc’s picture

BTW: "#Drupal Gardens now powered by #Nginx" - noticed that: http://twitter.com/omega8cc/status/3714176200

~Grace =)

brianmercer’s picture

Maybe there should be a groups.drupal.org for nginx for sharing configs and experiences. I nominate omega8cc as group manager. First post can be some advice on patching php for php-fpm. I'm still using spawn-fcgi.

1.x-dev is working fine for me as long as I keep the crawler disabled. Thx for that if patch. I'm going to review my nginx.conf setup and php settings.

mikeytown2’s picture

Having a nginx user group would be very useful IMHO.

omega8cc’s picture

OK, Nginx group is now waiting for moderation.

http://groups.drupal.org/nginx

In the meantime I will write a short how-to about php-fpm and Nginx.

Thanks!

~Grace

omega8cc’s picture

@brianmercer

Tried to respond in the Nginx group, but can't:

"Your submission has triggered the spam filter and will not be accepted."

Well, not sure if it looks like a spam:

http://omega8.cc/dev/for-gdo-this-is-spam.txt

~Grace

[EDIT] Spam filter on g.d.o. finally accepted my reply - please delete this comment. Thanks.

wobbler’s picture

How about the following if you don't have nginx with gzip_static module compiled in, also you don't need to change the boost module code. (this isn't supposed to be a full conf)

                location / {
                        try_files $uri @cache;
                }

                location @cache {
                        if ( $request_method != GET ) {
                                return 405;
                        }
                        if ($http_cookie ~ "DRUPAL_UID") {
                                return 405;
                        }
                        error_page 405 = @drupal;

                        if ( -f $document_root/cache/gz/$host${uri}_$args.html.gz ) {
                                rewrite .? /cache/gz/$host${uri}_$args.html.gz last;
                        }

                        try_files /cache/$host${uri}_$args.html @drupal;
                }

                location @drupal {
                        rewrite ^/(.+)$ /index.php?q=$1 last;
                }

                location ~ \.html\.gz$ {
                        add_header  Content-Encoding  gzip;
                        gzip off;
                        types { text/html gz; }
                }

                location ~ \.php$ {
                        try_files $uri @drupal;
                        fastcgi_pass   127.0.0.1:8888;
                        include        fastcgi_params;
                }

brianmercer’s picture

I don't completely remember all the things I tried, but it seems you'd achieve the same effect by removing the if{} and doing

try_files  /cache/$host${uri}_$args.html.gz  /cache/$host${uri}_$args.html  @drupal;

and that's likely to work... with some browsers.

But if the browser doesn't support gzipping, or doesn't recognize the gz file as a gzipped html file automatically, it's going to try to download it. The apache .htaccess rules check the browser for gzip capability before serving the .gz files and manipulate the file type. My recollection is that I tried a bunch of things to make it work with all browsers and then gave up and used gzip_static_module and it worked flawlessly.

There's no longer any need to hack the module, since Mike added options to the UI to set the directories.

With gzip_static_module, nginx handles the gzip capability testing, including how ie1-5 and ie6 before sp1 don't handle gzipped files well, with the setup like omega8cc has in her conf at http://groups.drupal.org/node/26363

## Compression
  gzip              on;
  gzip_buffers      16 8k;
  gzip_comp_level   9;
  gzip_http_version 1.1;
  gzip_min_length   10;
  gzip_types        text/plain text/css image/png image/gif image/jpeg application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  gzip_vary         on;
  gzip_static       on;
  gzip_proxied      any;
  gzip_disable      "MSIE [1-6]\.";

On the plus side, for ubuntu 9.10 karmic the repo has been upgraded to version 7.61 and now builds with both debugging and gzip-static.

bpm@c002:~$ nginx -V
nginx version: nginx/0.7.61
configure arguments: --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-debug --with-http_stub_status_module --with-http_flv_module --with-http_ssl_module --with-http_dav_module --with-http_gzip_static_module

So maybe all distros will start compiling those in by default and the recompiling problem will go away. BTW, for those using Ubuntu 8.04 (the latest Long Term Support release: LTS are on a 2 year cycle so next is 10.04), Jeff Waugh maintains PPAs for the stable 7.61 branch and for the unstable 8.XX branch. And his include the gzip_static_module.

https://launchpad.net/~jdub/+archive/ppa
https://launchpad.net/~jdub/+archive/devel

omega8cc’s picture

Hey! Please use our Nginx group to continue =)

~Grace

mikeytown2’s picture

Status: Needs work » Reviewed & tested by the community

Marking this config RTBC
http://groups.drupal.org/node/26363

Is there anything in here that needs special settings based on the server's setup, or is the Nginx configuration a 1 size fits all solution?

omega8cc’s picture

@mikeytown2

It should work with any Drupal site on any server, with/without Boost enabled, so it is safe and compatible.

Now added there - http://groups.drupal.org/node/26363 - also examples for custom nginx and php-fpm build to make it even easier for first time users.

Also updated main nginx config for imagecache compatibility.

~Grace

mikeytown2’s picture

Category: support » feature
omega8cc’s picture

Configuration example update: http://groups.drupal.org/node/26363#comment-109090

~Grace

usera’s picture

sub

scripthead’s picture

subscribing

adrianmak’s picture

subscribe

udvranto’s picture

Subscribing.

XiaN Vizjereij’s picture

Subscribe

chinabruce’s picture

Subscribe

bgm’s picture

Can someone write a summary of the discussion and what needs to be done so that we can close this issue?

Thanks

omega8cc’s picture

Status: Reviewed & tested by the community » Fixed

This thread is a mother of Nginx group: http://groups.drupal.org/nginx where you can find a few Boost compatible Nginx configurations, with probably the most mature and widely tested (and used) BOA configuration and good standalone (non-Aegir) configuration by perusio, so I believe it is safe to mark it as fixed, since any further discussion already takes place on the Nginx/Boost group on g.d.o

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

pkhlop’s picture

Subscribe