Обустройство локального и удаленного веб-сервера для PHP разработчиков. Переход на Nginx.

Данное руководство предназначено для разработчиков на PHP, переходящих на повседневное использование (K)Ubuntu Linux и организующих на ней рабочее место; желающих перейти на nginx; а также всех тех, кто хочет разобраться, как гибко управлять (вручную, но быстро) компонентами своего локального / удаленного веб-сервера.
Следуя современному подходу, я не буду рассматривать использование, установку и настройку Apache. Консерваторам, противникам всего нового, ленивым и задающим вопрос «зачем это все надо?» я предлагаю рассмотреть очевидные преимущества Nginx.

  • Легковесный и быстрый. К примеру, 10 000 неактивных keep-alive соединений занимают примерно 2.5Мб памяти.
  • Является лучшим средством в качестве фронт-энда, т.е. для обработки клиентских запросов.
  • Предлагает очень гибкую настройку.
  • Без nginx уже не обходится практически ни один highload (высоконагруженный) проект на открытых технологиях. Опыт работы с ним и настройки может оказаться очень полезным.
  • В подавляющем большинстве случаев позволяет вообще отказаться от использования Apache.
  • Как следствие роста популярности, многие современные стеки приложений уже опираются на него, нежели Apache.

Но зачем это все лично вам, если у вас пока нет highload проектов?
Наверняка, через какое-то время, вам захочется арендовать VPS/VDS - виртуальный выделенный сервер (возможно, он у вас уже есть) и размещать на нем свой сайт, блог, созданные вами сайты (проекты) для ваших клиентов или какие-либо демонстрационные работы. Как правило, ресурсы на виртуальных серверах ограничены и использование nginx дает очевидные преимущества. Вы сможете получить лучшую скорость/отзывчивость на менее мощных и дешевых VPS.
От себя добавлю, что мне не удалось добиться на самой честной виртуализации KVM и тарифе 2x1000 Мгц / 2 Гб RAM, даже со всеми ухищрениями и использованием mpm_event апача, тех же результатов, которые дает nginx из коробки.
Поэтому, единообразие настроек и подобный опыт сможет помочь вам в любой момент поднять быстрый и эффективный сервер на любом железе / VPS. Также, в некоторых случаях, вы сможете сэкономить на панели ISPManager, арендовав пустой VPS и затратить не более 15-30 минут на его обустройство. Хозяин - барин, и выбор, использовать или нет, конечно же, делать вам.

Итак, при построении нашего сервера будут три основных независимых компонента:

  1. nginx — фронт-энд, обработка клиентских (браузерных) подключений;
  2. php-fpm — бэк-энд, менеджер процессов FastCGI для PHP;
  3. mysql — сервер баз данных.

Для новичков: вопреки тому, что традиционно их используют в связке, как и LAMP, они могут работать и совершенно независимо. Вы можете установить MySQL и использовать его из С++, Perl, Python и даже делать запросы и парсить результаты с помощью bash. Nginx вы можете использовать как веб-сервер для раздачи статики (html), как прокси-сервер, а можете с его помощью расшарить свои фильмы с компьютера для просмотра на мобильных устройствах (кстати, один из самых быстрых способов, например, на Nexus 7 смотреть FullHD фильмы без задержек в отличие от использования SMB). PHP же может быть установлен в систему как CLI и вы можете вызывать его из командной строки или писать shell скрипты на PHP.

Установка Nginx.

Под (K)Ubuntu есть три пакета, отличающиеся по количеству включенных модулей:
nginx-light — базовый набор;
nginx-full — стандартный набор;
nginx-extras — полный набор.

Если вы не знаете точно, какой вам нужен, я рекомендую в общем случае ставить nginx-full.
apt-get install nginx-full
Да, всего 400 килобайт скачалось и чуть больше мегабайта установилось =)
Кстати, для получения самой свежей стабильной версии для всех актуальных версий дистрибутива есть репозиторий ppa:nginx/stable, поддерживаемый разработчиками, а с версии 14.04 nginx добавлен в main и поддержкой вплотную обещали заняться Canonical.

Установка PHP

Не устанавливайте пакет php5, он потянет за собой апач.
apt-get install php5-fpm
В дополнение рекомендую поставить пакет php5-cli, для возможности вызова php-скриптов из командной строки. Расширения PHP устанавливать также очень просто, поставим базовый набор (допишите нужные вам):
apt-get install php5-cli php5-curl php5-gd php5-mcrypt php5-mysql

Установка MySQL.

