Операционная система FreeBSD содержит механизм jail(8), позволяющий создавать изолированные группы процессов, вроде легковесных виртуальных машин.
Джейлы эффективнее Xen-клеток, практически не потребляют ресурсов (т.к. используют общее с хостом ядро). Процессы из джейлов легко управляются с хоста (ps -A, kill, jls, jexec и т.п.). Каждый джейл видит только часть файловой системы и может быть ограничен в ресурсах (rctl, zfs set quota). На джейлах часто строится FreeBSD VPS-хостинг (например RootBSD.net), где каждый клиент имеет свою маленькую ОС и набор приложений с правами рута (извращенцы даже могут поставить GNU/kFreeBSD), однако в этой статье мы рассмотрим другую задачу — запуск web-сервера в минимальном джейле.
Зачем это нужно? В web-серверах, как и в другом софте, написанном на C, время от времени находят уязвимости к атакам типа "переполнение буфера", позволяющие удалённо захватить контроль над системой. Эти ошибки являются следствием технологии разработки софта, поэтому не могут быть исправлены окончательно. Каждая из них — предпоследняя.
Представьте себе: джейл, у которого в папке /bin нет шелла, только бинарные nginx и php-fpm. В папке /dev только null, urandom и ещё пара подобных устройств. В папке /etc только конфиги nginx'а, php.ini и файл master.passwd, в котором хэши паролей обоих пользователей root и www заменены звёздочками. Также в джейле есть /www, /logs и /tmp, где нет ничего интересного. Такой джейл может быть взломан через переполнение стека web-сервера или другого серверного процесса, но нагадить в основной системе или украсть пароль рута из него нельзя. Системный вызов mount(2) не работает, ICMP не работает, ноды устройств создавать нельзя, список внешних процессов недоступен, сигналы им отправить нельзя и так далее.
Для начала нужно сделать так, чтобы файерволл ipfw поддерживал проброс TCP/IP-портов внутрь джейла из основной системы (ip forwarding).
1. Выполнить команды
# cd /usr/src/sys/amd64/conf
# cp GENERIC MYCONF
# nano MYCONF
2. Дописать в конец файла следующие строки
3. Пересобрать и переустановить ядро; перезагрузить сервер
# cd /usr/src
# make clean
# make buildkernel KERNCONF=MYCONF
# make installkernel KERNCONF=MYCONF
# make clean
# shutdown -r now
4. Проверить как файерволл загрузился:
# dmesg | grep ipfw
Нам нужен специальный nginx: статически слинкованный и с нестандартными путями для конфигурации и сохрания логов — тот, что в портах, не подходит. Надо собрать собственный из исходников.
1. Посетить web-страницу http://nginx.org/en/download.html и записать URL для скачивания исходных кодов самой свежей стабильной версии nginx. На момент написания этого руководства — http://nginx.org/download/nginx-1.2.4.tar.gz
2. Посетить web-страницу http://www.zlib.net/ и записать URL для скачивания исходных кодов самой свежей версии zlib. На момент написания этого руководства — http://zlib.net/zlib-1.2.7.tar.gz
3. Посетить web-страницу http://www.pcre.org/ и записать URL для скачивания исходных кодов самой свежей версии PCRE. На момент написания этого руководства —
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.31.tar.bz2
4. Скачать и распаковать nginx и его зависимости:
# cd ~
# mkdir nginx-build
# cd nginx-build
# wget http://nginx.org/download/nginx-1.2.4.tar.gz
# wget http://zlib.net/zlib-1.2.7.tar.gz
# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.31.tar.bz2
# ls -l
# tar zxf nginx-1.2.4.tar.gz
# tar zxf zlib-1.2.7.tar.gz
# tar jxf pcre-8.31.tar.bz2
5. Подготовить сборочный скрипт для nginx:
# cd nginx-1.2.4
# wget http://.../nginx_build.sh
Полагаю, что JIT внутри джейла — это вполне безопасно. Тем более, что внешний пользователь всё равно не может задавать регэкспы, которые JITятся: они есть только в конфигах web-сервера.
6. Скомпилировать статический nginx для использования в джейле
# chmod +x nginx_build.sh
# ./nginx_build.sh
7. Проверить, что nginx правильно собрался:
# file /wwwjail/bin/nginx
Для начала, можно не врубать ограничения джейла на всю катушку, а только ограничить корневой каталог с помощью chroot(2). Такие лёгкие ограничения не годятся для боевой системы, но позволяют проверить, что web-сервер — результат сборки — работает, не разгребая проблемы с firewall'ом и т.п.:
1. Удалить каталог /wwwjail/usr
2. Присвоить файлу /wwwjail/etc/nginx.conf следующее содержимое:
3. Создать минимальную БД пользователей в джейле:
# cd /wwwjail/etc
# echo 'root:*:0:0::0:0:Root:/:/bin/nologin' > master.passwd
# echo 'www:*:80:80::0:0:WWW:/:/bin/nologin' >> master.passwd
# pwd_mkdb -d . master.passwd
# echo 'wheel:*:0:root' > group
# echo 'www:*:80:www' >> group
# chmod 644 group
# cd ..
4. Создать подкаталоги для журналов и временных файлов:
# mkdir tmp
# chmod 777 logs tmp
5. Настроить резолвинг DNS-имён в джейле:
# cp /etc/resolv.conf /wwwjail/etc/
6. Подготовить ограниченный devfs для джейла:
# mkdir /wwwjail/dev
# mount -t devfs devfs /wwwjail/dev
# devfs -m /wwwjail/dev rule apply hide
# devfs -m /wwwjail/dev rule apply path null unhide
# devfs -m /wwwjail/dev rule apply path zero unhide
# devfs -m /wwwjail/dev rule apply path random unhide
# devfs -m /wwwjail/dev rule apply path urandom unhide
# ls -l /wwwjail/dev
7. Подготовить пробный индексный файл:
# echo '<html><body>Test</body></html>' > /wwwjail/www/index.html
8. Испытать работоспособность nginx'а в chroot-окружении:
# cd ~
# chroot /wwwjail /bin/nginx
# wget http://localhost/
# cat index.html
# cat /wwwjail/logs/access.log
# chroot /wwwjail /bin/nginx -s quit
1. В файле /wwwjail/etc/nginx.conf параметр http/server/listen задать в виде "192.168.101.1:80"
2. Испытать работоспособность nginx'а в jail-окружении
# cd ~
# ifconfig -l
# ifconfig rl0 inet alias 192.168.101.1/32
# ifconfig
# jail -c path=/wwwjail host.hostname=example.com \
ip4.addr=192.168.101.1 command=/bin/nginx
# ps -A
# jls
# wget http://192.168.101.1/
# cat /wwwjail/logs/access.log
Замените example.com на доменное имя вашего сайта, rl — на имя драйвера сетевой карты (ifconfig -l, ifconfig).
3. В правила файерволла добавить следующие строки:
Замените 1.1.1.1 на IP-адрес вашего сайта. Числа 100 и 101 задают относительный приоритет правил и не имеют абсолютного смысла; у меня эти два правила предпоследние.
4. Сделайте так, чтобы новые правила файерволла вступили в силу.
Следующие команды выполнить на внешней машине, например из Cygwin под Windows:
# cd /
# wget http://1.1.1.1/
# ls -l
# cat index.html
# rm index.html
5. Остановить временный джейл и включить в автозагрузку запуск джейла с nginx'ом
# kill -QUIT `cat /wwwjail/logs/nginx.pid`
# jls
# nano /etc/rc.conf
добавить следующие строки:
# umount /wwwjail/dev
# /etc/rc.d/jail start wwwjail
# jls
6. Ещё раз проверить работоспособность джейла wget'ом извне; после чего перезагрузить сервер и провести этот тест ещё раз. После этого удалить временный каталог, в котором происходила сборка nginx:
# cd ~
# ls -l
# rm -rf nginx-build
Собрать статический PHP непросто, но возможно. FreeBSDшный ld не понимает параметра "-all-static", в отличие от скрипта libtool. php-fpm и nginx будут обмениваться данными через UNIX domain socket по протоколу FastCGI.
# cd /usr/ports/graphics/gd
# make install clean
# cd ../../textproc/libxml2
# make install clean
# cd ../../ftp/curl
# make install clean
# cd ../../math/gmp
# make install clean
# cd ../../security/libmcrypt
# make install clean
# cd ../../databases/sqlite3
# make install clean
# cd ~
# mkdir php-fpm-build
# cd php-fpm-build
# wget http://us2.php.net/get/php-5.4.9.tar.bz2/from/this/mirror
# mv mirror php-5.4.9.tar.bz2
# wget http://.../build_php.sh
# chmod +x build_php.sh
# ./build_php.sh
# cd /wwwjail2
# ls -l sbin
# file sbin/php-fpm
# cp sbin/php-fpm ../wwwjail/bin/
# cp etc/php-fpm.conf.default ../wwwjail/etc/
# cd ..
# rm -rf wwwjail2
# cd wwwjail/etc
# cp php-fpm.conf.default php-fpm.conf
# cp ~/php-fpm-build/php-5.4.9/php.ini-production php.ini.default
# cp php.ini.default php.ini
# nano php.ini
Задать следующие опции:
# nano php-fpm.conf
Задать следующие опции:
# jls
# jexec 1 /bin/php-fpm
# ps -A
# cat /wwwjail/logs/php-fpm.log
# cd /wwwjail/etc
# nano nginx.conf
# cd ..
# kill -HUP `cat logs/nginx.pid`
# cat logs/error.log
# echo '<?php phpinfo(); ?>' > www/index.php
# cat www/index.php
# cd ~
# wget http://192.168.101.1/index.php
# rm -rf php-fpm-build
# nano /etc/rc.conf
Добавить следующую строку:
jail_wwwjail_exec_afterstart1="/bin/php-fpm"
Проверить, что процесс php-fpm корректно завершается при останове джейла
и что джейл корректно запускается с nginx и php-fpm:
# /etc/rc.d/jail stop wwwjail
# ps -A
# /etc/rc.d/jail start wwwjail
# ps -A
nginx перечитывает свой конфиг по сигналу SIGHUP. Ошибки конфига пишутся в журнал error.log (если были ошибки, web-сервер остаётся со старыми настройками).
php-fpm перечитывает свой конфиг и php.ini по сигналу SIGUSR2. Дочерние процессы порождаются только с помощью fork(2), при этом execve(2) не применяется.
SIGUSR2 используется в nginx для других целей — для бинарного обновления web-сервера без прерывания обслуживания клиентов: http://wiki.nginx.org/CommandLine#Upgrading_To_a_New_Binary_On_The_Fly
Желательно настроить логротацию как описано в newsyslog(8). Оба сервера переоткрывают свои логи по SIGUSR1.
Джейлы эффективнее Xen-клеток, практически не потребляют ресурсов (т.к. используют общее с хостом ядро). Процессы из джейлов легко управляются с хоста (ps -A, kill, jls, jexec и т.п.). Каждый джейл видит только часть файловой системы и может быть ограничен в ресурсах (rctl, zfs set quota). На джейлах часто строится FreeBSD VPS-хостинг (например RootBSD.net), где каждый клиент имеет свою маленькую ОС и набор приложений с правами рута (извращенцы даже могут поставить GNU/kFreeBSD), однако в этой статье мы рассмотрим другую задачу — запуск web-сервера в минимальном джейле.
Зачем это нужно? В web-серверах, как и в другом софте, написанном на C, время от времени находят уязвимости к атакам типа "переполнение буфера", позволяющие удалённо захватить контроль над системой. Эти ошибки являются следствием технологии разработки софта, поэтому не могут быть исправлены окончательно. Каждая из них — предпоследняя.
Представьте себе: джейл, у которого в папке /bin нет шелла, только бинарные nginx и php-fpm. В папке /dev только null, urandom и ещё пара подобных устройств. В папке /etc только конфиги nginx'а, php.ini и файл master.passwd, в котором хэши паролей обоих пользователей root и www заменены звёздочками. Также в джейле есть /www, /logs и /tmp, где нет ничего интересного. Такой джейл может быть взломан через переполнение стека web-сервера или другого серверного процесса, но нагадить в основной системе или украсть пароль рута из него нельзя. Системный вызов mount(2) не работает, ICMP не работает, ноды устройств создавать нельзя, список внешних процессов недоступен, сигналы им отправить нельзя и так далее.
1. Пересборка ядра для поддержки проброса портов в джейл
Для начала нужно сделать так, чтобы файерволл ipfw поддерживал проброс TCP/IP-портов внутрь джейла из основной системы (ip forwarding).
1. Выполнить команды
# cd /usr/src/sys/amd64/conf
# cp GENERIC MYCONF
# nano MYCONF
2. Дописать в конец файла следующие строки
options IPFIREWALL options IPFIREWALL_VERBOSE options IPFIREWALL_VERBOSE_LIMIT=100 options IPFIREWALL_DEFAULT_TO_ACCEPT options IPDIVERT options IPFIREWALL_FORWARD
3. Пересобрать и переустановить ядро; перезагрузить сервер
# cd /usr/src
# make clean
# make buildkernel KERNCONF=MYCONF
# make installkernel KERNCONF=MYCONF
# make clean
# shutdown -r now
4. Проверить как файерволл загрузился:
# dmesg | grep ipfw
2. Сборка специального nginx для использования в джейле
Нам нужен специальный nginx: статически слинкованный и с нестандартными путями для конфигурации и сохрания логов — тот, что в портах, не подходит. Надо собрать собственный из исходников.
1. Посетить web-страницу http://nginx.org/en/download.html и записать URL для скачивания исходных кодов самой свежей стабильной версии nginx. На момент написания этого руководства — http://nginx.org/download/nginx-1.2.4.tar.gz
2. Посетить web-страницу http://www.zlib.net/ и записать URL для скачивания исходных кодов самой свежей версии zlib. На момент написания этого руководства — http://zlib.net/zlib-1.2.7.tar.gz
3. Посетить web-страницу http://www.pcre.org/ и записать URL для скачивания исходных кодов самой свежей версии PCRE. На момент написания этого руководства —
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.31.tar.bz2
4. Скачать и распаковать nginx и его зависимости:
# cd ~
# mkdir nginx-build
# cd nginx-build
# wget http://nginx.org/download/nginx-1.2.4.tar.gz
# wget http://zlib.net/zlib-1.2.7.tar.gz
# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.31.tar.bz2
# ls -l
# tar zxf nginx-1.2.4.tar.gz
# tar zxf zlib-1.2.7.tar.gz
# tar jxf pcre-8.31.tar.bz2
5. Подготовить сборочный скрипт для nginx:
# cd nginx-1.2.4
# wget http://.../nginx_build.sh
#!/usr/local/bin/bash
mkdir /wwwjail
mkdir /wwwjail/bin
mkdir /wwwjail/etc
mkdir /wwwjail/logs
mkdir /wwwjail/www
./configure --sbin-path=/bin \
--conf-path=/etc/nginx.conf \
--http-log-path=/logs/access.log \
--error-log-path=/logs/error.log \
--pid-path=/logs/nginx.pid \
--lock-path=/logs/nginx.lock \
--user=www --group=www \
--with-ipv6 \
--without-select_module \
--without-poll_module \
--with-aio_module \
--with-file-aio \
--with-http_ssl_module \
--with-http_gzip_static_module \
--without-http_ssi_module \
--without-http_userid_module \
--without-http_access_module \
--without-http_geo_module \
--without-http_map_module \
--without-http_split_clients_module \
--without-http_referer_module \
--without-http_uwsgi_module \
--without-http_scgi_module \
--without-http_memcached_module \
--without-http_empty_gif_module \
--without-http_upstream_ip_hash_module \
--http-client-body-temp-path=/tmp/client \
--http-proxy-temp-path=/tmp/proxy \
--http-fastcgi-temp-path=/tmp/fastcgi \
--http-uwsgi-temp-path=/tmp/uwsgi \
--http-scgi-temp-path=/tmp/scgi \
--without-http-cache \
--with-pcre=/root/nginx-build/pcre-8.31 \
--with-pcre-jit \
--with-zlib=/root/nginx-build/zlib-1.2.7 \
--with-cc-opt="-O2 -fomit-frame-pointer -static" \
--with-ld-opt="-s -static"
if [ "$?" -ne "0" ]; then
echo "=== build script: failed to configure nginx ==="
exit 1
fi
make
if [ "$?" -ne "0" ]; then
echo "=== build script: failed to make nginx ==="
exit 1
fi
make DESTDIR=/wwwjail install
if [ "$?" -ne "0" ]; then
echo "=== build script: failed to install nginx ==="
exit 1
fi
echo "=== build script: OK ==="Полагаю, что JIT внутри джейла — это вполне безопасно. Тем более, что внешний пользователь всё равно не может задавать регэкспы, которые JITятся: они есть только в конфигах web-сервера.
6. Скомпилировать статический nginx для использования в джейле
# chmod +x nginx_build.sh
# ./nginx_build.sh
7. Проверить, что nginx правильно собрался:
# file /wwwjail/bin/nginx
3. Испытание nginx'а в chroot-окружении
Для начала, можно не врубать ограничения джейла на всю катушку, а только ограничить корневой каталог с помощью chroot(2). Такие лёгкие ограничения не годятся для боевой системы, но позволяют проверить, что web-сервер — результат сборки — работает, не разгребая проблемы с firewall'ом и т.п.:
1. Удалить каталог /wwwjail/usr
2. Присвоить файлу /wwwjail/etc/nginx.conf следующее содержимое:
user www;
worker_processes 1;
error_log /logs/error.log;
pid /logs/nginx.pid;
events {
worker_connections 1024;
use kqueue;
}
http {
include /etc/mime.types;
default_type application/octet-stream;
access_log /logs/access.log combined;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name localhost;
charset utf-8;
#access_log /logs/localhost.access.log combined;
location / {
root /www;
index index.html index.htm;
}
}
}3. Создать минимальную БД пользователей в джейле:
# cd /wwwjail/etc
# echo 'root:*:0:0::0:0:Root:/:/bin/nologin' > master.passwd
# echo 'www:*:80:80::0:0:WWW:/:/bin/nologin' >> master.passwd
# pwd_mkdb -d . master.passwd
# echo 'wheel:*:0:root' > group
# echo 'www:*:80:www' >> group
# chmod 644 group
# cd ..
4. Создать подкаталоги для журналов и временных файлов:
# mkdir tmp
# chmod 777 logs tmp
5. Настроить резолвинг DNS-имён в джейле:
# cp /etc/resolv.conf /wwwjail/etc/
6. Подготовить ограниченный devfs для джейла:
# mkdir /wwwjail/dev
# mount -t devfs devfs /wwwjail/dev
# devfs -m /wwwjail/dev rule apply hide
# devfs -m /wwwjail/dev rule apply path null unhide
# devfs -m /wwwjail/dev rule apply path zero unhide
# devfs -m /wwwjail/dev rule apply path random unhide
# devfs -m /wwwjail/dev rule apply path urandom unhide
# ls -l /wwwjail/dev
7. Подготовить пробный индексный файл:
# echo '<html><body>Test</body></html>' > /wwwjail/www/index.html
8. Испытать работоспособность nginx'а в chroot-окружении:
# cd ~
# chroot /wwwjail /bin/nginx
# wget http://localhost/
# cat index.html
# cat /wwwjail/logs/access.log
# chroot /wwwjail /bin/nginx -s quit
4. Перенос nginx'а в настоящий джейл
1. В файле /wwwjail/etc/nginx.conf параметр http/server/listen задать в виде "192.168.101.1:80"
2. Испытать работоспособность nginx'а в jail-окружении
# cd ~
# ifconfig -l
# ifconfig rl0 inet alias 192.168.101.1/32
# ifconfig
# jail -c path=/wwwjail host.hostname=example.com \
ip4.addr=192.168.101.1 command=/bin/nginx
# ps -A
# jls
# wget http://192.168.101.1/
# cat /wwwjail/logs/access.log
Замените example.com на доменное имя вашего сайта, rl — на имя драйвера сетевой карты (ifconfig -l, ifconfig).
3. В правила файерволла добавить следующие строки:
# port forwarding from internet to jails /sbin/ipfw 100 add fwd 192.168.101.1,80 tcp from any to 1.1.1.1/32 80 /sbin/ipfw 101 add fwd 192.168.101.1,443 tcp from any to 1.1.1.1/32 443
Замените 1.1.1.1 на IP-адрес вашего сайта. Числа 100 и 101 задают относительный приоритет правил и не имеют абсолютного смысла; у меня эти два правила предпоследние.
4. Сделайте так, чтобы новые правила файерволла вступили в силу.
Следующие команды выполнить на внешней машине, например из Cygwin под Windows:
# cd /
# wget http://1.1.1.1/
# ls -l
# cat index.html
# rm index.html
5. Остановить временный джейл и включить в автозагрузку запуск джейла с nginx'ом
# kill -QUIT `cat /wwwjail/logs/nginx.pid`
# jls
# nano /etc/rc.conf
добавить следующие строки:
ifconfig_rl0_alias0="inet 192.168.101.1/32" jail_enable="YES" jail_list="wwwjail" jail_wwwjail_hostname="example.com" jail_wwwjail_ip="192.168.101.1" jail_wwwjail_rootdir="/wwwjail" jail_wwwjail_devfs_enable="YES" jail_wwwjail_devfs_ruleset="devfsrules_jail" jail_wwwjail_fdescfs_enable="NO" jail_wwwjail_procfs_enable="NO" jail_wwwjail_exec_start="/bin/nginx" jail_wwwjail_exec_stop="/bin/nginx -s quit"
# umount /wwwjail/dev
# /etc/rc.d/jail start wwwjail
# jls
6. Ещё раз проверить работоспособность джейла wget'ом извне; после чего перезагрузить сервер и провести этот тест ещё раз. После этого удалить временный каталог, в котором происходила сборка nginx:
# cd ~
# ls -l
# rm -rf nginx-build
5. Сборка и включение сервера PHP-FPM
Собрать статический PHP непросто, но возможно. FreeBSDшный ld не понимает параметра "-all-static", в отличие от скрипта libtool. php-fpm и nginx будут обмениваться данными через UNIX domain socket по протоколу FastCGI.
# cd /usr/ports/graphics/gd
# make install clean
# cd ../../textproc/libxml2
# make install clean
# cd ../../ftp/curl
# make install clean
# cd ../../math/gmp
# make install clean
# cd ../../security/libmcrypt
# make install clean
# cd ../../databases/sqlite3
# make install clean
# cd ~
# mkdir php-fpm-build
# cd php-fpm-build
# wget http://us2.php.net/get/php-5.4.9.tar.bz2/from/this/mirror
# mv mirror php-5.4.9.tar.bz2
# wget http://.../build_php.sh
# chmod +x build_php.sh
#!/usr/local/bin/bash
cd /root/php-fpm-build
rm -rf php-5.4.9
tar jxf php-5.4.9.tar.bz2
cd php-5.4.9
LDFLAGS="-Wl,-s -Wl,-static -static-libgcc" \
./configure --enable-static --disable-shared \
--enable-fpm \
--with-fpm-user=www --with-fpm-group=www \
--prefix=/ --with-config-file-path=/etc \
--localstatedir=/logs \
--without-pear --disable-phar \
--with-gd --with-jpeg-dir --with-freetype-dir --enable-exif \
--with-openssl --with-curl --with-mcrypt --with-mhash \
--with-zlib --with-bz2 --enable-bcmath --with-gmp \
--with-gettext --enable-mbstring --enable-calendar \
--with-mysql=mysqlnd --with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd --with-pdo-sqlite
if [ "$?" -ne "0" ]; then
echo "=== build script: failed to configure PHP ==="
exit 1
fi
LDFLAGS="-Wl,-s -Wl,-static -all-static -static-libgcc" make all
if [ "$?" -ne "0" ]; then
echo "=== build script: failed to make PHP ==="
exit 1
fi
rm -rf /wwwjail2
mkdir /wwwjail2
make INSTALL_ROOT=/wwwjail2 install
if [ "$?" -ne "0" ]; then
echo "=== build script: failed to install PHP ==="
exit 1
fi
echo "=== build script: OK ==="# ./build_php.sh
# cd /wwwjail2
# ls -l sbin
# file sbin/php-fpm
# cp sbin/php-fpm ../wwwjail/bin/
# cp etc/php-fpm.conf.default ../wwwjail/etc/
# cd ..
# rm -rf wwwjail2
# cd wwwjail/etc
# cp php-fpm.conf.default php-fpm.conf
# cp ~/php-fpm-build/php-5.4.9/php.ini-production php.ini.default
# cp php.ini.default php.ini
# nano php.ini
Задать следующие опции:
date.timezone = UTC short_open_tag = On
# nano php-fpm.conf
Задать следующие опции:
pid = /logs/php-fpm.pid error_log = /logs/php-fpm.log daemonize = yes events.mechanism = kqueue listen = /tmp/fastcgi.socket listen.owner = www listen.group = www listen.mode = 0666 pm = static pm.max_children = 5 pm.max_requests = 100 request_terminate_timeout = 10m
# jls
# jexec 1 /bin/php-fpm
# ps -A
# cat /wwwjail/logs/php-fpm.log
# cd /wwwjail/etc
# nano nginx.conf
location ... {
location ~ \.php$ {
root /www;
fastcgi_pass unix:/tmp/fastcgi.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/fastcgi_params;
}
location ~ \.inc$ {
# Protect PHP include files from prying eyes
return 404;
}
}# cd ..
# kill -HUP `cat logs/nginx.pid`
# cat logs/error.log
# echo '<?php phpinfo(); ?>' > www/index.php
# cat www/index.php
# cd ~
# wget http://192.168.101.1/index.php
# rm -rf php-fpm-build
# nano /etc/rc.conf
Добавить следующую строку:
jail_wwwjail_exec_afterstart1="/bin/php-fpm"
Проверить, что процесс php-fpm корректно завершается при останове джейла
и что джейл корректно запускается с nginx и php-fpm:
# /etc/rc.d/jail stop wwwjail
# ps -A
# /etc/rc.d/jail start wwwjail
# ps -A
6. Нюансы администрирования
nginx перечитывает свой конфиг по сигналу SIGHUP. Ошибки конфига пишутся в журнал error.log (если были ошибки, web-сервер остаётся со старыми настройками).
php-fpm перечитывает свой конфиг и php.ini по сигналу SIGUSR2. Дочерние процессы порождаются только с помощью fork(2), при этом execve(2) не применяется.
SIGUSR2 используется в nginx для других целей — для бинарного обновления web-сервера без прерывания обслуживания клиентов: http://wiki.nginx.org/CommandLine#Upgrading_To_a_New_Binary_On_The_Fly
Желательно настроить логротацию как описано в newsyslog(8). Оба сервера переоткрывают свои логи по SIGUSR1.