Pull to refresh

Nginx+php-fpm+perl под Debian Squeeze

Reading time 10 min
Views 124K

Для чего эта заметка, ведь похожих уже полно? Если кратко, то когда я взялся настроить связку пришлось перечитать огромное количество документации и разных статей, все сразу и в одном месте найти не получилось. Данная статья попытка систематизировать накопленные знания, а также максимально подробная помощь тем, кто только начинает осваивать 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
Tags:
Hubs:
+25
Comments 66
Comments Comments 66

Articles