16 марта 2010 г. Linux MySQL Nginx PHP php-fpm Ubuntu

Ubuntu. Рабочее окружение Nginx+PHP5.3+FPM+MySQL

Собирали с васяцом на выходных рабочее окружение на своих нетбуках и решили юзать PHP 5.3 и PHP-FPM. Для себя я решил ставить все наиболее простым способом, если это возможно, поэтому сначала прибегаю к apt-get, а потом уже к сборке из сорцов. Кстати, если у вас уже установлен какой-либо PHP, то предварительно удалите его (libapache2-mod-php5 в том числе, если он есть).

Вообще эта инструкция применительна и к FreeBSD, просто вместо "apt-get install" используйте установку из портов.

Добавляем пользователя

Для начала создадим пользователя и группу www, от которой будет работать Nginx и PHP.

addgroup www
adduser --shell /usr/sbin/nologin --no-create-home --ingroup www --disabled-password --disabled-login www

Ставим Nginx

Как я и говорил прибегаем к наипростейшему пути:

apt-get install nginx

Теперь отредактируем /etc/nginx/nginx.conf и добавим upstream для php-fpm:

user www www;
worker_processes  1;

error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include     /etc/nginx/mime.types;
    access_log  /var/log/nginx/access.log;

    sendfile        on;
    keepalive_timeout  65;
    tcp_nodelay        on;

    upstream php-fpm {
        #server 127.0.0.1:9000;
        server unix:/tmp/php-fpm.sock;
    }

    include /etc/nginx/conf.d/*.conf;
}

Теперь приступим к установке PHP.

Ставим PHP 5.3 + PHP-FPM

Для того чтобы собрать php 5.3 + php-fpm нам потребуется слить сорцы php-fpm 5.3, но для начала убедитесь что у вас версия autoconf - 2.13, говорят что с другой версией будут проблемы. Пробовал собирать с более высокой версией (autoconf 2.59, вроде) - правда, проблемы есть. Поэтому ставим именно 2.13:

apt-get install autoconf2.13

Теперь надо поставить bison:

apt-get install bison

Далее libevent из сорцов. А именно версию 1.4.13 (установленная более ранняя версия не подходила).
Во время установки libevent была проблема - не хватало libtoolize... Сначала поставим libtool:

apt-get install libtool

А теперь libevent:

wget http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz
tar -xzvf libevent-1.4.13-stable.tar.gz
cd libevent-1.4.13-stable
./autogen.sh
./configure
make install

Все версии libevent тут.

И напоследок соберем libxml:

wget ftp://xmlsoft.org/libxml2/libxml2-2.7.6.tar.gz
tar -xzvf libxml2-2.7.6.tar.gz
cd libxml2-2.7.6
./configure
make && make install

Вам может понадобится mysql_config, например для Sphinx или модуля MySQL для PHP, то поставьте libmysqld-dev:

apt-get install libmysqld-dev

А теперь наконец сольем php-fpm и запустим скрипт сборщика:

svn co http://svn.php.net/repository/php/php-src/branches/PHP_5_3_FPM php_5_3_fpm
cd php_5_3_fpm
./buildconf 

Теперь у нас появился ./configure и мы можем указать с какими опциями собрать PHP:

./configure --prefix=/usr/local --disable-short-tags --enable-fpm --with-layout=GNU --without-pear \
--enable-mbstring --with-mysql=/usr/bin/mysql_config --with-mysqli=mysqlnd
make && make install

некоторые опции по пыху можно вычитать тут, а по поводу расширений типа mysqli/mbstring и прочих можно почитать в разделе "Installation" официальной документации, например mbstring или mysqli.

Многие опции включены по умолчанию, вы можете это поменять с помощью --disable-all.

Так как я ставил в кастомный каталог, то делаю ссылку на мой php для удобства:

ln -s /usr/local/bin/php /usr/bin/php

Нам понадобится скрипт управления php-fpm, скопируем его из сорцов:

cp php_5_3_fpm/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
chmod +x /etc/init.d/php-fpm

У меня стоял до этого PHP 5.2.10 (ставил из пакетов), поэтому у меня остался php.ini и я его скопировал:

cp /etc/php5/apache2/php.ini /usr/local/etc/php.ini

Если вы не знаете куда класть ваш php.ini, то зайдите в phpinfo и посмотрим пункт "Configuration File (php.ini) Path" и положите туда свой php.ini. В момент перезапуска PHP объявил некоторые опции как deprecated и я их закоментил просто-напросто. Если у вас нет файла php.ini, могу дать свой, в нем нет ничего особенного, это на случай отсутствия у вас этого файла.

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

Скопируем дефолтный конфиг:

cp /usr/local/etc/php-fpm.conf.default /usr/local/etc/php-fpm.conf

И доведем его немного до ума:

Address to accept fastcgi requests on.
Valid syntax is 'ip.ad.re.ss:port' or just 'port' or '/path/to/unix/socket'
<!--<value name="listen_address">127.0.0.1:9000</value>-->
<value name="listen_address">/tmp/php-fpm.sock</value>
....
<value name="listen_options">

        Set listen(2) backlog
        <value name="backlog">-1</value>

        Set permissions for unix socket, if one used.
        In Linux read/write permissions must be set in order to allow connections from web server.
        Many BSD-derrived systems allow connections regardless of permissions.
        <value name="owner">www</value>
        <value name="group">www</value>
        <value name="mode">0666</value>
</value>
...
<value name="php_defines">
    <!-- <value name="sendmail_path">/usr/sbin/sendmail -t -i</value> -->
    <value name="display_errors">1</value>    
    <value name="error_log">/var/log/php-error.log</value>    
    <value name="log_errors">true</value>
</value>
...
Unix user of processes
<value name="user">www</value>

Unix group of processes
<value name="group">www</value>
...
Comma separated list of ipv4 addresses of FastCGI clients that allowed to connect.
Equivalent to FCGI_WEB_SERVER_ADDRS environment in original php.fcgi (5.2.2+)
Makes sense only with AF_INET listening socket.
<value name="allowed_clients">127.0.0.1</value>

Вкратце что меняем:
1. Используем не tcp, а unix-сокет
2. Назначаем юзера и группу - www
3. Делаем вывод ошибок в стандартный поток и указываем файл лога ошибок

Это конфиг я уже приводил тут.

Проблемы с MySQLi

MySQLi ругался что не может открыть mysql-сокет по адресу "/tmp/mysql.sock", я отыскал путь до сокета в "/etc/my.cnf", скопировал его и поправил в "/usr/local/etc/php.ini" путь:


mysqli.default_socket = /var/run/mysqld/mysqld.sock

Запускаем наш сервер приложений

Добавим в Nginx виртуальный хост:


server {
    listen 80;
    server_name test.loc;
    root /www/test/htdocs;

    location / {
        index index.php;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass php-fpm;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

И запустим наш сервер:


service mysql start
service nginx start
service php-fpm start

Как всегда все просто! :)

Комментарии

Спасибо!

Можно также обратить внимание читателей, что в nginx.conf следует исправить user на www.

Ну, и если кто не поймёт - тов.Adw0rd делал это всё из-под root'а

в nginx.conf следует исправить user на www

Нет, там надо писать "user www;" и вообще желательно указывать группу:


user www www;
Ну, и если кто не поймёт — тов.Adw0rd делал это всё из-под root'а

да, я не переношу sudo... потому что все время его забываю писать, а потом приходится конфиг перенабирать, так как нельзя сохранить от своих прав :(

Ну еще во фре его не было и нет "из коробки".

Нет, там надо писать «user www;» и вообще желательно указывать группу:

Ну, я имел ввиду, что там изначально было что-то вроде "user www-kuemoe", а нужно заменить на "user www".

А, ну да, по дефолту user www-data

ь, а потом приходится конфиг перенабирать, так как нельзя сохранить от своих прав

Если vi, то :w !sudo tee %
И вопрос, в чем приемущество mysqli над стандартным модулем?

Вот в копилку еще один мануал по установке nginx+php-fpm , рабочий, если у кого-то что-то не получится : http://www.nginx.se/resurser/nginx_php_fpm/

И вопрос, в чем приемущество mysqli над стандартным модулем?

В том, что теперь стандартный - он :)

Ad1ce, васяц уже ответил на вопрос. А так, об этом уже писали неоднократно - погуглите (основное: mysqlnd, mysqli_multi_query, ОО-синтаксис, транзакции).

medar, сенкью, полезный материал

Спасибо за статью.

А php.ini в топку? В php-fpm "xml-style" конфига?

Почему php.ini в топку? Я такое не писал...
А php-fpm это спаунер, а не php-интерпретатор

как раз пересобираю серв, есть желание попробовать php-fpm, nginx нормально работает с xml на 443 порту и виртуальными хостами?

Что значит "nginx нормально работает с xml на 443 порту"? В каком плане нормально работает, какие именно работы имеются ввиду?

Да я просто ни когда не ставил nginx в качестве http сервера.
Всю жизнь он у меня обрабатывал статику на фронтенде (некая прокся)
А тут посмотрел видео, почитал каменты и .... загорелось.
от nginx нужно всего то 2 хоста 1й SSL (https (443)), 2й http (80)
https построен полностью на xml, а вот http полностью на пыхе.

все разобрался, все может спс...

Поставил, пока без SSL, ммм.... ваше класная штука, были правда некоторые терки с обработкой php скриптов но это из за непонимания nginx конфига.

поднимал на этом


%uname -v
FreeBSD 8.0-STABLE #2: Tue Mar 23 20:34:23 MSK 2010

PS
Adw0rd низкий поклон и уважуха, за то что показал такую клевую штуку, отловил пару ошибок в самописанных скриптах, переменным не были присвоены значения при определенном запросе, а это не есть хорошо.

В общем тест драйв, разбор SSL и мигрирую на эту связку :)

Рад что пригодилось :)

Эх... не смог завести cgi для xml откатился обратно на апач. lighthttp не стал ставить в качестве бекенда.

поставлю там где не нужна экзотика (только на php-mysql-http)

На днях таки решил переползти на nginx, пока полет нормальный.

Спасибо за мануал для лентяев :)

К слову:

root /www/test/htdocs; location / { index index.php; }

странно, но у меня так не завелось :(
Сработало только вот так(в /etc/nginx/sites-enabled/default к слову такой же вариант):

location / { index index.php; root /www/test/htdocs; }

P.S. Cтиль его конфигурационных файлов мне больше понравился чем у Apache.

Можно и так, а какая у тебя версия nginx?

context: http, server, location

http://sysoev.ru/nginx/docs/http/ngx_http_index_module.html#index

а какая у тебя версия nginx?

Без понятия, ставил по apt-get install nginx, наверное последняя стабильная.

Выполни "nginx -v", в пакетах всегда старье, а не последний стеубл

error: ./autogen.sh: 11: aclocal: not found
solution: sudo apt-get install automake

интересно =) не хватает такого же мануала для MAC OS X 10.6.3 Show Leopard

Принимаю подарки с условием написания поста :)

Эд, привет :)
Слушай, а как ты брал сорцы пэхэпэ, такого же бранча нету... Или просто его уже удалили? )

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

если кому интересно, то вот репо для пхп5.3 в Debian ≤5

echo "deb http://php53.dotdeb.org stable all" >> /etc/apt/sources.list

Есть ли предположения. Настраивал в FreeBSD по аналогии статье. Но возникла проблема php-fpm не обрабатывает php скрипты. Правда в логах ошибок нет ( и nginx и php-fpm ). Уровень логирования debug.

Ставили из портов php-fpm? Покажите конфиг nginx, связанный с работой php-fpm.

Да, ставил из портов, вместе с php 5.3.3.

upstream php-fpm { server 127.0.0.1:9000; }
И далее через
                location ~ .php$ {
include fastcgi_params;
fastcgi_pass php-fpm;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
в vhost-ах.

Ясно. И nginx ничего вообще не пишет при обращению к сайту? Никаких 50x?

netstat -an | grep 9000

что говорит?

При старте php-fpm создает pid-файл?
И с правами на файлы (pid, log) все нормально?

Nginx отдает php на скачку. Забыл указать что статика в nginx работает нормально.
netstat -an | grep 9000


tcp4       0      0 127.0.0.1.9000         *.*                    LISTEN

sockstat -4 | grep 9000


www      php-fpm    64891 0  tcp4   127.0.0.1:9000        *:*

ps -aux | grep /usr/local/sbin/php-fpm


root  64871  0.0  0.4 20636 12228  ??  Ss    2:19PM   0:19.17 /usr/local/sbin/php-fpm
www   64872  0.0  0.4 21656 12760  ??  I     2:19PM   0:00.43 /usr/local/sbin/php-fpm

pid создается, права в порядке.
p.s. Спасибо за помощь в решении проблемы.

Раз на скачку отдает, то наверное есть еще какие location, которые раньше срабатывают. Я для отладки location юзаю return или add_header:

location ... {
    return 401;
}
location ... {
    add_header tester $document_root;
}

Тем самым я понимаю какой локейшен срабатывает и могу посмотреть сожержимое переменных.


lynx -dump -head http://localhost/

Могу помочь напрямую, дайте доступ на время и я посмотрю сам всё.

Убрал все виртуалки. Обновил порты и пересобрал php. Конфиг сейчас такой:


    server {
        listen          80 default;
        server_name     _;
                access_log      /var/log/nginx/access.log main;
                error_log       /var/log/nginx/error.log debug;
                server_name_in_redirect off;

                location / {
                  root        /usr/local/www/default;
                  index index.php;
                }
                location ~ \.php$ {
                  add_header tester $document_root;
                  include fastcgi_params;
                  fastcgi_pass php-fpm;
                  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                }

заголовки такие:


HTTP/1.1 404 Not Found
Server: nginx/0.8.53
Date: Thu, 02 Dec 2010 09:45:54 GMT
Content-Type: text/html
Connection: close
X-Powered-By: PHP/5.3.3

внимание, вопрос знатокам: почему add_header не отрабатывает но версию php выдает?
p.s. С доступом временно не получиться.

  1. Не указан root для location .php$
  2. Укажите еще в location / add_header, нам надо понять в какой локейшен мы попадаем
  3. Какой запрос выдает такие заголовки? Если GET /, то в location .php$ он и не попадет

Могу чуть позже у себя ваш конфиг проверить и написать рабочий, сейчас просто надо срочно отъехать по делам.

Проблема решена. Все из-за непонимания.
Я думал что переменная $document_root глобальная для server{}.
Большое спасибо за внимание.

Это хорошо! Обращайтесь ещё, помогу чем смогу :)

Не плохо было бы добавить apt-get install subversion ;)

вообще всё как то печально, php не собирается так как не находит xml2 config да и ветки php_5_3_fpm нету...
Чё делать Эдво?

Ну сейчас в современныйх дистрибах убунты есть всё:


adw0rd@adw0rd-vaio~$ sudo apt-cache search php5-fpm
php5-fpm - server-side, HTML-embedded scripting language (FPM-CGI binary)
adw0rd@adw0rd-vaio~$ cat /etc/issue.net 
Ubuntu 10.10

Скажите, а зачем указан
upstream php-fpm {
#server 127.0.0.1:9000;
server unix:/tmp/php-fpm.sock;
}

Как я понял этот модуль используется для балансировки нагрузки на несколько бекендов, но у нас то он один? Или это дает, какой-то дополнительный плюс?

Это удобно для именования бекенда в *_pass конструкциях.
Ну и сегодня у вас 1 бекенд, а завтра 2, и придётся лишь добавить ещё один бекенд (при использованиии upstreams), а не менять 100500 мест в конфиге

Замечательная статья,на днях буду брать ВПСку,возьму ваш мануал за основу при настройке

Сейчас всё есть в портах и пакетах, не надо собирать из сорцов, просто ставьте всё из apt-get и будет счастье :)

Оставьте свой комментарий

Markdown