[lang_en]Nginx With PHP As FastCGI Howto[/lang_en][lang_ru]Настройка Nginx для поддержки PHP при помощи FastCGI[/lang_ru]
30 May2006

[lang_en]

After my first post about nginx web and reverse-proxy server, I have received many e-mail comments and questions. One of the most popular questions was “How to use PHP with nginx?”. This small howto-like article is about how to do it.

[/lang_en]

[lang_ru]

После моего первого рассказа о веб- и reverse-proxy сервере nginx, я получил много писем с коментариями и вопросами насчет него. Одним из самых распространенных вопросом был “Как использовать PHP вместе с nginx?”. А этой маленькой пошаговой инструкции я постараюсь описать, как это можно сделать.

[/lang_ru]

Since this article has been published long time ago, there is MUCH better option to manage PHP FastCGI processes than the one I described below. Please check out php-fpm project from Andrei Nigmatulin which IMHO is the best possible way to manage PHP processes.

[lang_en]

Nginx supports FastCGI technology to work with many external tools and servers. PHP itself can be runned as FastCGI application and can process FastCGI requests from nginx.

So, first of all we need to install PHP with fastcgi support and run it on some local tcp port. Installation process can go different ways, but I will describe here how to compile PHP from sources because it is generic way. To get fastcgi-enabled version of PHP interpreter, you may use following commands:

1
2
3
4
5
6
7
# ./configure --prefix=/opt/php --enable-fastcgi
...
# make
...
# make install
...
#

When all of these commands will be completed, you will be able to run your fastcgi server. But there are two different ways to do it:

  • Running PHP’s built-in FastCGI server – this method don’t require any third party tools.
  • Running PHP inside some third-party wrapper – it can be more comfortable than first method because of more flexibility.

If you want to run PHP using its built-in FastCGI manager, you can use following script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/bin/bash

## ABSOLUTE path to the PHP binary
PHPFCGI="/opt/php/bin/php"

## tcp-port to bind on
FCGIPORT="8888"

## IP to bind on
FCGIADDR="127.0.0.1"

## number of PHP children to spawn
PHP_FCGI_CHILDREN=5

## number of request before php-process will be restarted
PHP_FCGI_MAX_REQUESTS=1000

# allowed environment variables sperated by spaces
ALLOWED_ENV="ORACLE_HOME PATH USER"

## if this script is run as root switch to the following user
USERID=www-data

################## no config below this line

if test x$PHP_FCGI_CHILDREN = x; then
  PHP_FCGI_CHILDREN=5
fi

ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_CHILDREN"
ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS"
ALLOWED_ENV="$ALLOWED_ENV FCGI_WEB_SERVER_ADDRS"

if test x$UID = x0; then
  EX="/bin/su -m -c "$PHPFCGI -q -b $FCGIADDR:$FCGIPORT" $USERID"
else
  EX="$PHPFCGI -b $FCGIADDR:$FCGIPORT"
fi

echo $EX

# copy the allowed environment variables
E=

for i in $ALLOWED_ENV; do
  E="$E $i=${!i}"
done

# clean environment and set up a new one
nohup env - $E sh -c "$EX" &> /dev/null &

If you want to use third party software to start PHP as FastCGI-server,you can take a look at spawn-fcgi from Lighttpd project.

So, your PHP FastCGI server has been started and now last thing you need to do is to configure nginx server to forward php-requests to PHP’s tcp-port. It can be done with following config file snipet (full version is here):

1
2
3
4
5
6
7
8
9
10
11
12
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:8888
#
location ~ .php$ {
  fastcgi_pass   127.0.0.1:8888;
  fastcgi_index  index.php;

  fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name;
  fastcgi_param  QUERY_STRING     $query_string;
  fastcgi_param  REQUEST_METHOD   $request_method;
  fastcgi_param  CONTENT_TYPE     $content_type;
  fastcgi_param  CONTENT_LENGTH   $content_length;
}

That is all! Now you can use your nginx to serve any PHP-enabled sites and its performance will be very close to Apache mod_php module, but you will get more memory to process more requests from your site visitors.

As always, if you have some questions or suggestions, you can post them in comments area or email me. If you like this article, please vote for it on digg.com.

[/lang_en]

[lang_ru]

