Системное и сетевое администрирование
0,3
рейтинг
30 декабря 2012 в 10:57

Администрирование → Nginx+php-fpm+perl под Debian Squeeze tutorial


Для чего эта заметка, ведь похожих уже полно? Если кратко, то когда я взялся настроить связку пришлось перечитать огромное количество документации и разных статей, все сразу и в одном месте найти не получилось. Данная статья попытка систематизировать накопленные знания, а также максимально подробная помощь тем, кто только начинает осваивать nginx.

В качестве теста решил перевести все свои сайты на nginx, до этого все работало на Apache из состава ZendServerCE. Интересно было пробовать насколько сложно будет полностью переехать на новый для себя веб-сервер, ведь используется несколько CMS (DLE, Wordpress, самописныеCMS).

Задачи:
  • базовая работа web сервера — обработка html;
  • запуск php скриптов;
  • корректная работа phpmyadmin для всех сайтов на сервере;
  • запуск cgi и pl скриптов;
  • использование кеширования и подбор оптимальных параметров для увеличения производительности.


Имеем свежеустановленный сервер Debian 6 в минимальной установке из netinstall. И так поехали.

1. Подготовительные работы


Добавляем необходимые в дальнейшем репозитории в /etc/apt/sources.list
deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free
deb http://www.deb-multimedia.org stable main non-free
deb http://packages.dotdeb.org squeeze all
deb-src http://packages.dotdeb.org squeeze all
deb http://nginx.org/packages/debian/ squeeze nginx
deb-src http://nginx.org/packages/debian/ squeeze nginx

Устанавливаем ключи
apt-get update && apt-get install deb-multimedia-keyring
wget http://www.dotdeb.org/dotdeb.gpg -O- |apt-key add -
gpg --keyserver hkp://keys.gnupg.net --recv-keys ABF5BD827BD9BF62
gpg -a --export 7BD9BF62 | apt-key add -

Обновляемся.
apt-get update && apt-get upgrade

Из бэкпортов ставим свежее ядро (по желанию)
apt-get install -t squeeze-backports linux-image-3.2.0-0.bpo.3-amd64

Перезагружаемся
reboot

Ставим необходимые пакеты
apt-get install nginx php5-cli php5-common sqlite php5-sqlite php5-suhosin php5-cgi php5-fpm\
fcgiwrap mysql-server php5-mysql php5-gd php5-apc memcached php5-memcached siege


  • nginx — сам веб сервер.
  • php5-cli php5-common php5-sqlite php5-suhosin php5-cgi php5-fpm php5-gd — некоторые нужные для работы движков модули php.
  • mysql-server php5-mysql — база данных mysql и связь ее с php.
  • fcgiwrap — обработка perl скриптов.
  • php5-apc memcached php5-memcached — ускорители работы веб сервера.
  • siege — утилита для тестирования скорости работы сайта, понадобится при подборе количества обработчиков.

Создаем каталог для сайтов и логов, также устанавливаем права
mkdir /var/www
mkdir /var/log/nginx/
chmod -R a-rwx,u+rwX,g+rX /var/www && chown www-data:www-data -R /var/www 
#Дирректория для кеша 
mkdir /tmp/fcgi-cache/
chown www-data:www-data -R /tmp/fcgi-cache/

2. Настройка Nginx


Несмотря на то, что конфигурация Nginx состоит из нескольких файлов, сам nginx начинает читать единственный файл: /etc/nginx/nginx.conf, все остальные подключаются директивой include.

Редактируем /etc/nginx/nginx.conf
# Пользователь с правами которого работает nginx
user www-data;
# Рекомендуется устанавливать по числу ядер
worker_processes 4;
pid /var/run/nginx.pid;
worker_rlimit_nofile 8192;
events {
# Максимальное число подключений к серверу на один worker-процесс
worker_connections 1024;
# Эффективный метод обработки соединений, используемый в Linux 2.6+
use epoll;
}
http {
##
# Базовые настройки
	#Организовываем кеш для FastCGI сервера, я использую раздел в ram
	fastcgi_cache_path /tmp/fcgi-cache/ levels=1:2   keys_zone=one:10m;
	#Используем sendfile, но осторожно, если надо отдавать большие файлы, 
	#то sendfile случается вредит
	sendfile on;
	#Расширяем буфера отдачи
	#output_buffers   32 512k;
	#Ограничиваем размер сегмента отправляемой за одну
	#блокируемую отдачу
	sendfile_max_chunk  128k;
	#Буфер отдачи которы используется для обрабатываемых данных
	postpone_output  1460;
	#Размер хеша для доменных имен.
	server_names_hash_bucket_size 64;
	#Размер данных принемаемых post запросом
	client_max_body_size 15m;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # При ошибках не говорим врагу версию nginx
        server_tokens off;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
##
# Настройка логов
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
##
        
# Настройки сжатия
	gzip on;
	gzip_disable "msie6";
	ssi on;
##

# Настройка виртуальных доменов
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}


Настройка виртуального домена 

Создаем директории для доменов и шаблонов
mkdir /etc/nginx/sites-enabled
mkdir /etc/nginx/sites-available
mkdir /etc/nginx/templates
mkdir /var/www/htdocs


Настройка шаблонов. 

