Итак по просьбам трудящихся пишу заметку как настроить Nginx и пых-пых чтобы они заменили собой Apache + mod_php.
Плюсы этой связки таковы - не запускаются экземпляры веб-сервера, сайт не подвержен атаке типа Slow Lori на которую клюёт апач, кроме того эта связка потребляет меньше оперативной памяти. Что это даёт? - под нагрузкой более стабильную работу и меньшее время отклика. Вобщем-то и всё, а нам другого и не надо :)
Со вступлением покончили, теперь надо бы начинать основную часть. Начинать наверно надо всё-таки издалека. Nginx - это довольно гибкий в конфигурировании веб-сервер, который умеет fcgi и проксировать запросы, кроме того механизм ssi позволяет инклудить код с других серверов, что довольно редко встречается среди веб-серверов, он также умеет кэшировать ответы апстримов, но это нужно в весьма специфических ситуациях... Синтаксис файла конфигурации достаточно прост, кроме того на сайте автора http://sysoev.ru/nginx/docs/ есть подробная документация по всем директивам сервера. Оговорюсь сразу - наилучшие результаты nginx показывает на FreeBSD, потому что Игорь разрабатывал nginx нацеливаясь именно на эту платформу, остальное пришло потом, да и нагрузочные и прочие опыты ставятся именно на фрюхе ввиду ограниченности количества линуксовых и других серверов у команды разработчиков nginx.
Итак начинаем со сборки.
Собирал я всё довольно просто - изначально был план использовать скрипты самого дистрибутива для управления веб-сервером. Но потом планы поменялись, однако это уже другая история предпоглагается, что всё будет собираться полустатически с библиотекой перл-совместимых регулярных выражений и zlib для повышения скорости сжатия отдаваемого контента. Повышения производительности за счёт сборки с ssl в том же духе мне не нужно было, поэтому я на этот вопрос забил, ssl для меня не критичен. Итак, что нам нужно - debian gnu/linux 5.0.3 под x86_64 (как раз именно он у меня в качестве платформы под веб-сервер и крутился), само-собой php5, php5-cgi, openssl, gcc и ещё масса всего-всего по депендам :) nginx-0.8.xx, pcre-8.00 и zlib-1.2.3.
#!/bin/bash
./configure \
--prefix=/usr/local \
--sbin-path=/usr/local/sbin \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=www-data \
--group=www-data \
--with-file-aio \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_secure_link_module \
--http-client-body-temp-path=/tmp/nginx \
--http-proxy-temp-path=/tmp/nginx-cgi \
--http-fastcgi-temp-path=/tmp/nginx-fcgi \
--without-mail_pop3_module \
--without-mail_imap_module \
--without-mail_smtp_module \
--with-pcre=./pcre-8.00 \
--with-zlib=./zlib-1.2.3 \
make
Коментарии, я думаю, излишни, архивы с исходниками pcre и zlib были распакованы в каталог с nginx.
Если ошибок не было смело пишем make install и начинаем конфигурить собственно веб-сервер.
Топаем в /etc/nginx и открываем nginx.conf, если такового нет, то можно в него забить что-то вроде этого:
user www-data;
worker_processes 3;
worker_rlimit_nofile 30000;
timer_resolution 1000ms;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 256; # as apache :)
use epoll;
accept_mutex on;
accept_mutex_delay 50ms;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type text/plain;
charset utf-8;
access_log /var/log/nginx/access.log;
large_client_header_buffers 256 16k;
server_tokens off;
ignore_invalid_headers on;
port_in_redirect off;
server_names_hash_bucket_size 128;
limit_rate 1000000M; # on ALL interfaces including backend
output_buffers 256 128k;
postpone_output 1460;
sendfile off;
# aio on;
# directio 512;
# directio_alignment 512;
# tune for your needs
resolver 127.0.0.1;
resolver_timeout 1s;
# proxy_cache_path /tmp/nginx-cache levels=1:2 keys_zone=one:10m inactive=20m max_size=500m;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 3;
reset_timedout_connection on;
send_timeout 90;
lingering_time 90;
lingering_timeout 90;
types_hash_bucket_size 128;
#gzipping all text content
gzip on;
gzip_http_version 1.1;
gzip_buffers 32 8k;
gzip_types text/plain text/html text/xhtml text/css text/xml application/x-javascript application/xml application/xml+rss application/atom+xml;
gzip_proxied any;
gzip_comp_level 1; # for my processor it is enough, for xeons it will be 6 or more
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
upstream first { server 127.0.0.1:9000 }
include /etc/nginx/sites-enabled/*;
}
Далее - конфигурация конкретного сайта на конкретном домене, файл кладём в каталог /etc/nginx/sites-enabled :
server {
listen 80 default backlog=16384 sndbuf=2097152 rcvbuf=8192 deferred;
server_name имя сайта;
override_charset off;
access_log /var/log/nginx/access.log combined ;
root /var/www/имя сайта;
error_page 404 /404.html;
log_not_found on;
index index.php index.html index.htm;
# special rule that eases burden for index page
location = /index.php {
fastcgi_pass first;
fastcgi_param SCRIPT_FILENAME /var/www/exs.elm.ru/index.php;
include /etc/nginx/fastcgi_params;
break;
}
# root of site
location = / {
if (!-f $request_filename) {
break;
}
index index.php;
}
# .haccess .htpasswd and so on...
location ~ /\.ht {
deny all;
break;
}
# apache bug?
location ~ index$ {
deny all;
break;
}
# Static files location
# we cannot map all .html expires time 1 day, because we have catlogs that should have shorter expires time
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|xhtml|xml)$ {
if (-f $request_filename) {
access_log off;
expires 10d;
break;
}
}
# all php stuff goes to fastcgi server
location ~ \.php$ {
if (!-f $request_filename) {
return 404;
break;
}
include /etc/nginx/fastcgi_params;
fastcgi_pass first;
# fastcgi_pass unix:/tmp/php5.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/exs.elm.ru$fastcgi_script_name;
fastcgi_buffers 32 8k;
}
location ~ favicon\.ico$ {
expires 100d;
if (!-f $request_filename) {
return 404;
break;
}
break;
}
}
Остаётся только разместить контент и всё...
Ну, и конечно же не надо забывать про fcgi серверы, для этого нам надо скачать <a href="http://redmine.lighttpd.net/projects/spawn-fcgi">**http://redmine.lighttpd.net/projects/spawn-fcgi**</a> вот этот спаунер, он-то как раз и возьмёт на себя все хлопоты связанные с запуском php5-cgi
Скрипт для запуска этого чуда в Debian:
#!/bin/bash
### BEGIN INIT INFO
# Provides: php5-fcgi
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the php5-cgi in fast-cgi mode
# Description: configure and starts php5-cgi processes in fast-cgi mode using spawn-fcgi
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
SCRIPTNAME="/etc/init.d/php5-fcgi"
FCGI_PIDFILE="/var/run/spawn-php5-fcgi.pid"
## Абсолютный путь до spawn-fcgi
FCGI_DAEMON="/usr/local/bin/spawn-fcgi"
## PHP переключится на этого юзера и группу (делать такими же, как у nginx)
USER=webmaster
GROUP=webmaster
## Абсолютный путь до php
FCGI_PROGRAM="/usr/bin/php5-cgi"
## Количество запущенных процессов PHP-fcgi, см http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:PerformanceFastCGI#How-many-PHP-processes-do-I-need
PHP_FCGI_CHILDREN=10
## Максимальное количество запросов, которое обработает отдельный PHP - fcgi процесс до своего перезапуска
PHP_FCGI_MAX_REQUESTS=1000
## TCP порт, который будет слушать php-fcgi
FCGI_PORT="9000"
## IP адреса, по которым будет доступен PHP-fcgi (через запятую)
FCGI_IP="127.0.0.1"
test -x $FCGI_PROGRAM || exit 0
test -x $FCGI_DAEMON || exit 0
set -e
export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS
. /lib/lsb/init-functions
case "$1" in
start)
log_daemon_msg "Starting spawn-fcgi"
if ! $FCGI_DAEMON -a $FCGI_IP -p $FCGI_PORT -f $FCGI_PROGRAM -u $USER -g $GROUP -C $PHP_FCGI_CHILDREN -P $FCGI_PIDFILE; then
log_end_msg 1
else
log_end_msg 0
fi
RETVAL=$?
;;
stop)
log_daemon_msg "Killing all spawn-fcgi processes"
start-stop-daemon --stop --pidfile $FCGI_PIDFILE --signal 2 && log_end_msg 0 || log_end_msg 1
if killall --signal 2 php5-cgi > /dev/null 2> /dev/null; then
log_end_msg 0
else
log_end_msg 1
fi
RETVAL=$?
;;
restart|force-reload)
$0 stop
$0 start
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}"
exit 1
;;
esac
exit $RETVAL
Либо как-то по другому, команда запуска будет примерно такой:
/usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www-data -g www-data -C 2 -f /usr/bin/php5-cgi
Остаётся только проверить один нюанс - правильное значение параметра doc_root в файле /etc/php.ini (если этот параметр вообще там определён, в Debian ничего перенастраивать не надо) , он должен указывать на корень сайта, абсолютный путь (/var/www)
вроде бы всё...
Upd 15 Apr 2014:
Немного подрихтовано :)