Установка Nginx + FPM
- Для чего использовать Nginx и PHP-FPM, а не Apache и mod_php?
- Установка необходимого ПО
- Конфигурирование Dnsmasq для *.dev
- Установка вашей работающей директории
- Конфигурирование PHP-FPM пула для нашего пользователя
- Конфигурирование виртуальных хостов Nginx
При разворачивании PHP веб-приложений, моим предпочтением является обслуживание статического контента с помощью Nginx и передача PHP запросов к PHP-FPM (FastCGI Process Manager) слушающего Unix сокет. При локальной разработке желательно, чтобы локальная среда разработки была как можно более ближе к среде, в которой будет работать приложение.
К концу статьи мы будем иметь полностью готовый стек для веб-приложения, работающий на Nginx и PHP-FPM, к которому будет легко добавлять новые сайты как виртуальные хосты. Мы будем развёртывать простой Laravel проект и будем использовать Composer для установки необходимых библиотек.
Я работаю, используя Crunchbang Linux, это в основе своей Debian Wheezy с довольно-таки неплохо выглядящим оконным менеджером OpenBox и панелью Tint2, которая уже сконфигурированы. Эти инструкции подойдут также при работе с Crunchbang, Debian и Ubuntu. Я протестировал их на Debian 7 Wheezy и Ubuntu 13.04.
Для облегчения тестирования я собираюсь установить dnsmasq - это очень лёгковесный DNS сервер для перенаправления любых запросов типа http://*.dev на мою локальную машину.
Это значит, что http://some.dev, http://experimental.staff.dev или http://AnythingAtAll.dev все будут направляться на 127.0.0.1. Всё, что мне нужно сделать - это добавить несколько строк конфигурации Nginx, чтобы он знал, как отвечать на данные URLs.
Это намного проще и чище, чем добавлять в файл /etc/hosts записи каждый раз, когда добавляется новый локальный домен для разработки.
Для чего использовать Nginx и PHP-FPM, а не Apache и mod_php?
Nginx - это опенсорс (2 clause BSD) вебсервер, обратный прокси-сервер и балансировщик нагрузки. Сильные стороны работы которого - это высокая степень параллелизма и высокая производительность в сочетании с низким потреблением памяти.
Я использую PHP-FPM для запуска PHP через FastCGI, так как это позволяет ОС управлять двоичным PHP и позволяет PHP запускаться как мой собственный пользователь. Это значит, что PHP может писать или читать мои директории без установки прав на папки в 0777. Также я могу складывать пароли к базам данных в файл читаемый лишь моим пользователем и мои php скрипты по-прежнему могут иметь к ним доступ.
PHP-FPM - это также быстее и менее интенсивный в использовании памяти, в отличие от модуля Apache, так как PHP-FPM не нужно делать вызовы exec() или fork() к двоичному PHP при КАЖДОМ запросе так, как это делает Apache. Очевидно, что я не могу использовать модуль Apache2 вместе с Nginx.
Установка необходимого ПО
Я устанавливаю необходимый минимум пакетов. Вы можете также добавить несколько других вещей, например php5-gd и php5-imagick для обработки изображений, php5-pgsql и php5-sqlite если вы используете другие базы данных, php5-memcached для кеширования запросов и уменьшения загрузки базы данных. Есть множество PHP расширений в менеджере пакетов. Я попытаюсь установить только необходимые для меня. Будет таким образом меньше возможность взломать меня и меньше потенциальных возможностей неудачь или источников ошибок.
sudo apt-get update
sudo apt-get install nginx-full php5-fpm php5-cli php5-mcrypt php5-mysql mysql-server dnsmasq
sudo service nginx start
Обеспечьте безопасность MySQL после установки. Очевидно, что на локальной машине этим можно пренебречь, но хорошо иметь привычку так постоянно делать и тогда вы точно не забудете это сделать при установке на новый сервер, виртуальную машину или сервер. Вы увидите, что по-умолчанию скрипты, представленные ниже, являются довольно-таки толковыми.
sudo mysql_secure_installation
При открытии http://localhost/ в вашем браузере, по-умолчанию вы увидите страницу приветствия Nginx.
Конфигурирование Dnsmasq для *.dev
Теперь нужно отредактировать конфигурационный файл dnsmasq. Я использую vim, но вы можете использовать nano или gedit, или любой другой редактор, с которым вы более знакомы.
sudo vim /etc/dnsmasq.conf
Есть большое множество комментариев в этом файле с отличными примерами того, что может делать dnsmasq и как его установить, но я обычно использую всего лишь эти две строки в начале файла.
address=/dev/127.0.0.1
listen-address=127.0.0.1
Первая строка сообщает dnsmasq, что любые запросы к http://anything.anything.dev/ должны быть перенаправлены к 127.0.0.1 (наша локальная машина). Если я добавлю address=/robo.dev/127.0.0.1 значит http://anything.robo.dev направит к локальной машине. Директива прослушать-адрес во второй строке сообщает dnsmasq слушать ТОЛЬКО запросы, которые приходят с локальной машины. Это исключает любой другой локальный траффик.
Откредактируйте DHCP конфигурационный файл и раскоментируйте строку prepend domain-name-servers line (удалите “#” прямо перед ней).
sudo vim /etc/dhcp/dhclient.conf
Найдите следующую строку (приблизительно ном.21), далее удалите “#” напротив неё и сохраните файл.
prepend domain-name-servers 127.0.0.1;
После редактирования файлов dnsmasq.conf и dhclient.conf, вам нужно перезапустить dnsmasq и весь ваш сетевой стек. Обычно легче просто перезагрузить компьютр, если вы неуверены, что ваша сеть управляется DE или через интерфейс другого менеждера.
sudo service dnsmasq restart
sudo service networking restart
Теперь все запросы браузера к *.dev будут направляться к странице приветствия Nginx. Если это не случилось, то просто перезагрузите компьютер.
Установка вашей работающей директории
Для меня намного легче, когда проекты, над которыми я работаю, находятся в каталоге “web” всередине моей домашней директории. В этом веб каталоге содержатся подкаталоги с конфигурационными файлами (к которым имеет доступ мой пользователь для редактирования и обновления и дальнейшего создания ссылки к их точному положению) и файлы access/error log для каждого проекта. Для целей примера, я также собираюсь создать папку testsite.dev и мы будем использовать этот сайт для тестирования установки.
mkdir -p ~/web/{conf,log,testsite.dev/public}
Конфигурирование PHP-FPM пула для нашего пользователя
Возьмите копию конфигурации php-fpm пула и положите её в папку conf, отключите пул www, переименовав его и создав ссылку на конфигурационный файл как YOURUSERNAME.conf.
cp /etc/php5/fpm/pool.d/www.conf ~/web/conf/php5-fpm-pool.conf
sudo mv /etc/php5/fpm/pool.d/www.conf /etc/php5/fpm/pool.d/www.conf.off
sudo ln -s /home/$(whoami)/web/conf/php5-fpm-pool.conf /etc/php5/fpm/pool.d/$(whoami).conf
PHP-FPM сканирует директорию pool.d и загружает все файлы .conf при загрузке. Переименуем www.conf в www.conf.off для того, чтобы этот пул не загрузился. Это, по-моему, лучше, чем удаление файла. С такой установкой мы можем редактировать наш файл в домашней директории, но рут-пользователь будет по-прежнему владеть символической ссылкой, так как ожидаемо конфигурацией должен владеть рут.
Давайте отредактируем ее. Откройте файл ~/web/conf/php5-fpm-pool.conf в вашем любимом редакторе.
vim ~/web/conf/php5-fpm-pool.conf
Под строкой, где у вас ;pool name, смените [www] на [YOURUSERNAME]. В моём случае я поменял его на [scottydelicious]. Это ни на что не влияет, это просто организует правильно все вещи и легко потом найти в менеджере процессов, таком как htop, особенно на сервере, когда у вас больше одного запущеного пула.
; Start a new pool named 'www'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[scottydelicious]
Найдите пользователя и группу и смените www-data на ваше имя пользователя. Это важно! Это пользователь от имени которого будет запускаться PHP. Мы хотим, чтобы это было имя нашего пользователя. В производственной среде, вы можете захотеть, чтобы это было www-data или вы захотите отдельные пулы и отдельных пользователей для каждого приложения, которое вы разместили на хостинге.
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
; will be used.
;user = www-data
;group = www-data
user = scottydelicious
group = scottydelicious
Найдите раздел listen = прямо под разделом user/group, который мы только что редаткировали. Убедитесь, что он слушает сокет Unix. Предпочтительнее слушать TCP порт, так как тогда отстутствуют накладные расходы и задержки в сети. Используйте порт TCP, если PHP запущен на другой машине, а не на вебсервере. В нашем случае, как и в большинстве случаев, вебсервер и PHP запущены на одной машине, поэтому сокет является лучшим выбором. Коментирование в этом файле начинается с точки с запятой “;”.
Если вы увидите:
listen = 127.0.0.1:9000
значит закоментируйте эту строку и сообщите PHP запускать сокет в /var/run/php5-fpm.sock
;listen = 127.0.0.1:9000
listen = /var/run/php5-fpm.sock
Следующий раздел, который будем конфигурировать процесс менеджер или pm. Поскольку это машина для разработки, то реальная ситуация - это один разработчик будет обращаться к серверу с запросами страницы. Держим это в уме при настройке этих опций и ставим их чуть ниже, чтобы они не поглощали нужную оперативную память для других приложений (редакторов, браузеров, десктопного окружения, плееров и т.д.), которые мы будем использовать при разработке. Эти настройки впрочем очень важны при продакшене, здесь же нам нужно всего лишь 1 или 2 PHP дочерних процесса.
; Note: This value is mandatory.
pm = dynamic
; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI. The below defaults are based on a server without much resources. Don't
; forget to tweak pm.* to fit your needs.
; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
; Note: This value is mandatory.
pm.max_children = 4
; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 1
; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 1
; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 2
Сохраните файл конфигурации и далее перезапустите PHP-FPM.
sudo service php5-fpm restart
Конфигурирование виртуальных хостов Nginx
Схожим образом как мы делали с PHP-FPM пулом, мы собираемся настроить конфигурацию хостов Nginx в нашей директории ~/web/conf/, на которую мы создадим ссылку в месте, где Nginx будет её искать. Сервер Nginx очень прост в конфигурировании как только вы изучите его синтаксис. Синтаксис очень хорошо задокументирован. Если вы привыкли конфигурировать виртуальные хосты Apache, то вам может показаться это несколько иначе, но на самом деле всё очень просто. Вы можете увидеть полный пример настройки по ссылке http://wiki.nginx.org/FullExample.
Если вы хотите начать с сильнозадокументированного работающего примера, то вы можете скопировать дефолтный конфигурационный файл для виртуального хоста /etc/nginx/sites-available/default в нашу conf директорию.
cp /etc/nginx/sites-available/default ~/web/conf/nginx-vhosts.conf
Я собираюсь начать с самого начала и установить наш “testsite.dev” проект. Это даст отличную точку для старта и потом можно будет просто копи-пастить для добавления сайта. Просто замените “testsite.dev” на “scottydelicious” - ваше имя проекта и ваше имя пользователя. Снова, я использую vim, если вы используете другой редактор, но смените команду.
im ~/web/conf/nginx-vhosts.conf
Если вы скопировали дефолтный конфигурационный файл, то удалите весь текст и следуйте дальнейшим инструкциям.
Первое, что мы сделаем - это создадим многоразовый направляющий PHP бекенд для всех наших проектов.
##################################
## PHP-FPM ##
##################################
upstream myphp {
# We use the upstream directive, give it a name, then
# pass all PHP requests to this socket.
server unix:/var/run/php5-fpm.sock;
}
Вы обратите внимание, что это указывает на сокет, который мы установили для нашего личного пула, когда мы устанавливали PHP-FPM. Далее, я объясню блок сервера testsite.dev. Он идёт сразу же за направляющим блоком, но не всередине его. Я подробно всё опишу в коментариях.
##################################
## testsite.dev ##
##################################
server {
# To add a new site, just copy this server directive then
# find and replace "testsite" with the new project name
# and replace "scottydelicious" with your username.
# This is is the equivalent of Apache's ServerName.
# There is no ServerAlias alternative, just add more domain
# names separated by space. For example:
# server_name example.com www.example.com example2.com;
server_name testsite.dev;
# This sets the web root.
root /home/scottydelicious/web/testsite.dev/public;
# Tell Nginx where to record logs. These will be owned by root.
access_log /home/scottydelicious/web/log/testsite.access.log;
error_log /home/scottydelicious/web/log/testsite.error.log;
# List folders if no index file is present:
# This is a terrible idea in production, but can be useful
# in development.
autoindex on;
# Which files should be used as indexes. Ordered in preference,
# e.g. look for index.php first, then index.html, then stop looking.
index index.php index.html;
location / {
# Pretty URLs. Allows removal of "index.php" from the URL.
# Useful for frameworks like Laravel or WordPress.
try_files $uri $uri/ /index.php?$query_string;
}
# Turn off logging for favicon and robots.txt
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
# serve static files directly
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires max;
}
# Removes trailing slashes (prevents SEO duplicate content issues)
if (!-d $request_filename)
{
rewrite ^/(.+)/$ /$1 permanent;
}
# Removes trailing "index" from all controllers.
# Useful for frameworks like Laravel.
if ($request_uri ~* index/?$)
{
rewrite ^/(.*)/index/?$ /$1 permanent;
}
# Unless the request is for a valid file (image, js, css, etc.),
# send it to index.php
if (!-e $request_filename)
{
rewrite ^/(.*)$ /index.php?/$1 last;
break;
}
# Uncomment this to run all 404 errors to index.php
#error_page 404 /index.php;
# Handle requests for files with the .php extension.
location ~ \.php$ {
# Pass php requests to the upstream server we created above
fastcgi_pass myphp;
fastcgi_index index.php;
include fastcgi_params;
}
}
Надеюсь, что коментарии хорошо объясняют, что происходит. Не стесняйтесь оставлять коментарии, если у вас возникнут какие-либо вопросы.
Теперь нужно создать ссылку на файл в месте, где nginx будет искать доступные сайты и далее сообщить Nginx перезагрузить свою конфигурацию нашей.
sudo ln -s /home/$(whoami)/web/conf/nginx-vhosts.conf /etc/nginx/sites-enabled/$(whoami)
sudo service nginx reload
Если вы создаете index.php файл в ~/web/testsite.dev/public/ с функцией phpinfo()
<?php
phpinfo();
?>
и откроете в браузере ссылку http://testsite.dev/, то вы увидите PHP инфо страницу.
15-10-2013 Nginx Ubuntu Виктор Матушевский
Сергій Росоловський
21.10.2013 20:39О настройке процесс менеджер на рабочем сервере поподробней можно? Ну например 1k пользователей в сутки такие то настройки, 10k - такие то.
Viktor Matushevskyi
21.10.2013 21:57По поводу настроек - ещё не разобрался сам. Только начал знакомство с Nginx. Эта настройка скорее подходит больше для локального дев-сервера. Продакшен-сервер естественно будет отличатся некоторыми моментами, в т.ч. и настройками на бОльшую нагрузку и т.д. Разберусь - отвечу по сути вопроса.
Тоха Макарук
09.04.2014 16:49"Убедитесь, что он слушает сокет Unix. Предпочтительнее слушать TCP порт, так как тогда отстутствуют накладные расходы и задержки в сети."
Вы наверно хотели сказать Предпочтительнее слушать Unix сокет.
Александр Фролов
07.05.2014 08:18>> Это значит, что PHP может писать или читать мои директории без установки прав на папки в 0777
У меня даже слов нет, чтобы описать насколько это неправильно и Apache с mod_php тут совершенно ни при чём.
Viktor Matushevskyi
07.05.2014 12:18Александр, найдите слова и напишите нам, потому что черпаю знания из англоязычных источников и перевожу их ближе к полуночи. Может они ошибаются, может я ошибся...