Общий шаблон
nano  /etc/nginx/templates/default
# Типовые настройки общие для всех доменов (если не захочется экзотики)
##
index index.html index.php;
# Реализуем "красивые" ссылки для Drupal (и для ряда других CMS)
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}

# Закрываем доступ к файлами .htaccess и .htpassword
location ~ /\.ht {
deny all;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}


Шаблон подключения обработки php
nano  /etc/nginx/templates/php
# Передаём обработку PHP-скриптов PHP-FPM
location ~ \.php$ {
try_files $uri =404; 
#PHP-FPM слушает на Unix сокете
fastcgi_pass   unix:/tmp/wwwpool.sock;
#Использовать cache зона one
fastcgi_cache  one;
#Помещать страницу в кеш, после 3-х использований. Меньшее число вызвало у меня труднообъяснимые глюки
# на формах регистрации
fastcgi_cache_min_uses 3;
#Кешировать перечисленные ответы
fastcgi_cache_valid 200 301 302 304 5m;
#Формат ключа кеша - по этому ключу nginx находит правильную страничку
fastcgi_cache_key "$request_method|$host|$request_uri";
#Если не использовать эту опцию - то в форумах все будут сидеть под именем первого вошедшего на форум
# fastcgi_hide_header "Set-Cookie";
#Этот запрос заставит nginx кешировать все что проходит через него
# fastcgi_ignore_headers "Cache-Control" "Expires";
fastcgi_index  index.php;
#  fastcgi_intercept_errors on; # только на период тестирования
# Включаем параметры из /etc/nginx/fastcgi_param
include fastcgi_params;
# Путь к скрипту, который будет передан в php-fpm
fastcgi_param       SCRIPT_FILENAME  $document_root$fastcgi_script_name;
fastcgi_ignore_client_abort     off;
}


Шаблон подключения обработки Perl
nano  /etc/nginx/templates/perlcgi
#Все скрипты заканчивающиеся на pl и cgi
location ~ \.(pl|cgi)$
{
#Не сжимаем скрипты
gzip off;
try_files $uri =404;
#Передаем скрипты на обработку fcgiwrap
fastcgi_pass unix:/var/run/fcgiwrap.socket;
# Используем стандартные параметры
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_ignore_client_abort off;
}
#Замена апачевской ScriptAlias
location /cgi-bin/ {
gzip off;
try_files $uri =404;
root /var/www/;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_ignore_client_abort off;
}


Шаблон подключения phpmyadmin
nano  /etc/nginx/templates/phpmyadmin
location /phpmyadmin {
root /var/www/;
index index.php index.html index.htm;
location ~ ^/phpmyadmin/(.+\.php)$ {
try_files $uri =404;
root /var/www/;
fastcgi_pass unix:/tmp/wwwpool.sock;
#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 ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
root /var/www/;
}
}


Отключаем уязвимость forum.antichat.ru/thread222063-php-fpm.html
прописываем в /etc/php5/fpm/php.ini
cgi.fix_pathinfo=0


Создаем шаблон по умолчанию для своего домена:

nano /etc/nginx/sites-available/default
server {
# Папка с контентом сайта (удобно, когда совпадает с именем домена)
root /var/www/htdocs/;
# Настройка логов, каждому виртуальному домену - свой лог
access_log /var/log/nginx/default-access.log;
error_log /var/log/nginx/default-error.log;

# Подключаем все шаблоны для проверки, на реальных хостах будем использовать только нужные.
include /etc/nginx/templates/default;
include /etc/nginx/templates/php;
include /etc/nginx/templates/phpmyadmin;
include /etc/nginx/templates/perlcgi;

}


Создаем симлинк
ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/000-default

Удаляем стандартный default, если есть
 rm /etc/nginx/conf.d/default 

Применение новых параметров
service nginx reload


Если все верно, то nginx начинает работать с новой конфигурацией, если нет — работа продолжается со старой, рабочей конфигурацией.

Проверка работоспособности php.
Создадим файл test.php в корневом каталоге сайта (в нашем случае это /var/www/htdocs/) следующего содержания:
 <?php phpinfo(); ?> 

chmod 755 /var/www/htdocs/test.php && chown www-data:www-data /var/www/htdocs/test.php

После чего переходим в браузере IP/test.php, если все верно — получаем параметры php на сервере, после чего удаляем этот фаил для безопасности.

Проверка работоспособности Perl.
Создадим файл test.cgi в корневом каталоге сайта (в нашем случае это /var/www/htdocs/) следующего содержания:
#!/usr/bin/perl -w
print "Content-type: text/html\n\n";
print "<html><head><title>Hello World!! </title></head>\n";
print "<body><h1>Hello world</h1></body></html>\n";


chmod 755 /var/www/htdocs/test.cgi && chown www-data:www-data /var/www/htdocs/test.cgi

После чего переходим в браузере IP/test.cgi, если все верно — получаем «Hello world».

Если все работает, то на этом этапе мы имеем рабочий веб сервер с поддержкой php и perl скриптов, дальше опишу некоторые нюансы донастройки отдельных его частей.



.htaccess !


В Nginx нет никакого аналога апачевского .htaccess, поэтому если работа сайта требует его наличия, то придётся переписывать его содержание в соответствии с синтаксисом nginx в основную конфигурацию домена. В нашем конфиге .htaccess был заменён следующим блоком:
location / { try_files $uri $uri/ /index.php?q=$uri&$args; }

