Nginx

Материал из OpenWiki
Перейти к: навигация, поиск

Ссылки с примерами настройки nginx

Пример преобразования rewrite правил:

Apache mod_rewrite:

   RewriteCond %{QUERY_STRING} !^nobranding$
   RewriteCond %{REQUEST_FILENAME} ^/assets/XL/([^.]+)\.([jpegif]+)$
   RewriteCond /usr/local/www/assets-nz/XL/%1.branded.%2 -f
   RewriteRule ^/([^.]+)\.([jpeg]+)$ /$1.branded.$2

nginx:

   location /assets {

      if ($args = nobranding) {
          rewrite  ^(.+)$ /nobranding$1  last;
      }

      rewrite  ^/assets/XL/(.+)\.(jpeg|jpg|gif)  /XL/$1.branded.$2;
      root /usr/local/www/assets-nz;
      error_page  404  =  /nobranding/assets$uri;
  }


  location /nobranding/assets {
      internal;
      alias /usr/local/www/assets-nz/;
  }


Другие примеры rewrite:

    # Запрос индекса, отдаем index.php
    location = / {
            root   /path/to/drupal;  # Again, replace this. 
            index  index.php;
    }

    # Обработка всего остального
    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;
            }

   }

   # Локальная отдача статики, без записи в лог
   location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico)$ {
        access_log        off;
        expires           30d;
        root   /path/to/img;
   }

   # Редирект
   location ~ .php$ {
          fastcgi_pass   127.0.0.1:8888;  # By all means use a different server for the fcgi processes if you need to
          fastcgi_index  index.php;

          fastcgi_param  SCRIPT_FILENAME  /path/to/drupal$fastcgi_script_name;   # !! <--- Another path reference for you.
          fastcgi_param  QUERY_STRING     $query_string;
          fastcgi_param  REQUEST_METHOD   $request_method;
          fastcgi_param  CONTENT_TYPE     $content_type;
          fastcgi_param  CONTENT_LENGTH   $content_length;
  }


       location ~ ^/$ {
          if (-f /index.html){
            rewrite (.*) /index.html last;
          }
           proxy_pass  http://mongrel;
        }

        location / {
          if (!-f $request_filename.html) {
            proxy_pass  http://mongrel;
          }
          rewrite (.*) $1.html last;
        }

        location ~ .html {
           root /Users/ez/nginx/public;
        }

           location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov)$ {
          root /Users/ez/nginx/public;
        }

        location / {
            proxy_pass  http://mongrel;
            proxy_redirect     off;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }

location /blog/ {
      index index.php;
        if (-e $request_filename) {
          break;
        }
      rewrite ^/blog/(.+)$ /blog/index.php?q=$1 last;
    }

if ($host != 'example.com' ) {
    rewrite  ^/(.*)$  http://example.com/$1  permanent;
    proxy_set_header Host "example.com";
}

if ($http_user_agent ~ MSIE) {
    rewrite  ^(.*)$  /msie/$1  break;
}

if ($http_cookie ~* "id=([^;]+)(?:;|$)" ) {
    set  $id  $1;
}

if ($request_method = POST ) {
    return 405;
}

if (!-f $request_filename) {
    break;
    proxy_pass  http://127.0.0.1;
}

geo  $slow   {
        default          no;
        include          conf/geo.conf;
        127.0.0.0/24     us;
        127.0.0.1/32     ru;
        10.1.0.0/16      ru;
        192.168.1.0/24   uk;
}

if ($slow) {
    limit_rate  10k;
}

valid_referers   none  blocked  server_names
**.example.com  www.example.info/galleries/
                     ~\.google\. ;


if ($invalid_referer) {
    return   403;
}