Тут все просто:
apt-get install mysql-server
Установщик спросит у вас два раза пароль на пользователя root для MySQL.
Сразу, не отходя от кассы, внесем настройки в /etc/mysql/my.cnf в любое место секции [mysqld], например, после skip-external-locking
character-set-server = utf8
для дефолтного использования кодировки UTF-8 в таблицах.
Обратите внимание, что начиная с версии 5.5 тип таблиц, создаваемых по умолчанию, являются innodb. Если вам нужен тип myisam по умолчанию, допишите строку default-storage-engine = myisam, хотя лучше всегда писать точные запросы при создании таблиц.

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

Конфигурация PHP.

Конфиги находятся в каталоге /etc/php5. Важно: для каждой конфигурации, будь то модуль апача, CLI или FPM существуют отдельные конфиги и, соответственно, отдельный php.ini.
Если у вас был апач, то конфиги под него находятся в /etc/php5/apache2 и больше использоваться не будут.
Для скриптов, вызываемых из консоли, будут использоваться конфиги из каталога /etc/php5/cli.
FPM же имеет некоторые отличия. Помимо отдельной конфигурации, он представляет собой менеджер процессов, работающий как демон. Nginx сам не запускает интерпретатор PHP и не «скармливает» ему конкретные скрипты, он только обрабатывает запросы, быстро отдает статику, но когда требуется выполнить скрипт — он передает эту задачу бэк-энду FPM, который намного лучше решает эту задачу, после чего результат идет по цепочке обратно (на самом деле, раньше это решалось через FastCGI, но этот метод устарел и в нынешних реалиях неэффективен).
Настройка FPM сводится к конфигурированию пулов, что дает большую гибкость. Если вам нужно выполнять скрипты от другого пользователя или с другими конфигурационными настройками — это можно сделать, создав новый пул.
По умолчанию создается пул www, конфиг которого находится в /etc/php5/fpm/pool.d/www.conf. Чтобы создать дополнительный, нужно просто скопировать файл в этот же каталог под новым именем, дать пулу другое имя в квадратных скобках и настроить под себя. На начальном этапе этого делать не требуется, важен лишь параметр listen.
Он может принимать значение listen = /var/run/php5-fpm.sock в случае использования unix-сокета и listen = 127.0.0.1:9000 в случае tcp-сокета (в различных дистрибутивах дефолтные параметры могут разниться). Через этот сокет происходит общение nginx и php-fpm.
На рабочем сервере / VPS параметры пула нужно будет настроить в соответствие нагрузке.
Внесем пару изменений в /etc/php5/fpm/php.ini, поскольку настраиваем сервер под разработку и нам нужно будет видеть все ошибки:
display_errors = On
error_reporting = E_ALL | E_STRICT

Для вступления изменений в силу, не нужно по привычке перезапускать веб-сервер, нужно перезапустить fpm:
service php-fpm restart

Создание виртуальных хостов.

Алгоритм добавления виртуального хоста следующий:

  • создать домашний каталог;
  • сделать копию /etc/nginx/sites-available/default в том же каталоге с новым именем и внести изменения;
  • сделать символическую ссылку созданного файла в /etc/nginx/sites-enabled/;
  • перезагрузить правила/конфиги nginx;
  • добавить запись в /etc/hosts (или DNS), чтобы получить возможность открывать в браузере.

Пара примеров. Начнем с «песочницы», где у нас будут всякие обрывки скриптов и тестовая фигня.
Для начала определимся, где у нас будут лежать домашние каталоги хостов и как их будем именовать. Как правило, единообразие в этом вопросе приводит к порядку и уменьшает головную боль в дальнейшем. Допустим, что пользователь в системе один, поэтому домашние каталоги расположим в /var/www (если нет — создадим, есть не пустой — очистим), а виртуальные хосты будем именовать через точку с local, например, для «песочницы» будет выглядеть как test.local.
Вы можете выбрать другой каталог, например в /home/user/www и выбрать другой принцип именования, но все же, рекомендую придерживаться единой схемы.

sudo -s
mkdir -p /var/www/test.local
chown -R user:user /var/www #где user — пользователь DE
cd /etc/nginx/sites-available
cp default test.local
nano test.local

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

Создаем ссылку (аналог команды a2ensite апача):
ln -s /etc/nginx/sites-available/test.local /etc/nginx/sites-enabled/

Удаляем дефолтный виртуальный хост:
rm /etc/nginx/sites-enabled/default

Перезагружаем правила:
service nginx reload
(отличается от restart тем, что не прерывает работы, полезно на работающих серверах)

Добавляем в /etc/hosts такую строчку:
127.0.0.1 test.local

