Роман Теличко

Заметки веб-разработчика/админа

Настройка nginx + php5-fpm под Linux/Debian

// | 21840 просмотров | 29 комментариев

Сегодня я расскажу как настроить связку nginx + php5-fpm под Debian.

Начнём с инсталляции nginx.
И тут же мы сталкиваемся с тем, какой именно пакет ставить, т.к. их существует аж три:

  • nginx-light
  • nginx-full
  • nginx-extras

Отличаются они только поставкой дополнительных модулей.
Вызовем описание пакета nginx-light

aptitude show nginx-light

aptitude покажет какие именно дополнительные модули входят в «лёгкую» версию nginx

STANDARD HTTP MODULES : Core, Access, Auth Basic, Auto Index, Charset, Empty GIF, FastCGI, 
                        Gzip, Headers, Index, Log, Map, Proxy, Rewrite, Upstream. 
OPTIONAL HTTP MODULES : Gzip Precompression, IPv6, SSL, Stub Status.  
THIRD PARTY MODULES   : Echo.

А теперь для сравнения выведем список модулей «расширенной» версии nginx

aptitude show nginx-extras
STANDARD HTTP MODULES : Core, Access, Auth Basic, Auto Index, Browser, Charset, Empty GIF, 
                        FastCGI, Geo, Gzip, Headers, Index, Limit Requests, Limit Zone, Log, 
                        Map, Memcached, Proxy, Referer, Rewrite, SCGI, Split Clients, SSI, 
                        Upstream, User ID, UWSGI.  
OPTIONAL HTTP MODULES : Addition, Debug, Embedded Perl, FLV, GeoIP, Gzip Precompression, 
                        Image Filter, IPv6, MP4, Random Index, Real IP, Secure Link, SSL, 
                        Stub Status, Substitution, WebDAV, XSLT. 
MAIL MODULES          : Mail Core, IMAP, POP3, SMTP, SSL. 
THIRD PARTY MODULES   : Auth PAM, Chunkin, DAV Ext, Echo, Embedded Lua, HttpHeadersMore, 
                        http push, Nginx Development Kit, Upload module, Upload Progress, 
                        Upstream Fair Queue.

Как видите, список модулей и дополнений впечатляет.
С их подробной конфигурацией вы можете ознакомиться здесь и здесь.
Я рекомендую ставить nginx-light, т.к. чем меньше будет доставлено пакетов, тем меньше памяти будет «кушать» ядро nginx. Но также необходимо учитывать нужные модули для работы.

Устанавливаем nginx

aptitude install nginx-full

После успешной инсталляции открываем главный конфигурационный файл /etc/nginx/nginx.conf и приводим его к следующему виду:

user                www-data    www-data;

worker_processes    8;    # указать текущее количество ядер процессора
worker_priority     -20;

pid /var/run/nginx.pid;

error_log  /var/log/nginx/error.log  warn;

events {
    worker_connections              1024;
    accept_mutex                    on;
    multi_accept                    on;
}