Приммеры rewrite для Gallery2:

        location /v/ {
            rewrite ^/v/(.*)$/wp-gallery2.php?g2_view=core.ShowItem&g2_path=$1;
        }
        location /d/ {
        #    rewrite ^/d/([0-9]{1,20})-([0-9]{1,20})/(.*)$/gallery2/index.php?g2_view=core.DownloadItem&g2_itemId=$1&g2_serialNumber=$2&g2_fileName=$3;

            rewrite ^/d/([0-9]+)-([0-9]+)/(.*)$/gallery2/index.php?g2_view=core.DownloadItem&g2_itemId=$1&g2_serialNumber=$2&g2_fileName=$3;

        }

        location /rss/ {
            rewrite ^/rss/(.*)$/wp-gallery2.php?g2_view=rss.Render&g2_name=$1;
        }
        location /srss/ {
             rewrite ^/srss/(.*)$/wp-gallery2.php?g2_view=rss.Render&g2_name=$1;
        }
        location /c/add/ {
            rewrite ^([0-9]+).html(.*)$/wp-gallery2.php?g2_view=comment.AddComment&g2_itemId=$1;
        }

        location /c/view/ {
            rewrite ^/c/view/([0-9]+).html(.*)$/wp-gallery2.php?g2_view=comment.ShowAllComments&g2_itemId=$1;
        }

        location /admin/ {
            rewrite ^/admin/(.*)$ /wp-gallery2.php?g2_view=core.SiteAdmin;
        }
        location /gallery2/ {
            root /var/www/brainstorm/htdocs/;
            index  index.php index.html index.htm;
            location ~ /.ht {
                deny  all;
            }
            location /gallery2/images/{
                  root /var/www/brainstorm/htdocs/;
            }
            location /gallery2/core/ {
                root /var/www/brainstorm/htdocs/;
            }
            location /gallery2/modules/ {
                root /var/www/brainstorm/htdocs/;
            }
            rewrite ^/gallery2/v/(.*)$/gallery2/index.php?g2_view=core.ShowItem&g2_path=$1;
            rewrite ^/gallery2/d/([0-9]+)-([0-9]+)/(.*)$/gallery2/index.php?g2_view=core.DownloadItem&g2_itemId=$1&g2_serialNumber=$2&g2_fileName=$3;

            rewrite ^/gallery2/rss/(.*)$/gallery2/index.php?g2_view=rss.Render&g2_name=$1;
            rewrite ^/gallery2/srss/(.*)$/gallery2/index.php?g2_view=rss.SimpleRender&g2_itemId=$1;
            rewrite ^/gallery2/c/add/([0-9]+).html(.*)$/gallery2/index.php?g2_view=comment.AddComment&g2_itemId=$1;
            rewrite ^/gallery2/c/view/([0-9]+).html(.*)$/gallery2/index.php?g2_view=comment.ShowAllComments&g2_itemId=$1;
            rewrite ^/gallery2/admin/(.*)$/gallery2/index.php?g2_view=core.SiteAdmin;
            rewrite ^/gallery2/sitemap(.*)$/gallery2/index.php?g2_view=sitemap.Sitemap;
        }
        location / {
            root   /var/www/brainstorm/htdocs;
            index  index.php index.html index.htm;
            #wordpress bullshit
            if (!-e $request_filename ) {
                    rewrite ^(.*)$  /index.php;
            }
            rewrite ^/sitemap(.*)$/wp-gallery2.php?g2_view=sitemap.Sitemap;

Образец реврайтов для drupal:

location / {

            root   /path/to/drupal/install/doc/root;
            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;
            }

        }

user  www www;
worker_processes  5;
error_log  logs/error.log debug;
pid        logs/nginx.pid;
events {
        worker_connections  8192;
        use epoll; # linux only!
}
http {
    include       conf/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] $status '
                      '"$request" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  logs/access.log  main;
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    server_names_hash_bucket_size 128; # this seems to be required for vhosts
    server { # php/fastcgi
        listen       80;
        server_name  domain1.com www.domain1.com;
        access_log  logs/domain1.access.log  main;
        location / {
            root   html;
            index  index.html index.htm index.php;
        }
        location ~ \.php$ {
            include        /etc/nginx/fastcgi.conf;
            fastcgi_pass   127.0.0.1:1025;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name;
        }
    }
    server { # simple reverse-proxy
        listen       80;
        server_name  domain2.com www.domain2.com;
        access_log  logs/domain2.access.log  main;
        # serve static files
        location ~ ^/(images|javascript|js|css|flash|media|static)/  {
                root    /var/www/virtual/big.server.com/htdocs;
                expires 30d;
        }

        # pass requests for dynamic content to rails/turbogears/zope, et al
        location / {
            proxy_pass      http://127.0.0.1:8080;
            include         /etc/nginx/proxy.conf;
        }
    }
    upstream big_server_com {
        server 127.0.0.3:8000 weight=5;
        server 127.0.0.3:8001 weight=5;
        server 192.168.0.1:8000;
        server 192.168.0.1:8001;
    }
    server { # simple load balancing
        listen          80;
        server_name     big.server.com;
        access_log      logs/big.server.access.log main;
        location / {
                proxy_pass      http://big_server_com;
                include         /etc/nginx/proxy.conf;
        }
    }
}