Под юзером или в своей любимой IDE делаем файлик /var/www/test.local/test.php что угодно, вроде:
<?php
phpinfo
();
?>

Заходим в браузере на http://test.local

Установка и полноценная настройка phpmyadmin.
Приложения вроде phpmyadmin, drupal, wordpress и т. д. можно, конечно, поставить из пакетов, но... версии в пакетах практически всегда устаревшие, потянут апач, да и все равно потребуют серьезной настройки, так что будем ставить свежую версию и настраивать ее для получения максимальной функциональности.
Архив с последней версией можно получить тут http://www.phpmyadmin.net/, создаем каталог /var/www/mysql.local, распаковываем туда файлы из архива.
Настраиваем для него отдельный виртуальный хост, теперь это еще проще.
Копируем наш шаблон /etc/nginx/sites-available/test.local в /etc/nginx/sites-available/mysql.local, правим: убираем default в директиве listen, изменяем домашний каталог, имя сервера и пути к логам

создаем ссылку в sites-enabled, делаем reload
ln -s /etc/nginx/sites-available/mysql.local /etc/nginx/sites-enabled/
service nginx reload

добавляем запись в /etc/hosts
127.0.0.1 mysql.local
В принципе, phpmyadmin уже готов к работе и доступен из браузера через http://mysql.local, но локально каждый раз вводить пароль не комильфо, а часть функционала не будет задействована, пока не создать для phpmyadmin собственную базу.
Заходим в phpmyadmin под root, нажимаем «Импорт», выбираем файл /var/www/mysql.local/examples/create_tables.sql. Создастся база phpmyadmin, выбираем ее, нажимаем «Привилегии», «Добавить пользователя», указываем имя пользователя pma, хост — локальный, создать пароль — жмем «Генерировать», копируем пароль в буфер обмена. Должна стоять галочка «Выставить полные привилегии на базу данных phpmyadmin», глобальные привилегии не даем, жмем внизу «ОК».
Переименовываем файл /var/www/mysql.local/config.sample.inc.php в config.inc.php и правим:

Дополнительная информация по параметрам конфигурации http://php-myadmin.ru/doc/config.html.

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

По аналогии вы можете сделать виртуальный хост под рабочий проект и еще неограниченное количество оных.

Поиск и решение проблем.

Если что-то не заработало — читайте логи. Не ленитесь писать для каждого виртуального хоста свой лог - будет намного проще найти причину проблемы. Также, если все работает верно, FPM передает ошибки и предупреждения stderr Nginx и результат будет писаться в /var/log/nginx/.
Также частой проблемой начинающих является превышение лимита client_max_body_size при передаче между nginx и fpm, возникающую, например, при попытке загрузить файл на сервер через POST. Решается добавлением
client_max_body_size 20M
в блок server отдельного виртуального хоста, либо в блок http в файл /etc/nginx/nginx.conf для всех хостов. На рабочем сервере желательно согласовать размер с настройками PHP.
Если встречается ошибка "could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32", нужно добавить в http блок
server_names_hash_bucket_size 64;

На какие технологии стоит обратить внимание.

Для дальнейшей оптимизации рабочего сервера / VPS стоит обратить внимание на следующие вещи.
memcached — связующее программное обеспечение, реализующее сервис кэширования данных в оперативной памяти на основе парадигмы хеш-таблицы. Для работы из php есть расширения php5-memcache или php5-memcache. Также, nginx умеет брать статику / часть контента из memcached напрямую. Поддерживается плагинами многих готовых решений (drupal, wordpress etc).
zend opcache - данное расширение сохраняет компилированный байт код скрипта и повышает производительность, избавляя от интерпретации кода при каждом обращении к скрипту. В отличие от Zend Optimizer, Zend Opcache не загружает файлы, закодированные по Zend Guard, и является только акселератором. Входит в состав начиная с версии 5.5, однако собрать и подключить можно начиная с 5.3.

Версии PHP.

В (K)Ubuntu 12.04.3 LTS по умолчанию 5.3.10. Версию 5.5 можно получить, используя репозиторий ppa:ondrej/php5, а версию 5.4 - ppa:ondrej/php5-oldstable.
Для (K)Ubuntu 13.10 текущая версия 5.5.3.
Для Debian 7.3 текущая версия 5.4.4
В (K)Ubuntu 14.04 текущей будет 5.5.х, но поскольку она будет LTS, предположу, что после релиза появятся репозитории с пакетами 5.4 (не точно).

____________________________________________________________________
Буду признателен за дополнения и полезные советы для начинающих.