Настраиваем Nginx + Php-fpm на Debian

Опубликовано admin - ср, 04/11/2012 - 20:02

В предыдущей статье Настройка веб-сервера Nginx на Debian как front-end к Apache мы настроили Nginx для обработки статических запросов и Apache для обработки динамических запросов. Теперь попробуем рассмотреть альтернативную конфигурацию сервера для Drupal сайта заменив Apache на Php-fpm. Принцип работы нашего веб-сервера будет следующим:

  1. Nginx принимает запросы от клиентов
  2. Статику nginx отдает самостоятельно
  3. Динамические запросы Nginx передает на php-fpm, который запущен локально на порту 9000.

Первоначальная установка всех компонентов

Обновляем локальный кэш пакетов:

apt-get update

Устанавливаем все компоненты:

 apt-get install nginx php7.0-fpm mysql-server php7.0-gd php7.0-mysql

Настройка nginx

Конфигурация nginx выглядит следующим образом:

server {
  server_name www.drupaladmin-example.com;
  rewrite (.*) http://drupaladmin-example.com$1;
}

server {
   listen 80; 
   server_name drupaladmin-example.com;
   root /home/webmaster/domains/drupaladmin-example.com/html;
   index index.php;

   access_log /home/webmaster/domains/drupaladmin-example.com/logs/nginx_access.log;
   error_log /home/webmaster/domains/drupaladmin-example.com/logs/nginx_error.log;
 
   if ($bad_bot) {
      return 444;
   }
   if ($bad_referer) {  
      return 444;  
   }
   if ($not_allowed_method) {
      return 405;
   }
   fastcgi_keep_conn on;
   add_header X-XSS-Protection '1; mode=block';
   add_header X-Frame-Options deny;
   add_header X-Content-Options nosniff;
   
   location ~* ^/.well-known/ { 
      allow all;  
   }
   location / {
      location ~* /system/files/ {
         include /etc/nginx/fastcgi_drupal.conf; 
         fastcgi_pass 127.0.0.1:9000;
         log_not_found off; 
      }
      location ~*  /sites/default/files/private/ { 
         internal;  
      }
      location ~* /imagecache/ {
         expires 30d;
         try_files $uri @drupal; 
      }
      location ~*  /sites/default/files/styles/ {
         expires 30d;
         try_files $uri @drupal;
      }
      location ~* /sites/.+/files/.+\.txt {
         expires 30d;
         tcp_nodelay off;
         open_file_cache max=3000 inactive=120s;
         open_file_cache_valid 45s;
         open_file_cache_min_uses 2;
         open_file_cache_errors off;        
      }
      location ~* /sites/.+/files/advagg_css/ {
         expires max;
         add_header X-XSS-Protection '1; mode=block';
         add_header X-Frame-Options deny;
         add_header X-Content-Options nosniff;
         add_header ETag '';
         add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT';
         add_header Accept-Ranges '';
         location ~* /sites/.*/files/advagg_css/css[_[:alnum:]]+\.css$ { 
            try_files $uri @drupal;          
         } 
      }
      location ~* /sites/.+/files/advagg_js/ {
         expires max;
         add_header X-XSS-Protection '1; mode=block';
         add_header X-Frame-Options deny;
         add_header X-Content-Options nosniff;         
         add_header ETag '';
         add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT';
         add_header Accept-Ranges '';
         location ~* /sites/.*/files/advagg_js/js[_[:alnum:]]+\.js$ { 
            try_files $uri @drupal;  
         } 
      }
      location ~* /admin/reports/hacked/.+/diff/ { 
         try_files $uri @drupal;  
      }
      location ~* ^.+\.xml {  
         try_files $uri @drupal;  
      }
      location ~* ^.+\.(?:css|ico|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff2?|svg|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf|woff|ogg|mp4|wav|aac|skin)$ {
         expires 30d;
         tcp_nodelay off;
         open_file_cache max=3000 inactive=120s;
         open_file_cache_valid 45s;
         open_file_cache_min_uses 2;
         open_file_cache_errors off;
         location ~* ^.+\.svgz$ {
            gzip off;
            add_header X-XSS-Protection '1; mode=block'; 
            add_header X-Frame-Options deny;    
            add_header X-Content-Options nosniff;             
            add_header Content-Encoding gzip;  
         } 
      }
      location ~* ^.+\.(?:pdf|pptx?)$ {
         expires 30d;
         tcp_nodelay off; 
      }
      location ~* ^(?:.+\.(?:htaccess|make|txt|yml|twig|engine|inc|info|install|module|profile|po|pot|sh|.*sql|test|theme|tpl(?:\.php)?|xtmpl)|code-style\.pl|/Entries.*|/Repository|/Root|/Tag|/Template|composer\.(json|lock))$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ {  
         deny all;   
      }
      try_files $uri @drupal;
   }
   location @drupal {
       include /etc/nginx/fastcgi_drupal.conf;
       fastcgi_pass 127.0.0.1:9000; 
   }
   location = /authorize.php {
       fastcgi_pass 127.0.0.1:9000; 
   }
   location = /cron.php {
       fastcgi_pass 127.0.0.1:9000;
   }
   location = /index.php {
       fastcgi_pass 127.0.0.1:9000;
   }
   location = /install.php {
       fastcgi_pass 127.0.0.1:9000;
   }
   location = /update.php { 
       fastcgi_pass 127.0.0.1:9000;
   }
   location = /xmlrpc.php {
       fastcgi_pass 127.0.0.1:9000;
   }
   location ^~ /.bzr { 
      return 404; 
   }
   location ^~ /.git { 
      return 404; 
   }
   location ^~ /.hg { 
      return 404; 
   }
   location ^~ /.svn {
      return 404;
   }
   location ^~ /.cvs { 
      return 404;
   }
   location ^~ /patches { 
      return 404; 
   }
   location ^~ /config {   
      return 404; 
   }
   location ^~ /backup { 
      return 404;
   }
   location = /robots.txt { 
      try_files $uri @drupal;  
    }
   location = /favicon.ico {
      expires 30d;
      try_files /favicon.ico @empty; 
   }
   location @empty {
      expires 30d;
      empty_gif; 
   }
   location ~* ^.+\.php$ { 
      return 404; 
   }
}