user  www www;

worker_processes  2;

pid /var/run/nginx.pid;

#                          [ debug | info | notice | warn | error | crit ]

error_log  /var/log/nginx.error_log  info;

events {
    connections   2000;

    # use [ kqueue | rtsig | epoll | /dev/poll | select | poll ];
    use kqueue;
}

http {

    include       conf/mime.types;
    default_type  application/octet-stream;


    log_format main      '$remote_addr - $remote_user [$time_local] '
                         '"$request" $status $bytes_sent '
                         '"$http_referer" "$http_user_agent" '
                         '"$gzip_ratio"';

    log_format download  '$remote_addr - $remote_user [$time_local] '
                         '"$request" $status $bytes_sent '
                         '"$http_referer" "$http_user_agent" '
                         '"$http_range" "$sent_http_content_range"';

    client_header_timeout  3m;
    client_body_timeout    3m;
    send_timeout           3m;

    client_header_buffer_size    1k;
    large_client_header_buffers  4 4k;

    gzip on;
    gzip_min_length  1100;
    gzip_buffers     4 8k;
    gzip_types       text/plain;

    output_buffers   1 32k;
    postpone_output  1460;

    sendfile         on;
    tcp_nopush       on;
    tcp_nodelay      on;
    send_lowat       12000;

    keepalive_timeout  75 20;

    #lingering_time     30;
    #lingering_timeout  10;
    #reset_timedout_connection  on;


    server {
        listen        one.example.com;
        server_name   one.example.com  www.one.example.com;

        access_log   /var/log/nginx.access_log  main;

        location / {
            proxy_pass         http://127.0.0.1/;
            proxy_redirect     off;

            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            #proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;

            client_max_body_size       10m;
            client_body_buffer_size    128k;

            client_body_temp_path      /var/nginx/client_body_temp;

            proxy_connect_timeout      90;
            proxy_send_timeout         90;
            proxy_read_timeout         90;
            proxy_send_lowat           12000;

            proxy_buffer_size          4k;
            proxy_buffers              4 32k;
            proxy_busy_buffers_size    64k;
            proxy_temp_file_write_size 64k;

            proxy_temp_path            /var/nginx/proxy_temp;

            charset  koi8-r;
        }

        error_page  404  /404.html;

        location /404.html {
            root  /spool/www;

            charset         on;
            source_charset  koi8-r;
        }

        location /old_stuff/ {
            rewrite   ^/old_stuff/(.*)$  /new_stuff/$1  permanent;
        }

        location /download/ {

            valid_referers  none  blocked  server_names  *.example.com;

            if ($invalid_referer) {
                #rewrite   ^/   http://www.example.com/;
                return   403;
            }

            #rewrite_log  on;

            # rewrite /download/*/mp3/*.any_ext to /download/*/mp3/*.mp3
            rewrite ^/(download/.*)/mp3/(.*)\..*$
                    /$1/mp3/$2.mp3                   break;

            root         /spool/www;
            #autoindex    on;
            access_log   /var/log/nginx-download.access_log  download;
        }

        location ~* ^.+\.(jpg|jpeg|gif)$ {
            root         /spool/www;
            access_log   off;
            expires      30d;
        }
    }
}