Для преобразования .htaccess в синтаксис nginx можно воспользоваться онлайн-конвертором, например этим

3. Настройка PHP-FPM


 
В Debian конфигурация PHP-FPM состоит из 2х частей: глобальной (/etc/php5/fpm/php-fpm.conf) и настройки пулов (/etc/php5/fpm/pool.d/*.conf). В данном примере глобальные настройки мы трогать не будем, а вот на настройке пулов остановимся чуть подробнее.

Пулы

Для начала разберёмся зачем нужны пулы. В случае разных требований сайтов к PHP-окружению (различные параметры php.ini, разное число обработчиков и т.д.) может потребоваться создание дополнительных пулов. Данная операция в PHP-FPM весьма тривиально:

Настройка каждого пула в Debian представлена своим файлом в каталоге /etc/php5/fpm/pool.d/. По умолчанию системе есть единственный пул «www» (файл: /etc/php5/fpm/pool.d/www.conf) именно его настройкой мы и займёмся.

Workers (обработчики)

Самая спорная часть в настройке пула, это количество обработчиков php-скриптов. На первый взгляд, кажется, что чем больше обработчиков, тем эффективней обрабатываются php-скрипты. Но это не так! Во-первых: большое число обработчиков расходует больше памяти (а для нашего сервера память весьма критичный ресурс), во-вторых: если обработчиков очень много и, так случилось, что все они реально заняты работой, то у сервера может просто не хватить ресурсов на другие задачи (даже есть вероятность, что подключение по SSH станет практически не возможным).

В идеале число обработчиков должно быть таким, что даже при стрессовой нагрузке LoadAvarage системы оставался в разумных пределах. Т.е. пусть лучше при высокой нагрузке пользователи периодически получают сообщения о недоступности сервиса (ошибка 502: Gateway timeout), чем полная недоступность сервера даже для администратора.

И так немного подредактируем стандартный пул nano /etc/php5/fpm/pool.d/www.conf
#Где будем слушать подключения, я предпочитаю сокеты, но если сервера разнесены, то прийдется использовать порт.
;listen = 127.0.0.1:9000
listen = /tmp/wwwpool.sock

# Выбираем динамический режим создания процессов, т.е.
# число запущенных процессов PHP-FPM будет зависеть от текущей нагрузки
pm = dynamic
 
# Максимальное количество дочерних процессов.
pm.max_children = 7
 
# Количество дочерних процессов, стартующих сразу при загрузке сервера. Т.к. время запуска каждого
# нового процесса отлично от нулевого, то выбираем значение больше 1, не смотря на экономию ресурсов
pm.start_servers = 3
 
# Минимальное чисто простаивающих процессов. Должен согласовываться по логике с предыдущими
# при экономии ресурсов будет удобно pm.start_servers = pm.min_spare_servers.
pm.min_spare_servers = 3
 
# Максимальное чисто простаивающих процессов. Естественно, что не более чем pm.max_children
# и не менее pm.min_spare_servers. Остальные будут выгружены.
pm.max_spare_servers = 4

# Если скрипт будет выполняться больше указанного времени, то отладочная информация по нему будет записана в файл "медленных" запросов
request_slowlog_timeout = 3s
 
# Определяет путь к файлу "медленных" запросов (обязательный параметр, в случае определения request_slowlog_timeout)
slowlog = /var/log/php-slow.log


Оптимальное число обработчиков зависит от ресурсов сервера, сложности php-скриптов, нагрузки, создаваемой на mysql-сервер и т.д. В любом случае оптимальное число обработчиков нужно подбирать на основе тестирования работы сайта. Методика тестирования неплохо описана тут, повторяться не буду.

Добавление пула

При увеличении числа обслуживаемых сайтов может понадобиться создание дополнительных пулов, для настройки различных параметров каждому сайту — своё. Данная операция в php-fpm, на наш взгляд, весьма тривиальна:
Нужно скопировать файл /etc/php5/fpm/pool.d/www.conf под новым именем (для примера назовём его newpool.conf)
Дать новому пулу имя: находим вверху нового файла строку [www] (имя первого пула) и меняем на [newpool]
Меняем адрес подключения к php-fpm (директива «listen»). Т.к. каждый адрес должен быть уникален, то нужно изменить:
listen = 127.0.0.1:9000

на
listen = 127.0.0.1:9001

Или, в случае использования unix-сокетов,
listen = /tmp/newpool.sock

Номера портов и путей к unix-сокетам во всех пулах должны быть разными!

Для применения параметров после изменения php.ini (для PHP-FPM полный путь к файлу выглядит так: /etc/php5/fpm/php.ini) или собственных настроек PHP-FPM требуется перезапуск сервиса
service php5-fpm restart


4. Установка phpmyadmin


Загрузим стабильную версию phpmyadmin с сайта www.phpmyadmin.net/home_page/downloads.php
wget http://dl.cihar.com/phpMyAdmin/master/phpMyAdmin-master-latest.tar.gz

Распакуем сразу в нужную дирректорию и дадим нужные права.
tar -xzf phpMyAdmin-master-latest.tar.gz -C /var/www/
mv /var/www/phpMyAdmin-master-версия /var/www/phpmyadmin
chown www-data: /var/www/phpmyadmin -R

Скопируем файл с примером конфигурации и приведем его к следующему виду (сгенерировать blowfish_secret можно здесь):
cp /var/www/phpmyadmin/config.sample.inc.php /var/www/phpmyadmin/config.inc.php
nano /var/www/phpmyadmin/config.inc.php


$cfg['blowfish_secret'] = ‘e%o$fd3}tC9[HxY_$zY+dxstdsZ[i*JG]#GHt]alv’
$cfg['Servers'][$i]['auth_type'] = ‘http’;
$cfg['Servers'][$i]['controluser'] = ‘pma’;
$cfg['Servers'][$i]['controlpass'] = ‘DZMkI4vZ1’; // Сгенерируйте свой пароль
$cfg['Servers'][$i]['pmadb'] = ‘phpmyadmin’;
$cfg['Servers'][$i]['bookmarktable'] = ‘pma_bookmark’;
$cfg['Servers'][$i]['relation'] = ‘pma_relation’;
$cfg['Servers'][$i]['table_info'] = ‘pma_table_info’;
$cfg['Servers'][$i]['table_coords'] = ‘pma_table_coords’;
$cfg['Servers'][$i]['pdf_pages'] = ‘pma_pdf_pages’;
$cfg['Servers'][$i]['column_info'] = ‘pma_column_info’;
$cfg['Servers'][$i]['history'] = ‘pma_history’;
$cfg['Servers'][$i]['tracking'] = ‘pma_tracking’;
$cfg['Servers'][$i]['designer_coords'] = ‘pma_designer_coords’;
$cfg['Servers'][$i]['userconfig'] = ‘pma_userconfig’;
$cfg['SuhosinDisableWarning'] = ‘true’;

Затем создаем базу данных и пользователя необходимые для работы phpMyAdmin:
mysqladmin -p create phpmyadmin
 mysql -p
 CREATE USER 'pma'@'localhost' IDENTIFIED BY 'DZMkI4vZ1';
 GRANT ALL ON phpmyadmin.* TO 'pma'@'localhost';
 exit;

и необходимые для работы таблицы при помощи скрипта create_tables.sql:
mysql -p phpmyadmin < /var/www/phpmyadmin/examples/create_tables.sql


Теперь при обращении к любому хосту, в конфигурацию которого включен шаблон /etc/nginx/templates/phpmyadmin мы имеем возможность запустить phpMyAdmin, перейдя по адресу _http://имя_хоста/phpmyadmin

При написании использованы материалы:
nginx.org/ru/docs
habrahabr.ru/post/65128
manualpages.pro/node/31
dklab.ru/chicken/nablas/56.html
linuxwork.org.ua/debian/ustanovka-oficialnoj-versii-phpmyadmin-s-vozmozhnostyu-obnovleniya-na-debian-6-0-squeeze
www.hilik.org.ua/tuning-nginx
Сергей Петриков @RicoX
карма
81,7
рейтинг 0,3
Системное и сетевое администрирование
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (66)

  • 0
    Подскажите мощность вашего сервера и сколько сайтов на нем крутится.
    • 0
      Сейчас это тестовый сервер, в перспективе, если не найду глюков в работе движков и устроит производительность на него переедет около 20 сайтов, все проекты одной компании, движки разные, в том числе на самописных cms (из-за них пока окончательно не переехал, тестирую все опции).
  • +7
    А все-таки похожих статей уже полно. И на Хабре в том числе.
    • +2
      Чтоб все и сразу я не нашел, вот мне понадобилась одновременная работа php и perl скриптов в рамках одного сайта, во всех туториалах, что попались либо то, либо другое. С phpmyadmin была отдельная песня. Это скорее заметка себе на будущее ну и может еще кому пригодится.
      • +1
        Заметка себе на будущее делается в evernote, а не в коллективном блоге.
        • 0
          Если больше никому статья будет не интересна — уберу в черновики, пусть хабраюзеры решат нужна она тут или нет.
          • +12
            Нужна. Оставьте, пожалуйста.
          • +1
            Шестидесяти людям (на данный момент) нужна
          • 0
            Спасибо, про Perl никак не мог найти более менее понятное объяснение)
      • –2
        У меня для подобных целей есть собственный блог, куда я записываю подобные штуки, дабы что-то не забыть. Кому надо — тот найдет. Хабр для более сложных и интересных вещей.
        • +4
          Буду рад прочесть ваши сложные и интересные статьи. Основной минус собственного блога, если конечно он не раскручен — возможность получения обратной связи. Может я вообще бред написал и в своем блоге об этом даже не узнаю.
          • –1
            Про бред никто не говорил — было сказано, что подобное уже публиковалось.
            А если пишете интересный и полезный материал — фидбек гарантирован везде.
    • 0
      Подскажите парочку, на Хабре.
  • +3
    # Директива уменьшает разрешение времени в рабочих процессах, за счёт чего уменьшается число системных вызовов gettimeofday().
    timer_resolution 100ms;

    Нет особого смысла, во всех современных ядрах/дистрибутивах gettimeofday работает не через системный вызов.

    #Организовываем кеш для FastCGI сервера, я использую раздел в ram
    fastcgi_cache_path /tmp/fcgi-cache/ levels=1:2 keys_zone=one:10m;

    10 мегабайт всего? Думаю, для продакшена надо будет увеличить :) Кстати, у вас сейчас в access.log записывается HIT/MISS?

    #Расширяем буфера отдачи
    output_buffers 32 512k;

    Зачем? Много лишней памяти?

    #Если не использовать эту опцию — то в форумах все будут сидеть под именем первого вошедшего на форум
    fastcgi_hide_header «Set-Cookie»;
    #Этот запрос заставит nginx кешировать все что проходит через него
    fastcgi_ignore_headers «Cache-Control» «Expires»;

    Очень странное сочетание. Сначала заставляете нгинкс кешировать страницы авторизации, которые куки выставляют, а потом тупо запрещаете установку кук. Пользователи не устанут каждый раз логиниться при заходе на сайт?
    • 0
      gettimeofday — убрал.
      10 — поставил пока для тестов работы кеша, потом конечно расширю, нет не записываются, включу, как поборю некоторые особенности одной из CMS, тогда полностью займусь тестированием именно кеширования.
      output_buffers 32 512k; — советуете уменьшить или не трогать?
      По поводу странного сочетания, а как лучше сделать?
      • 0
        output_buffers 32 512k; — почему 32 для начала?

        К тому же — обычно output_buffers используется для отдачи больших файлов.
  • 0
    Советую убрать output_buffers и fastcgi_hide_header вместе с fastcgi_ignore_headers, потом попробовать.
    Скорее всего для правильного кеширования надо будет попилить csm-ки.
    • 0
      Спасибо, поэкспериментирую.
  • 0
    Статью оставьте, но rocket-sience тут и вправду нет.

    > worker_rlimit_nofile
    ulimit поднимать не забывайте для www-data.
    • 0
      Если я правильно понял имелось в виду
      su - www-data
      $ ulimit -a
      time(seconds)        unlimited
      file(blocks)         unlimited
      data(kbytes)         unlimited
      stack(kbytes)        8192
      coredump(blocks)     0
      memory(kbytes)       unlimited
      locked memory(kbytes) 64
      process              unlimited
      nofiles              32000
      vmemory(kbytes)      unlimited
      locks                unlimited
      
      • 0
        ulimit -n смотрите.
        • +1
          Ну так он есть в выводе выше, вполне с запасом.
          nofiles 32000

          • –1
            Хм. А чего за ведро и procfs? Раньше ж оно open files звалось. Да и в stable до сих пор именно так.
            • 0
              Да давненько уже не так.
              cat /proc/version
              Linux version 3.2.0-0.bpo.3-686-pae (Debian 3.2.23-1~bpo60+2) (debian-kernel@lists.debian.org) (gcc version 4.4.5 (Debian 4.4.5-8) ) #1 SMP Thu Aug 23 08:21:41 UTC 2012
              

              Вот с другого сервера со стейблом
              su - www-data
              $ ulimit -n
              1024
              $ ulimit -a
              time(seconds)        unlimited
              file(blocks)         unlimited
              data(kbytes)         unlimited
              stack(kbytes)        8192
              coredump(blocks)     0
              memory(kbytes)       unlimited
              locked memory(kbytes) 64
              process              unlimited
              nofiles              1024
              vmemory(kbytes)      unlimited
              locks                unlimited
              $ cat /proc/version
              Linux version 2.6.32-5-amd64 (Debian 2.6.32-45) (dannf@debian.org) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 SMP Sun May 6 04:00:17 UTC 2012
              
              • 0
                Ох уж эти девелоперы ядра) Без объявления войны меняют)

                Но вообще речь была о том, что у вас в статье про это не упомянуто. А nginx не всегда поднимает их сам, лучше сразу в security.conf писать.
  • 0
    Сокеты не всегда хороши (на linux`ах):

    * http://forum.nginx.org/read.php?3,97959,99123#msg-99123
    * www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-websites.html

    Поэтому гуглим, что такое net.core.somaxconn и почему по дефолту мы будем иметь только 128 конкурентных коннектов. А особенно если мы юзаем только один дефолтный пул, то 502 будет частой гостьей.

    Также в php-fpm желательно добавить защиту от криворучия сторонних модулей: pm.max_requests (чтобы «перезагружаться» после стольки-то реквестов) & rlimit_files (лимиты на открытые файлы).
    @sее github.com/garex/puppet-module-nginx/commit/700cee70841b9781be77815aa38f4560c34041f7
    • 0
      За ссылку на багтреккер спасибо, nginx сам только осваиваю, тонкостей многих еще не знаю, информация очень полезна. Веб сервера далеко не самое приоритетное направление деятельности и не самое нагруженное, занимаюсь потихоньку когда есть время, вот выкроил время — решил разобраться с nginx. Как оптимально подобрать pm.max_requests и rlimit_files — снять статистику за неделю и увеличить максимум процентов на 30%?
      cat /proc/sys/net/core/somaxconn
      2048
      

      Стандартный тюнинг от DDoS делается на автомате, не стал углубляться в настройки tcp_syncookies, tcp_max_syn_backlog, tcp_synack_retries настройки фаирвола и прочее, все таки тема была немного другая.
      • –1
        Эт пример коммита из одного из модулей для папета.

        По поводу оптимальности — надо смотреть есть ли смысл вообще? Напр., если ничего не течёт, то можно и не делать этого.

        Я когда настраивал в одном месте, смотрел и видел, что php-fpm понаоткрывал кучу файлов, а закрыть их не судьба. Это можно lsof`ом посмотреть. Проблема была или в нём, или в одном из модулей php`шных. В общем подобная штука помогает просто делать «reset» и всё. Как грится — не работает? Перезагрузите компутер.

        Для более грамотных вариантов надо просто вручную всё собирать и ставить/выбирать версии, которые не текут или уже пофикшены.
        • 0
          Да думал все собрать вручную, но меня за прошлую статью запинали, что не из репозиториев ставил, решил на этот раз обойтись только собранными версиями софта. Поставил сервер на мониторинг, посмотрю по графикам как себя вести будет. Как начал разбирать для себ nginx, решил все записывать по горячим следам, по-этому конфиги могут быть где-то не оптимальны. Просто писать все, что настраивалось месяц назад и уже отлажено и работает часто бывает лень, да и не вспомнишь всех нюансов.
          • 0
            Пиналы идут боком — в результате должен быть качественный продукт. А ставить всё так или эдак — на это нам мозг даден.

            С т.з. удобства записывания/запоминания папеты/шефы удобны. Т.к. всё можно в одном месте держать и уже видеть по истории что когда и почему делалось.

            Можно даже не юзать спец-модулей — а всё в одном главном делать. Потом уже как опыт будет и рука набьется — перейти на модули. Но это опять не золотая птица щастья.
            • 0
              У меня столько серверов нет, чтоб с папетами/чефами заморачиваться, в основном роутингом занимаюсь, с железками все проще, конфиг перекинул — считай клон. Сервера — так побочный продукт в двойном экземпляре каждый только, когда время есть разбираю поглубже, вдруг работу сменить надумаю. Рука набьется как баги вылазить начнут, пока ровно — черт его знает куда копать.
              • 0
                Плюсы этих штук в том, что всё в одном месте + видно что когда менялось + всё не внутри реальной машинки.

                Даже для одной машинки.
                • 0
                  Все таки для одной машинки мне кажется это оверхед. Для отслеживания изменений есть и другие средства, например для дебиан использую etckeeper, в крайнем случае есть ежедневные бэкапы на бакуле. Не оспариваю плюсы этих штук, но главный минус их должны использовать все в компании. У меня был опыт внедрения шефа, пока на сервере сам еще удается делать рецепты и как-то следить, когда появляется необходимость отдать временно сервер (переключился на другую задачу, обслуживание текущей работоспособности передал в ТП) часть конфигов правится «по-быстрому» руками, часть в рецептах, часть не пойми как, понимаю что это проблема организации, регламента и прочего, но снова наступить на эти грабли пока не готов. Хотя может еще просто не дорос до необходимости «кукловодства».
  • –3
    Данная операция в php-fpm, на наш взгляд, весьма тривиальна:


    Скопировать файл, поправить в нём юзеров и порт — нетривиально? Эээ… Ну тогда пишите скрипты или используйте папеты/шефы.

    Напр., в модуле папета это можно сделать так:

    nginx::backend::php {"Another site":
        port        => 9001,
        try_files   => '$uri $uri/ $uri/index.html /index.php?url=$uri&$args',
        pool_user   => "www-data2",
        pool_group  => "www-data2",
      }
    


    И вручную или через пол-часа новый пул сам там будет.

    Да даже просто ручками — что сложного скопировать *.conf и поправить там 3 значения? Можно вообще заранее себе подготовить шаблон *.conf`а с только нужными значениями, который копи-пастить.

    Прям катарсис у меня от такого заявления :)
    • +3
      Ну все верно, тривиальна, останавливаться подробней не стал, я все понимаю праздники на носу, но где вы там прочли НЕ?
      • –3
        Упс… Точно праздники на носу. Я — сам себе злобная буратина :)
    • 0
      Можно еще юзать $pool:
      user = $pool
      group = $pool
      Если listen делается через сокет, то тоже прокатит
  • 0
    > Обнобляемся
    • 0
      Спасибо, исправлено.
  • 0
    Зачем на сервер устанавливать phpmyadmin? Для кого? Пользователям сайта и заказчику он не нужен. А разработчик всегда может пробросить туннель и работать с локальным pma.
    • 0
      Безусловно когда это хостинг, но тут собственный сервер, на собственной техплощадке на который тестово периодически ставятся разные движки, смотрятся, настраиваются, удаляются. Банальный пример, захотел один из сотрудников СТП установить движок одной игры, мне проще ему дать доступ к директории по фтп и пользователя в mysql и пусть ковыряет движок свой как хочет. Естественно что доступ не по имени phpmyadmin (дал стандартное для примера) и в правилах разрешен доступ только с внутреннего диапазона адресов, не суть, инструмент удобный, почему не поставить? Случаи разные бывают, мне удобней когда инструмент есть на сервере и я в дороге с планшета могу зайти при необходимости и глянуть что с базой, а не париться с заходом по ssh и наслаждаться печатанием команд в терминале на сенсорной клавиатуре планшетки, поверьте то еще удовольствие.
      • 0
        тестово периодически ставятся разные движки

        Вы нигде не написали про тестовый или dev-сервер. Безусловно, это совсем другой разговор, но статьи с хабра, обычно копипастятся один в один, не сильно задумываясь о том, что и зачем они устанавливают на серваке.
        • 0
          Не думал что важна специфика работы фирмы, всегда думал кому нужно — поставит, кому нет — не будет. (Тем более расписал как сделать отдельным шаблоном, чтоб включать только там, где это нужно) Может чтоб еще какие-либо вопросы исключить, мы ISP и вебсервера далеко не самый приоритетный род занятий, сайт свой развернуть, форум, пару движков личных блогов сотрудников, ERP, игровые движки, несколько параллельных тестовых проектов и все. До этого все крутилось на сборке ZendServerCE и вполне успешно вообще без особой доработки, nginx поставил лично для себя чтоб разобраться, пока перед праздниками по основному роду деятельности почти нет нагрузки.
  • –2
    dotdeb? Сразу отказать. Пробовал заюзать их несколько раз, постоянно возникали траблы.
    Просто подключаем testing репозиторий дебиана и имеем все, что есть в дотдебе без лишних проблем.

    в /etc/apt/sources.list:
    deb ftp.debian.org/debian/ testing main non-free contrib
    deb-src ftp.debian.org/debian/ testing main non-free contrib
    deb security.debian.org/ testing/updates main contrib non-free
    deb-src security.debian.org/ testing/updates main contrib non-free
    • +1
      На вкус и цвет, я готов закрыть глаза на нестабильность некоторых элементов при общей стабильности системы, тестинг часто собран со слишком новыми версиями либ и приходится тянуть пол системы. У меня пока проблем с дотдебом небыло, может не нарывался, зато с тестингом было предостаточно, каждое обновление как русская рулетка. Я с дотдеба беру только php и mysql, может что другое неудачно собирают. Если вдруг столкнуть или пересоберу сам или возьму альтернативу (для mysql например percona), а вот если глюк в тестинге, то только на бэкап откатываться.
  • 0
    Оптимальное число обработчиков зависит от ресурсов сервера, сложности php-скриптов, нагрузки, создаваемой на mysql-сервер и т.д. В любом случае оптимальное число обработчиков нужно подбирать на основе тестирования работы сайта. Методика тестирования неплохо описана тут, повторяться не буду.

    По ссылке что-то не то.
    • 0
      Все верно, может чуток сумбурно, попробую объяснить подробней.
      1) Строим карту сайта в xml (многие движки умеют или сами или с помощью плагинов)
      2) С помощью скрипта по ссылке парсим этот xml в файл линков для Siege
      Скрипт
      #! /bin/sh
      sed -r 's/<loc/\n<loc/g; s!</loc>!</loc>\n!g' $1 | sed -r -n '/<loc>.*?<\/loc>/! D; /<loc>.*?<\/loc>/ s!</?loc>!!g; s!\s+!!g; P'
      

      использование
      ./sitemap2list.sh sitemap.xml > usrl.txt
      

      3) Устанавливаем для php-fpm в качестве максимального числа обработчиков (параметр pm.max_children) заведомо большое значение (30 например)
      4) Производим набор тестов следующего вида:
      siege -i -b -t 1m -с <num> -f urls.txt
      

      При каждом новом тесте мы будем увеличивать от 1 и далее с шагом 1. По достижении определённого значения число обработанных запросов в секунду начнёт уменьшаться, значит нам нужно выбрать значении предыдущего тестирования в качестве максимального числа обработчиков.
  • 0
    Мне кажется, что perl надо отделить и поставить для него фронтендом, например, lighthttpd. Нет времени объяснять, всех с наступающим! Ну а если серьезно, будет проще потом разобраться с ошибками, языки разные, задачи, которые они решают — разные и по-разному. Для легких и простых штук, можно вообще попробовать embedded perl.
    Было бы неплохо еще подкрутить sysctl на предмет TIME_WAIT — reuse, recycle.
    • 0
      Тут тоже не nginx перлом занимается, а fcgiwrap, не нравится он — отдайте в любой другой, некоторые вообще советуют весь апач притянуть, вариантов много. Еще не понял зачем делать фронтенд для nginx, может как-раз бэкенд?
  • 0
    Хорошо бы еще раскрыть тему open_basedir, иначе любой поломанный сайт открывает буквально все остальные сразу, да и в целом очень много позволяет видеть. Что с этим делать?
    • 0
      Пока из вариантов нашел только на каждого юзера (юзер=домен) поднимать отдельно fastcgi от имени юзера и рулить уже на уровне прав файловой системы, но думаю такой вариант кушать ресурсов будет не слабо. Видел еще решение подправить php.ini так:
      [HOST=hostname]
       open_basedir = somedir
      

      , но как себя поведет на реальных движках можно только гадать.
      Если кто знает правильный ответ, будет очень полезно услышать.
      • 0
        Как вы сказали, у вас 20 проектов. Нагрузка и правда будет не слабой, если поднимать отдельно fastcgi от имени юзера на каждый проект. Тогда вообще все преимущество в сравнении с apach потеряется. Да и рулить этим будет сложно.

        Что с этим делать я пока тоже не разобрался. Поэтому мне больше нравится связка apache + nginx. В этом случае каждый сайт работает под своим юзером и все хорошо.
        • 0
          Ну это классика энжиникс на фронтенд, апач на бэкенд. Если руки дойдут, подыму 3 одинаковых идентичных виртуалки на одной сделаю апач от ZendServer, на второй nginx+php-fpm с отдельными пулами на критичные проекты, на третьем nginx+apache залью наши движки и прогоню ряд нагрузочных тестов. Сейчас тестовый сервер в разы слабее боевого и сложно сказать, что будет быстрее. Рулить врядли будет сложно, не руками же каждый раз делать, разок скрипт набросать и все. Тут я боюсь серебряной пули не будет, как и везде, сильно будет зависеть от конкретных движков на чем будет лучше.
      • +1
        У меня каждый проект на php имеет свой отдельный pool, но работают они из под одного пользователя.
        Это и позволяет устанавливать разные настройки на отдельные сайты.

        Файл пула при это выглядит минималистично:

        [example.com]
        include=/etc/php-fpm.d/default
        


        В default содержится единый для всех код. Среди прочих его настроек для примера можно выделить следующие:

        listen =  /var/run/php-fpm/$pool.socket
        slowlog = /var/www/$pool/logs/slow.log
        php_admin_value[open_basedir] = /var/www/$pool
        php_admin_value[upload_tmp_dir] = /var/www/$pool/tmp
        


        Как мы видим, тут и basedir свой и tmp и логи.
        Nginx, при этом, работает с php через сокеты, что, как я надеюсь, исключает вероятность увеличения нагрузки из-за использования разных пулов. Если в этом своём предположении я ошибаюсь, то прошу указать мне на это и устыдить.

        Если интересно, то подобный подход с шаблоном, применяю и в настройках nginx.
        Файл одного сайта выглядит так:

        server {
            set $domain example.com;
            server_name example.com www.example.com;
        
            include php.conf;
        }
        


        В php.conf, естественно, содержаться все общие настройки. Демонстрируют работу с пулом следующие:

        fastcgi_pass unix:/var/run/php-fpm/$domain.socket;
        access_log  /var/www/$domain/logs/nginx.access.log;
        root /var/www/$domain/www;
        

        • 0
          Хороший подход, интересно было-бы сравнить нагрузку когда 1 пул и много для одинакового количества хостов, если разница не очень большая для меня такое решение будет оптимальным.
  • 0
    Классная статья, спасибо! Есть один вопрос.
    В файле /etc/nginx/templates/php параметр
    fastcgi_pass unix:/tmp/wwwpool.sock;
    этот конфиг подходит, если nginx стоит на той же машине, где и php-fpm. Если php-fpm на другой машине, то нужно писать
    fastcgi_pass 10.0.0.1:9000;

    А что делать, если используется несколько машин с php через upstream? Можно ли написать так:
    upstream backend-php {
    server 10.0.0.1:9000;
    server 10.0.0.2:9000;
    }

    fastcgi_pass backend-php;
  • 0
    Вопрос по статье, у вас в конфиге /etc/nginx/nginx.conf
    2 раза строка error_log /var/log/nginx/error.log; — так и надо или один раз лишний?
    • 0
      Не увидел где, даже по поиску проверил.
      • 0
        # Рекомендуется устанавливать по числу ядер
        worker_processes 4;
        pid /var/run/nginx.pid;
        worker_rlimit_nofile 8192;
        error_log /var/log/nginx/error.log; — тут и:

        # Настройка логов
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log; — тут.
        ##
        • 0
          Спасибо подправил.
  • 0
    Зачет Афтору, статья реально спасло дело.
    • 0
      Спасибо, значит не зря писал.
  • 0
    Большое спасибо автору! Пара мелких ошибок:
    «chomod» вместо chmod в двух местах
    «sige» вместо siege
    Наверное стоило бы написать, что nginx будет подхватывать конфигурацию дефолтового сайта из /etc/nginx/conf.d/default и пока мы его не удалим, он будет перекрывать описанный в статье default. Наши тестовые файлы просто не там будут искаться!
    • 0
      Спасибо подправил, похоже сначала хотел написать chown потом решил первым вписать chmod получился такой гибрид.
  • 0
    Прекрасная статья до сих пор настраиваю многие свои VPS по ней.
    Хотелось бы добавить.
    Часто мучался, что после рестарта файл /tmp/wwwpool.sock; создается под пользователем root, и соответственно nginx не может его слушать т.к. permission denied.
    Часто решал вопрос просто прописывая после рестарта комнаду
    chown www-data:www-data /tmp/wwwpool.sock
    

    но это сильно напрягало, т.к. требовало ручками каждый раз так делать.
    Короче в /etc/php5/fpm/pool.d/www.conf есть такие строки
    listen.owner = www-data
    listen.group = www-data
    listen.mode = 0660
    

    их надо раскомментить и вопрос решен.
    • 0
      Да давненько это добавили, инструкция писалась еще в 2013 году и тогда эта опция не требовалась, с того времени произошло много изменений и в самом nginx, как добавились разные плюшки, так и подогнаны дефолтные параметры под большинство серверов, что требует меньше лезть в базовый конфиг, если конфигурация близка к стандартной.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.