Создаем файл конфигурации Nginx  /etc/nginx/conf.d/nginx_additional.conf с дополнительными настройками для определения переменных:

map $http_user_agent $bad_bot {
    default 0;
    ~*^Lynx 0; # Let Lynx go through
    libwww-perl                      1;
    ~(?i)(httrack|htmlparser|libwww) 1;
}

map $http_referer $bad_referer {
    default 0;
    ~(?i)(adult|babes|click|diamond|forsale|girl|jewelry|love|nudit|organic|poker|porn|poweroversoftware|sex|teen|webcam|zippo|casino|replica) 1;
}

map $request_method $not_allowed_method {
    default 1;
    GET 0;
    HEAD 0;
    POST 0;
}

Теперь создадим файл /etc/nginx/fastcgi_drupal.conf с параметрами fastcgi для Drupal:

## 1. Parameters.
fastcgi_param QUERY_STRING q=$uri&$args;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME /index.php;
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 GATEWAY_INTERFACE CGI/1.1;
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 REDIRECT_STATUS 200;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param HTTPS $fastcgi_https if_not_empty;

## 2. Nginx FCGI specific directives.
fastcgi_buffers 256 4k;
fastcgi_intercept_errors on;
fastcgi_read_timeout 14400;
fastcgi_index index.php;
fastcgi_hide_header 'X-Drupal-Cache';
fastcgi_hide_header 'X-Generator';

Файл параметров /etc/nginx/fastcgi_params оставим без изменений.

Перезапускаем Nginx

/etc/init.d/nginx restart

Настройка php-fpm

В файле /etc/php5/fpm/php-fpm.conf устанавливаем следующие параметры:

syslog.facility = daemon
syslog.ident = php-fpm
log_level = error
emergency_restart_interval = 12h
events.mechanism = epoll

Теперь переходим к настройке пула /etc/php5/fpm/pool.d/www.conf

user = www-data
group = www-data
pm = dynamic
pm.max_requests = 1500
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1 
pm.max_spare_servers = 3
pm.process_idle_timeout = 10s
security.limit_extensions = .php
catch_workers_output = yes
listen = 127.0.0.1:9000
php_admin_value[error_log] = /home/webmaster/domains/drupaladmin-example.com/logs/fpm-php.www.error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 256M
php_admin_value[upload_tmp_dir] = "/home/webmaster/domains/tmp"
php_admin_value[session.save_path] = "/home/webmaster/domains/tmp"

Перезапускаем php-fpm

/etc/init.d/php7.0-fpm restart

В файле конфигурации /etc/php5/fpm/php-fpm.conf достаточно подробно описаны все параметры. Также для более подробного описания можно обратиться к официальной документации.