Nginx включает в себя поддержку технологии FastCGI для работы с внешними серверами и утилитами. PHP тоже поддерживает FastCGI и может быть использован для обработки FastCGI-запросов от nginx.

Итак, для начала нам необходимо установить PHP с поддержкой технологии fastcgi и запустить его на каком-либо tcp-порту, на который потом будут переправляться запросы из nginx. Процесс инсталляции может отличаться на разных системах, потому я опишу процесс сборки PHP из исходного кода как один из самых распространенных методов. Для того, чтобы получить версию интерпретатора PHP с поддержкой FastCGI, Вы можете использовать следующий набор команд:

# ./configure --prefix=/opt/php --enable-fastcgi
...
# make
...
# make install
...
#

Когда эта последовательность команд будет успешно завершена, Вы сможете запустить свой fastcgi-сервер. Но существует два возможных варианта, как это сделать:

  • Запуск встроенного в PHP сервера FastCGI – метод, не требующий никаких дополнительных утилит.
  • Запуск PHP внутри какого-либо стороннего обработчика запросов – этот вариант может быть более удобным из-за большей гибкости в настройке.

Если Вы решили не использовать никакого стороннего ПО, то можете запустить PHP с использованием его встроенного менеджера FastCGI-запросов при помощи следующего скрипта:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/bin/bash

## ABSOLUTE path to the PHP binary
PHPFCGI="/opt/php/bin/php"

## tcp-port to bind on
FCGIPORT="8888"

## IP to bind on
FCGIADDR="127.0.0.1"

## number of PHP children to spawn
PHP_FCGI_CHILDREN=5

## number of request before php-process will be restarted
PHP_FCGI_MAX_REQUESTS=1000

# allowed environment variables sperated by spaces
ALLOWED_ENV="ORACLE_HOME PATH USER"

## if this script is run as root switch to the following user
USERID=www-data

################## no config below this line

if test x$PHP_FCGI_CHILDREN = x; then
  PHP_FCGI_CHILDREN=5
fi

ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_CHILDREN"
ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS"
ALLOWED_ENV="$ALLOWED_ENV FCGI_WEB_SERVER_ADDRS"

if test x$UID = x0; then
  EX="/bin/su -m -c "$PHPFCGI -q -b $FCGIADDR:$FCGIPORT" $USERID"
else
  EX="$PHPFCGI -b $FCGIADDR:$FCGIPORT"
fi

echo $EX

# copy the allowed environment variables
E=

for i in $ALLOWED_ENV; do
  E="$E $i=${!i}"
done

# clean environment and set up a new one
nohup env - $E sh -c "$EX" &> /dev/null &

Если же Вы решили попробовать использовать какое-либо стороннее программное обеспечение для запуска PHP как FastCGI-серера, могу посоветовать Вам взглянуть на утилиту spawn-fcgi из пакета lighttpd.

Итак, Ваше сервер PHP запущен в режиме FastCGI и последнее, что Вам осталось сделать, это изменить конфигурацию Вашего сервера nginx таким образом, чтобы он переправлял все запросы к файлам php на определенный tcp-порт, на котором слушает PHP. Для этого может быть использован следующий пример секции location из конфигурационного файла nginx (полная версия примера нвходится здесь):

1
2
3
4
5
6
7
8
9
10
11
12
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:8888
#
location ~ .php$ {
  fastcgi_pass   127.0.0.1:8888;
  fastcgi_index  index.php;

  fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name;
  fastcgi_param  QUERY_STRING     $query_string;
  fastcgi_param  REQUEST_METHOD   $request_method;
  fastcgi_param  CONTENT_TYPE     $content_type;
  fastcgi_param  CONTENT_LENGTH   $content_length;
}

Вот и все! Теперь Вы можете использовать Ваш сервер nginx для обслуживания любых сайтов, написанных на PHP с производительностью, близкой к той, с которой работает модель mod_php в Apache, но при этом у вас будет больше свободной памяти, что позволит Вам обрабатывать больше запросов от посетитесей Ваших сайтов.

Как всегда, если у вас есть какие либо вопросы или пожелания, оставляйте их здесь в области для комментирования или отправляйте их почтой прямо ко мне. Если Вам понравилась эта статья, проголосуйте за нее на digg.com.
[/lang_ru]