worker_processes 20;
events {
       worker_connections  8192;
       use epoll;
}
http {
       ...
       limit_zone one $binary_remote_addr 10m;
       limit_conn one 64;
       limit_zone too $http_host 10m;
       upstream  apache0  {
           ip_hash;
...
       }
       server {
       ....

       location ~* ^(.+\.(php|html)|.*/)$ {
               proxy_pass              http://apache0;
               proxy_set_header        Host <ZZZ>;
               proxy_set_header        X-Forwarded-For  $proxy_add_x_forwarded_for;
               proxy_set_header        X-Real-IP  $remote_addr;
               index                   index.php index.html;
               limit_conn too 100;
       }
       location /  {
               root   /data/<ZZZ>/htdocs;
       }
       server {
       ...
               limit_conn too 200;
       ...
       }
}

Как ограничить число одновременных соединений по сетевой маске

limit_zone   one  $my_addr  32k;
server {
 if ($remote_addr ~ "^(\d+\.\d+\.\d+)") {
   set $my_addr $1;
 }
 limit_conn one 1;

Сеть класса С можно делать так:

http {

    perl_set  $cnet  '

         sub {
             my $r = shift;
             return pack "c3", split /\./, $r->remote_addr;
         }
    ';


    limit_zone   one  $cnet   10m;

Ещё вариант:

   if ($binary_remote_addr ~ "^(...)") {

Каким образом организовать копирование запросов на тестовый бэкэнд так чтобы ответ с него НЕ возвращался пользователю:

      location ~ \.php$ {

          set   $ouri  $uri;

          fastcgi ...

          post_action   /post;
      }

      location = post {
          fastcgi ...
          fastcgi_param  SCRIPT_FILENAME  /home/www/scripts/php$ouri;
      }
server {
    server_name   www.* ;

    root /home/default-site/www/;

    ...

    location = /favicon.ico {

        if ($http_host ~ ^www\.([^.]+)$) {
            set    $root /home/$1/$1.$2/www; }
            break;
            root   $root;
        }

        error_page  404  = @default;
    }

    location @default {
    }
location / {
        proxy_pass http://127.0.0.1:81;
    }

    location = /cache {
        proxy_set_header Nginx-Uri $request_uri;
        proxy_set_header Nginx-Host $host;
        proxy_pass http://127.0.0.1:81/cache.php;
    }

    location ~* \.(php)$ {
        root /tmp/cache;
        error_page 404 = /cache;
    }

memcached:

location =/ajax/SOME_URL.html {
   #без этого content_type кривой будет
   default_type    text/html;

   #идем в memcached
   #ключ в memcached '/ajax/SOME_URL.html'
   #если у запроса нужны аргументы надо не забыть их сохранить для случая 
memcached miss
   #через set      $ArgsCopy       $args;
   #и потом добавить их через rewrite в location /_backend_/
   memcached_pass  SOME_MEMCACHED_IP:SOME_MEMCACHED_PORT;

   #если в memcached не попали то через 404 error_page запрашиваем данные у 
backend
   #который нам их отдает и записывает итог в memcached
   error_page      404 = /_backend_/ajax/SOME_URL.html;
}

#внутренний URL для обработки случаем memcached miss на этот location
location /_backend_/ {
   internal;
   #идем на backend
   proxy_pass http://BACKEND_IP:BACKEND_PORT/;
}

Избавление от лишних FIN_WAIT_1:

send_timeout              30s;     # менять по вкусу
keepalive_timeout         75  20;
reset_timedout_connection on;

pf.conf

pass in quick proto tcp from any to $ext_if port 80 flags S/SA
  keep state (source-track rule, max-src-conn-rate 8/20, tcp.established 60, tcp.closing 5, 
  overload <bad_hosts> flush global)


Perl + FastCGI + nginx

Полноформатная статья: FastCGI-приложение на Perl

Примеры

  • Способ 1 - запустить mod_fastcgi на бакенде с apache и редиректить туда.
  • Способ 2 (оптимальный)- по аналогии с php, запустить через spawn-fcgi (из комплекта lighttpd) нужное число Perl процессов.
  • Способ 3 - запуск perl скрипта как fastcgi-сервера. Например (для паралелльного запуска нескольких обработчиков нужно использовать FCGI::ProcManager):

   #!/usr/bin/perl

   use strict;
   use FCGI;
   # use FCGI::ProcManager;


   # my $proc_manager = new FCGI::ProcManager({ n_processes => 2, die_timeout => 10 });

   my $socket = FCGI::OpenSocket( ":9000", 5 ); # 5 - разрем очереди запросов.
   my $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket );

   # В случае с ProcManager цикл обработки запросов будет выглядеть примерно так:
   # $proc_manager->pm_manage();
   # while (my $cgi = CGI::Fast->new()) { 
   #   $proc_manager->pm_pre_dispatch(); 
   #   # ... 
   #   $proc_manager->pm_post_dispatch();
   #}

   my $count;
   while( $request->Accept() >= 0 ) {
       print "Content-type: text/html\r\n\r\n";
       print ++$count;
   }
   FCGI::CloseSocket( $socket );

Настройка nginx

   location /cgi-bin/script.fcgi {
      fastcgi_pass localhost:9000;
      fastcgi_root /path/to/cgi-bin/script.fcgi;
  }

Пример с codemongers.com:

#!/usr/bin/perl

use FCGI;
#perl -MCPAN -e 'install FCGI'
use Socket;

#this keeps the program alive or something after exec'ing perl scripts
END() { } BEGIN() { }
*CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; }; eval q{exit}; if ($@) { exit unless $@ =~ /^fakeexit/; } ;

&main;



sub main {
        #$socket = FCGI::OpenSocket( ":3461", 10 ); #use IP sockets
        $socket = FCGI::OpenSocket( "/var/run/nginx/perl_cgi-dispatch.sock", 10 ); #use UNIX sockets - user running this script must have w access to the 'nginx' folder!!
        $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket );
        if ($request) { request_loop()};
            FCGI::CloseSocket( $socket );
}

sub request_loop {
        while( $request->Accept() >= 0 ) {
            
           #processing any STDIN input from WebServer (for CGI-POST actions)
           $stdin_passthrough ='';
           $req_len = 0 + $req_params{'CONTENT_LENGTH'};
           if (($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ){ 
                        while ($req_len) {
                            $stdin_passthrough .= getc(STDIN);
                            $req_len--;
                        }
            }

            #running the cgi app
            if ( (-x $req_params{SCRIPT_FILENAME}) &&  #can I execute this?
                 (-s $req_params{SCRIPT_FILENAME}) &&  #Is this file empty?
                 (-r $req_params{SCRIPT_FILENAME})     #can I read this file?
            ){
                foreach $key ( keys %req_params){
                   $ENV{$key} = $req_params{$key};
                }
                #http://perldoc.perl.org/perlipc.html#Safe-Pipe-Opens
                open $cgi_app, '-|', $req_params{SCRIPT_FILENAME}, $stdin_passthrough or print("Content-type: text/plain\r\n\r\n"); print "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !\n";
                if ($cgi_app) {print <$cgi_app>; close $cgi_app;}
            } 
            else {
                print("Content-type: text/plain\r\n\r\n");
                print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.\n";
            }

        }
}

http {
    root  /var/www/htdocs;
    index index.html;
    location ~ ^/cgi-bin/.*\.cgi$ {
        fastcgi_pass  unix:/var/run/nginx/perl_cgi-dispatch.sock;
        fastcgi_index index.cgi;
        fastcgi_param SCRIPT_FILENAME /var/www/cgi-bin$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 GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param SERVER_SOFTWARE    nginx;
        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 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;
    }
}    

Пример с kiev.pm.org

use FCGI;
use FCGI::ProcManager;
use CGI;
my $proc_manager = FCGI::ProcManager->new({ n_processes => 10 });
my $socket = FCGI::OpenSocket(":9000", 5);
my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket);
$proc_manager->pm_manage();
my $count = 0;
while($request->Accept() >= 0) {
$count++;
print <<TEXT;
Content-Type: text/html
<h1>hello</h1>
$count
<hr>
TEXT
    print "$_ = $ENV{$_}<br>\n" foreach sort keys %ENV;
    print "<hr>\n";
    my $query = CGI->new();
    print "$_ = ", $query->param($_), "<br>\n" foreach sort $query->param();
}
FCGI::CloseSocket($socket);

Разное