На этом настройка завершена и Drupal сайт будет работать без использования веб-сервера Аpache.

Теги

Читал, что связка Nginx + Php-fpm + Apc выигрышная только на тарифах с ограниченной оперативной памятью , если памяти хватает то Nginx + Apache + mod_php + Apc будет тоже хорошим решением т.е. не уступающим.

В чем плюс в остальном Php-fpm перед апачем ?

Я вижу разницу в том, что Nginx + php-fpm + APC будет быстрее, чем Nginx + Apache + mod_php + APC, потому что не используется дополнительное звено Apache, который на каждом запросе будет тратить время на VirtualHost, на .htaccess, до того как обработать динамический запрос.
В целом для повышения производительности можно применять затюненный Apache в режиме Worker MPM. Кстати неплохо было бы сравнить на одном и том же железе Apache Worker MPM + mod_php vs Nginx + php-fpm. На abmysite.com пока что нет такого теста. Обязательно добавим.

Да, вижу используется Nginx + Apache. Подозреваю, что это особенность хостинга, где они сейчас размещаются. Я так понимаю этот хостинг использует именно связку Nginx + Apache в продакшн.
Думаю, что нужно проводить тесты разных конфигураций на одном и том же железе, чтобы найти оптимальную конфигурацию. Видимо drupal.ru нашел эту конфигурацию на этом хостинге.

Привет!
А друпал ни как не увидит что включен APC? Отчет статусов в Друпале выводит такую запись

Upload progress Not enabled
Your server is not capable of displaying file upload progress. File upload progress requires an Apache server running PHP with mod_php.

С апачем он вроде писал что включен APC.

Добрый день! У меня nginx выдает 502 ошибку :( В логах

[error] 13413#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: мой ip адрес, server: somehost.kz, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "somehost.kz"

нужно через ps aux проверить что php-fpm запущен, и netstat -an глянуть что порт 9000 занят. Также посмотреть конфиг php-fpm на каком порту он запущен.

Судя по всему, он не запущен. При запуске ничего не сообщает, но статус показывает failed.
В логах php-fpm ничего нет :(

[09-Aug-2013 12:00:54] NOTICE: fpm is running, pid 8601
[09-Aug-2013 12:00:54] NOTICE: ready to handle connections
[09-Aug-2013 12:00:57] NOTICE: configuration file /etc/php5/fpm/php-fpm.conf test is successful

[09-Aug-2013 12:00:57] NOTICE: Finishing ...
[09-Aug-2013 12:00:57] NOTICE: exiting, bye-bye!
[09-Aug-2013 12:00:57] NOTICE: fpm is running, pid 9301
[09-Aug-2013 12:00:57] NOTICE: ready to handle connections
[09-Aug-2013 12:21:48] NOTICE: Finishing ...
[09-Aug-2013 12:21:48] NOTICE: exiting, bye-bye!

php-fpm.conf:
[global]
pid = /var/run/php5-fpm.pid
error_log = /var/log/php5-fpm.log
syslog.facility = daemon
syslog.ident = php-fpm
log_level = error
emergency_restart_interval = 12h
events.mechanism = epoll
include=/etc/php5/fpm/pool.d/*.conf

www.conf:
[www]
user = dark
group = dark
listen = /var/run/php5-fpm.sock
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 1500
max_execution_time = 30
request_terminate_timeout = 30
chdir = /
security.limit_extensions = .php
php_admin_value[error_log] = /home/dark/domains/somehost.kz/logs/fpm-php.www.error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 256M
php_admin_value[open_basedir] = "/home/dark:."
php_admin_value[upload_tmp_dir] = "/home/dark/tmp"
php_admin_value[session.save_path] = "/home/dark/tmp"

Пробовал ставить в www.conf "listen = 127.0.0.1:9000", но это не помогло

Вы настроили php-fpm на сокете listen = /var/run/php5-fpm.soc, а из nginx подключаетесь по порту. Нужно вместо сокета прописать 127.0.0.1:9000.

Я пробовал ставить вместо сокета айпишник, не помогло:
2013/08/14 12:25:59 [error] 4444#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: ip-адрес, server: somehost.kz, request$
P.S: отключить бы еще каптчу для авторизованных пользователей

Добавить комментарий

Filtered HTML

  • Допустимые HTML-теги: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd>
  • Строки и абзацы переносятся автоматически.
  • Web page addresses and email addresses turn into links automatically.