http {
    include         /etc/nginx/mime.types;
    default_type    application/octet-stream;

    reset_timedout_connection       on;
    server_tokens                   off;

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

    sendfile                        on;
    tcp_nopush                      on;
    tcp_nodelay                     on;

    keepalive_timeout  	            65;

    client_max_body_size            512m;

    server_names_hash_max_size      1024;
    server_names_hash_bucket_size   128;

    port_in_redirect                off;

    gzip                            on;
    gzip_vary                       on;
    gzip_min_length                 1024;
    gzip_buffers                    16 8k;
    gzip_comp_level                 5;
    gzip_http_version               1.0;
    gzip_proxied                    any;
    gzip_disable                    "msie6";
    gzip_types                      text/plain text/css application/x-javascript text/xml 
                                    application/xml application/xml+rss text/javascript 
                                    text/json;

    fastcgi_temp_path               /var/cache/nginx/temp/fastcgi;
    proxy_temp_path                 /var/cache/nginx/temp/proxy;

    charset                         utf-8;
    index                           index.php index.html index.htm;

    access_log                      off;
    error_log                       /dev/null;

    set_real_ip_from    	    1.2.3.4/32;  # указать "честный" IP сервера
    real_ip_header      	    X-Real-IP;

    include                         /etc/nginx/sites-enabled/*;
}

Создаём папки для хранения кэша nginx и выставляем на них правильные права

mkdir -p /var/cache/nginx/temp/fastcgi
mkdir -p /var/cache/nginx/temp/proxy
chown -R www-data:www-data /var/cache/nginx

Перейдём в папку /etc/nginx/sites-enabled. Сейчас там по умолчанию лежит только один файл, что является символической ссылкой на файл с таким же именем в папке /etc/nginx/sites-available. Почему символическая ссылка, а не файл? С символическими ссылками очень удобно работать в случае когда вам нужно убрать какой-то виртуальный хост из настроек ядра, но при этом не потерять его на будущее. Вы просто удаляете ссылку на файл из папки /etc/nginx/sites-enabled не удаляя реальный файл. Это очень удобно.

К конфигурации виртуального сервера nginx мы ещё вернёмся после установки php5-fpm.

Устанавливаем php5-fpm:

aptitude install php5-fpm

В главном файле конфигурации php5-fpm /etc/php5/fpm/php-fpm.conf нас всё устраивает по умолчанию.

[global]
pid = /var/run/php5-fpm.pid
error_log = /var/log/php5-fpm/error.log
log_level = warning
daemonize = yes
include=/etc/php5/fpm/pool.d/*.conf

Перейдём к конфигурации виртуальных пулов что лежат в папке /etc/php5/fpm/pool.d/.

Открываем созданный по умолчанию /etc/php5/fpm/pool.d/www.conf
Без комментариев результирующий конфиг должен выглядеть так:

[www]
listen = /var/run/php5-fpm.$pool.sock
listen.allowed_clients = 127.0.0.1
listen.owner = www-data
listen.group = www-data
user = www-data
group = www-data
pm = dynamic
pm.max_children = 24
pm.start_servers = 12
pm.min_spare_servers = 2
pm.max_spare_servers = 24
pm.max_requests = 100
request_terminate_timeout = 90s
request_slowlog_timeout = 5s
slowlog = /var/log/php5-fpm/slow.$pool.log
chdir = /
catch_workers_output = yes
php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php5-fpm/error.$pool.log
php_admin_flag[log_errors] = on

Обратите внимание что я использовал переменную $pool что будет заменена на текущее имя пула, что задано в квадратных скобках в самом начале. В нашем случаи это будет [www]

Создадим папку для логов php5-fpm

mkdir /var/log/php5-fpm && chown www-data:www-data /var/log/php5-fpm

Немного поправим настройки PHP.
Откроем файл /etc/php5/fpm/php.ini и изменим следующие директивы:

expose_php = Off
cgi.fix_pathinfo = 0
max_execution_time = 90

Запускаем php5-fpm

service php5-fpm restart

Если всё ОК, возвращаемся к конфигурации nginx.
Создадим файл виртуального хоста в /etc/nginx/sites-available/example.com со следующим содержанием:

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

    set 	            $main_host		'example.com';

    if ($host != $main_host) {
        rewrite             ^(.*)$              https://$main_host$1     permanent;
        break;
    }

    access_log              /var/log/nginx/example.com.access.log       main;
    error_log       	    /var/log/nginx/example.com.error.log;
    
    root                    /var/www/$main_host/www;
    index                   index.php;

    # favicon.ico conf
    location = /favicon.ico {
        try_files 	    /favicon.ico    @favicon_empty;
        expires	            7d;
        access_log          off;
        log_not_found       off;
    }

    location @favicon_empty {
        empty_gif;
        expires	            7d;
        access_log          off;
        log_not_found       off;
    }

    location ~* ^.+\.(ico|htm|html|txt|jpg|png|gif|css|js)$ {
        access_log          off;
        autoindex           off;
        expires             30d;
        add_header          Cache-Control       'public';
    }

    location / {
        try_files           $uri    $uri/    /index.php?$args;
    }	

    location ~ \.php$ {
        include             /etc/nginx/conf.d/fastcgi_params.conf;

        fastcgi_param       SCRIPT_FILENAME  	/var/www/$main_host/www$fastcgi_script_name;
        fastcgi_param       DOCUMENT_ROOT       /var/www/$main_host/www;

        fastcgi_param       PHP_ADMIN_VALUE     upload_tmp_dir=/var/www/$main_host/tmp/upload;
        fastcgi_param       PHP_ADMIN_VALUE     session.save_path=/var/www/$main_host/tmp/sessions;
    }

    location ~ /\. {
	deny                all;
	access_log          off;
	log_not_found       off;
    }
}

В конфигурации мы использовали дополнительный конфиг, что не был описаны ранее.
Создадим его.
/etc/nginx/conf.d/fastcgi_params.conf

fastcgi_pass    unix:/var/run/php5-fpm.www.sock;
fastcgi_index   index.php;

fastcgi_split_path_info 		^(.+\.php)(/.+)$;

fastcgi_param   PATH_INFO        	$fastcgi_path_info;

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	SERVER_PROTOCOL		$server_protocol;

fastcgi_param  	SCRIPT_URI         	$scheme://$host$request_uri;

fastcgi_param	GATEWAY_INTERFACE	CGI/1.1;
fastcgi_param	SERVER_SOFTWARE		nginx;

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   Host                    $host;
fastcgi_param   HTTP_X_REAL_IP          $remote_addr;
fastcgi_param   HTTP_X_FORWARDED_FOR	$remote_addr;

fastcgi_param   Range                   "";
fastcgi_param   Request-Range           "";

fastcgi_buffer_size                     128k;
fastcgi_buffers                         4       256k;
fastcgi_busy_buffers_size               256k;
fastcgi_temp_file_write_size            256k;

fastcgi_connect_timeout                 600;
fastcgi_send_timeout                    600;
fastcgi_read_timeout                    600;

Обратите внимание что в параметре fastcgi_pass я указал путь к сокету php5-fpm пула www как unix:/var/run/php5-fpm.www.sock.

Теперь создадим символическую ссылку на созданный нами только что виртуальный хост, чтобы nginx его «увидел»

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com

Проверяем (тестируем) конфигурации nginx

nginx -t

Результатом должно быть следующее:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Теперь мы можем запустить nginx

service nginx restart

Если всё ОК — продолжаем дальше.

Создадим иерархию директорий нашего тестового проекта.

mkdir -p /var/www/example.com/www
mkdir -p /var/www/example.com/tmp/upload
mkdir -p /var/www/example.com/tmp/sessions
chown -R www-data:www-data /var/www/example.com

И создадим index.php файл с проверкой работы php5-fpm

echo " /var/www/example.com/www/index.php

Отроем в браузере. И если вы увидели вывод функции phpinfo(), то вы всё сделали правильно.

Это всё.
Удачи!

P.S. Не забудьте про logrotate для того, чтобы ваши логи не заняли в один прекрасный момент всё дисковое пространство, прекратив тем самым работу всех сайтов на этом веб-сервере.

  • Евгений

    Nginx ругается что данный параметр не может быть сдесь

    fastcgi_pass unix:/var/run/php5-fpm.www.sock;
    В чем ошибка в вашем коде?

    • Ошибки в коде нет. Я думаю что есть ошибка у вас со вставкой.
      Вы точно вставляете /etc/nginx/conf.d/fastcgi_params.conf в location ~ .php$

      • У меня тоже выскакивала данная ошибка:
        Restarting nginx: nginx: [emerg] «fastcgi_pass» directive is not allowed here in /etc/nginx/conf.d/fastcgi_params.conf:1
        nginx: configuration file /etc/nginx/nginx.conf test failed

        Пока я не закомментировал этот парамерт #include /etc/nginx/conf.d/*.conf; в конфигурационном файле /etc/nginx/nginx.conf

        • Всё верно. Такого параметра в /etc/nginx/nginx.conf и не должно быть. Впрочем, в моём конфиге его и нет.

  • rudi

    все сработало с первого раза, спасибо.

  • В вашем коде действительно какая-то ошибка. Сделал все в точности по описанному, однако при перезагрузке service php5-fpm выдает ошибку: service php5-fpm restart
    [FAIL] Restarting PHP5 FastCGI Process Manager: php5-fpm failed!
    вот лог:
    [05-Oct-2014 22:12:13] ALERT: [pool www] user has not been defined
    [05-Oct-2014 22:12:13] ERROR: failed to post process the configuration
    [05-Oct-2014 22:12:13] ERROR: FPM initialization failed

    В чем может быть проблема?

    • В конфиге действительно не хватало
      user = www-data
      group = www-data
      Уже добавил.

      • Роман, у меня изначально в конфигурационном файле php5-fpm /etc/php5/fpm/php-fpm.conf выдавало ошибки, пока я не закомментировал эти строки:
        set_real_ip_from 1.2.3.4/32; # указать «честный» IP сервера
        real_ip_header X-Real-IP;

        теперь выдает ошибку и по этой строке:

        error_log /dev/null;

        И еще, подскажите пожалуйста какие модули (из перечисленных) дополнительно лучше установить?
        * php5-cli php5-common php5-sqlite php5-suhosin php5-cgi php5-fpm php5-gd — некоторые нужные для работы движков модули php.
        * php5-apc memcached php5-memcached — ускорители работы веб сервера.

        • Я вот как-то не понял при чём тут конфигурационный файл php5-fpm /etc/php5/fpm/php-fpm.conf к конфигурационному файлу nginx /etc/nginx/nginx.conf, где и должны находиться эти строки?
          А какую вы версию ставили nginx? nginx-light?

          По-поводу того, какие именно пакеты ставить для php5-fpm мне сложно сказать, т.к. я не знаю какие компоненты php5 вам нужны будут для работы вашего приложения.

          • Да, я установил — nginx-light

            • Эту версию я рекоммендовал, но в инструкции описан конфиг для nginx-full. Видимо из-за этого он и ругается, т.к. в nginx-light много чего нет.

              • В любом случае, огромное спасибо за статью. Я настроил свой VDS и все работает. Сейчас посмотрю какие модули необходимо доустановить.

                p.s.

                Кстати, вам бы не помешало дополнить статью установкой и настройкой mysql + phpmyadmin, чтобы статья помогала настроить полноценный вебхостинг.

                • Спасибо за идею, но правда MySQL ненавижу с детства 🙂

                  • Как бы плохо вы не относились к MySQL, но на этой базе работает очень много CMS, таких как: WordPress, PHP-Fusion, NetCat, Joomla, UMI.CMS, Drupal и другие…

                    Поэтому, продвинутым пользователям необходимо будет настраивать свои сервера с MySQL + phpmyadmin.

  • Роман, подскажите пожалуйста, что необходимо сделать чтобы заработал виртуальный хостинг? Я попробовал настроить несколько сайтов, так вот всегда открывается только первый. При попытки открыть второй происходит переадресация на первый)))

    • Т.е. вы создали несколько конфигов в /etc/nginx/sites-available с разными именами и создали симлинки в /etc/nginx/sites-enabled, перезагрузили nginx, а всё-равно открывается только один сайт?

      • Да, перезагрузил nginx, почистил кеш браузера, теперь выдается ошибка: 403 Forbidden

        • Это права в www-папку не те

          • Делал все как по «учебнику» написано)))

            • Т.е. этого файла там нет?

              /var/www/example.com/www/index.php

              • В папке я разместил тестовый index.html, но он почему-то не отрабатывался, выдавалась ошибка: 403 Forbidden. Заменил файл на index.php и все заработало!

                Сейчас вот разбираюсь, почему index.html не захотел работать..

                • Потому-что в конфиге nginx’a для этого сервера написано
                  index index.php;

                  • Так у нас же прописано — index index.php index.html index.htm; файлы с расширением php работают, а вот с html проблемы…

                    Насколько я понимаю это последовательность исполняемых файлов, если не найдется первый «index.php», то будет искаться второй, потом третий. Правильно?

                    • Эта настройка глобальна, но её можно сменить для каждого сервера/локэйшена, как у нас и просходит.

  • Здравствуйте Роман,
    у меня возник такой вопрос, вы тестировали nginx + php5-fpm в данной конфигурации на производительность и отказоустойчивость на серверах с высокой нагрузкой и большим количеством сайтов ?

    • Конечно 🙂

  • скажите а зачем отключать access_log и error_log в nginx.conf?

    • В целях производительности или там, где в их сборе нет смысла (например лог доступа к статическим ресурсам).

      • ясно, спасибо