UMGUM.COM (лучше) 

Apache + PHP ( Инсталляция и настрока Apache + PHP. )

26 марта 2010  (обновлено 31 января 2015)

OS: Linux Debian Lenny/Squeeze.
Application: Apache2, PHP5 + SuPHP.

Обновляем набор системного и прикладного программного обеспечения:

# aptitude update
# aptitude full-upgrade

Устанавливаем сервер приложений и предположительно необходимый набор компонентов:

# aptitude install apache2 libapache2-mod-suphp php5-cgi
# aptitude install php5-curl php5-gd php5-imagick php5-mcrypt imagemagick php5-imap php5-sasl php5-xmlrpc

Инсталляция потянет "apache2-mpm-worker". Это модуль "поточной" обработки запросов, то есть, в нем каждый запрос обслуживается в отдельном потоке одного из дочерних процессов. Потоки - более лёгкие для ОС объекты, чем процессы, они более эффективно используют память и переключения контекста для них происходят быстрее. Однако, из-за того что каждый поток имеет доступ ко всей памяти процесса, "worker" MPM (Multi-processing module) более подвержен сбоям: сбой одного потока может повлечь падение всего процесса, в котором находился этот поток (именно поэтому "worker" MPM запускает несколько дочерних процессов с несколькими потоками в каждом). По причине потенциально большей неустойчивости выбранного "worker" необходимо будет предусмотреть механизм слежения за состоянием сервиса и принятием мер в случае сбоя в работе.

"Mod-suphp" представляет из себя своего рода "обёртку" для запуска PHP как CGI приложения для отрабатывания пользовательских скриптов с правами владельца файла. Практически то же самое можно получить с помощью ручной настройки комбинации Apache2+SUExec+PHP-CGI+FastCGI, но мы положимся на опыт и знания умных людей, которые подготовили для нас работоспособное решение.

При инсталляции Apache обычно автоматически создаётся пользователь "www-data" и одноимённая группа. Если этого не случилось (что уже говорит о том, что процесс идёт не гладко) - исправьте это, так как дальнейшие настройки будем осуществлять отталкиваясь от того, что сервер Apache запускается от имени пользователя и группы "www-data:www-data".


При инсталляции по умолчанию активны не все модули, которые нам в дальнейшем понадобятся. Дополняем конфигурацию, создавая символические ссылки (если они уже не созданы, конечно):

# ln -s /etc/apache2/mods-available/actions.load /etc/apache2/mods-enabled/actions.load
# ln -s /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled/rewrite.load
# ln -s /etc/apache2/mods-available/include.load /etc/apache2/mods-enabled/include.load
# ln -s /etc/apache2/mods-available/headers.load /etc/apache2/mods-enabled/headers.load
# ln -s /etc/apache2/mods-available/suphp.load /etc/apache2/mods-enabled/suphp.load
# ln -s /etc/apache2/mods-available/suphp.conf /etc/apache2/mods-enabled/suphp.conf

Займёмся настройкой web-сервиса. Припомним, что корневой конфигурационный файл несет в себе лишь базовые настройки, а все остальное в момент запуска сервера Apache подключается из указанных мест соответствующими директивами. Пробежимся по конфигурационным файлам и убедимся, что файлы сайтов лежат именно там, где им определено, возможен запуск сервера в конфигурации "по умолчанию" и при запросе сервер отвечает.

Проще говоря, в конфигурации "по умолчанию", файлы данных расположены в директории "/var/www" и при запросе на порт #80 сервер ответит "тестовой страницей", нечто вроде "It works!". Если это случилось, то сервер жив и готов подвергнуться дальнейшей настройке.

Web-сервер Apache2 на начальном этапе в настройке практически не нуждается, базовые настройки выставлены достаточно оптимально для среднестатистических запросов, а вопросы тонкой настройки мы будем рассматривать позже, применительно к работающей полнофункциональной схеме.

Для удобства и исключения сомнений в дальнейшем в конфигурационном файле "/etc/apache2/conf.d/charset" выставим значение кодировки отдаваемых страниц "по умолчанию" (персональные параметры ресурсов позже можно будет переопределить в конфигурации "виртуальных ресурсов"):

AddDefaultCharset UTF-8

В конфигурационном файле "/etc/apache2/conf.d/security" укажем базовые параметры корневой директории ресурсов с наследованием потомками (персональные параметры ресурсов позже можно будет переопределить в конфигурации "виртуальных ресурсов"):

<Directory /var/www>
  DirectoryIndex index.php index.html
  Options +FollowSymLinks -Indexes
  # запрещаем переопределение конфигурации сервера в файле .htaccess из соображений увеличения производительности
  AllowOverride None
  Order deny,allow
  Deny from all
</Directory>

Опишем режим использования модуля "SUPHP" в конфигурационном файле "/etc/apache2/mods-available/suphp.conf". Здесь мы велим серверу Apache2 при наличии модуля "mod_suphp" зарегистрировать привязку расширений файлов за типом ресурсов, далее к типу ресурсов привязываем обработчик таковых, и потом ограничиваем работу модуля целевой директорией:

<IfModule mod_suphp.c>
  AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
  suPHP_AddHandler application/x-httpd-php
  <Directory /var/www>
    suPHP_Engine on
  </Directory>
</IfModule>

В конфигурационном файле Apache2 по адресу "/etc/apache2/conf.d/security" приведем ряд переменных к следующему виду:

ServerTokens Minimal
ServerSignature Off
TraceEnable Off

Опишем конфигурацию модуля "SUPHP" в конфигурационном файле "/etc/suphp/suphp.conf":

[global]
; Path to logfile
logfile=/var/log/apache2/suphp.log

; Loglevel
loglevel=info

; User Apache is running as
webserver_user=www-data

; Path all scripts have to be in
docroot=/var/www

; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false

; Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true

; Send minor error messages to browser
errors_to_browser=false

; PATH environment variable
env_path=/bin:/usr/bin

; Umask to set, specify in octal notation
umask=0027

; Minimum UID
min_uid=1000

; Minimum GID
min_gid=33

[handlers]
; Handler for php-scripts
application/x-httpd-php=php:/usr/bin/php-cgi

; Handler for CGI-scripts
x-suphp-cgi=execute:!self

Директива "umask" в конфигурационном файле, могущая "вынести мозг" начинающим администраторам, это не значение правил доступа к создаваемым объектам, а маска, накладываемая на правила доступа "по умолчанию", то есть на значения для файла в "666" или директории "777"; в итоге значение "umask" в "027" даст при наложении на "666", для создаваемого PHP-файла, "640" (владельцу можно все, группе только чтение, другим запрещено все) и для директории, создаваемой PHP, "750" (владельцу разрешено все, группе просмотр и чтение, другим запрещено все).

Опишем в конфигурационных файлах Apache2 наши виртуальные ресурсы и укажем в них на режим запуска исполняемых скриптов. Создадим в директории "/etc/apache2/sites-available/" файлы "u000.local" и "u001.local" примерно со следующим содержимым, варьирующимся в зависимости от имён ресурсов и мест их расположения:

# touch /etc/apache2/sites-available/u1000
# touch /etc/apache2/sites-available/u1001

Пример содержания конфигурационного файла для виртуальной площадки пользователя "u1000":

<VirtualHost *:80>
  ServerName u1000.local
  ServerAlias www.u1000.local
  ServerAdmin admin@u1000.local
  DocumentRoot /var/www/u1000/www
  # AddDefaultCharset windows-1251
  suPHP_ConfigPath /var/www/php/u1000
  # SetEnv PHP_INI_SCAN_DIR /var/www/php/u1000/conf.d
  <Directory /var/www/u1000/www>
    Options +ExecCGI
    # AllowOverride All
    Order allow,deny
    Allow from all
  </Directory>
  LogLevel warn
  ErrorLog /var/www/u1000/log/apache.error.log
  CustomLog /var/www/u1000/log/apache.access.log combined
</VirtualHost>

Для некоторых версий модуля в пользовательской конфигурации можно указать принудительно, от имени какого пользователя и группы запускается скрипт с помощью директивы "suPHP_UserGroup user groupe". В нашей этого делать не нужно, скрипты будут исполняться от имени того пользователя - владельца исполняемого файла.

Выше опцией "suPHP_ConfigPath" мы указываем месторасположение индивидуального для площадки конфигурационного файла "php.ini". Модуль "suphp" каким-то своим способом подставляет его вместо системного, который по умолчанию располагается по адресу "/etc/php5/cgi/php.ini". Тут всё просто - каждой площадке выделяется по индивидуальному файлу "php.ini", в котором мы вольны задавать её параметры так вольно, как нам будет угодно.

Другая опция - "SetEnv PHP_INI_SCAN_DIR" - неактивна, но готова к применению. Она задаёт отличное от принятого по умолчанию "/etc/php5/conf.d/" месторасположение директории, содержимое которой добавляется к содержимому основного конфигурационного файла интерпретатора "php.ini".

Если опцию "SetEnv PHP_INI_SCAN_DIR" не использовать, как это делаю я, то загрузка конфигураций происходит в два этапа: вначале подключается индивидуальный файл "php.ini", месторасположение которого определено опцией "suPHP_ConfigPath", а вторым этапом загружаются динамически подключаемые файлы из места по умолчанию "/etc/php5/conf.d/". Это удобно в плане глобального применения настроек; чтобы мы не накрутили в индивидуальном "php.ini" площадки, всё можно переопределить в глобальной конфигурации, которая загрузится из "/etc/php5/conf.d/" уже после применения "php.ini". Удобно это так же и тем, что при установке дополнительных или обновлении уже работающих модулей не нужно менять настройки каждой площадки - достаточно сделать это один раз для содержимого "/etc/php5/conf.d/".

В случае активации опции "SetEnv PHP_INI_SCAN_DIR", указывающей на иное расположение динамически подключаемых конфигурационных файлов, мы получим для целевой площадки возможность полностью индивидуальной настройки. Это бывает полезно, когда из ста площадок только одной-двум нужна эксклюзивная конфигурация, конфликтующая с общепринятой на сервере. Понятно, что перед изменением режима необходимо сформировать содержимое целевой директории динамических конфигураций "/var/www/php/*/conf.d", а то подключать нечего будет.

Есть ещё возможность переписать значение переменных конфигурации непосредственно во время исполнения PHP-скрипта, но такому воздействию доступны далеко не все параметры, отчасти и потому, что это может быть запрещено предыдущими настройками в защитных целях.

Теперь займёмся непосредственно PHP-интерпретатором.

Скопируем в служебную директорию конфигурационный файлы интерпретатора PHP. Далее все работы будут проводится уже с ним:

# cp /etc/php5/cgi/php.ini /var/www/php/php.ini

Немного оптимизируем работу нашего сервера и ужесточим политики доступа на нашем сервере, усложнив работу желающим получить информацию о состоянии. Запретим исполнятся чему бы то ни было за пределами каталогов наших web-ресурсов. Запретим показ расширенной информации о наших ресурсах и сервере.

В используемом нами базовом конфигурационном файле PHP по адресу "/var/www/php/php.ini" приведем ряд переменных к следующему виду (чтение и применение параметров конфигурационного файла PHP производится последовательно, потому достаточно разместить свои параметры в конце файла, чтобы переопределить значения расположенные выше по тексту):

;; Custom global configuration ;;
max_execution_time = 90
max_input_time = 90
safe_mode = On
safe_mode_gid = On
allow_url_fopen = Off
allow_url_include = Off
enable_dl = Off
expose_php = Off
disable_functions = "exec, shell_exec, system, passthru, popen, proc_open, phpinfo, curl_exec, curl_multi_exec, parse_ini_file, show_source, ini_restore, com_load_typelib, symlink, eval"
mysql.allow_persistent = Off
pgsql.allow_persistent = Off

С глобальными настройками мы закончили, проработаем теперь методику создания индивидуальных конфигураций для PHP-интерпретатора.

Скопируем конфигурационный файл интерпретатора PHP в директории индивидуальных пользовательских конфигураций для принудительного запуска скриптов пользователя с указанными файлами (кстати, использование индивидуальных конфигурационных файлов PHP спасет нам конфигурацию при обновлении PHP, так как базовый конфигурационный файл инсталлятором злостно заменяется без вопросов):

# cp /var/www/php/php.ini /var/www/php/u1000/php.ini
# cp /var/www/php/php.ini /var/www/php/u1001/php.ini

Применим правила доступа к служебным файлам:

# chown -R root:ug1000 /var/www/php/u1000
# chown -R root:ug1001 /var/www/php/u1001
# chmod -R o-rwx /var/www/php/u1000 /var/www/php/u1001
# chmod -R g-w /var/www/php/u1000 /var/www/php/u1001

В создаваемых нами индивидуальных конфигурационных файлах "/var/www/php/u000/php.ini", "/var/www/php/u001/php.ini" и так далее, приведем ряд переменных к следующему виду или допишем их в конце конфигурационного файла для переопределения установленных "по умолчанию" в нем переменных (пример для площадки пользователя "u1000"):

;; Custom user configuragion ;;
open_basedir = /var/www/u1000
upload_tmp_dir = /var/www/u1000/tmp
session.save_path = /var/www/u1000/tmp

Создадим тестовые файлы на виртуальных площадках пользователей "/var/www/u1000/www/info.php" и "/var/www/u1001/www/info.php" со следующим содержимым:

# touch /var/www/u1000/www/info.php
# touch /var/www/u1001/www/info.php

<?php
  phpinfo();
?>

Размещаем символические ссылки в директории, откуда Apache2 берет конфигурационные файлы ресурсов:

# ln -s /etc/apache2/sites-available/u1000 /etc/apache2/sites-enabled/u1000
# ln -s /etc/apache2/sites-available/u1001 /etc/apache2/sites-enabled/u1001

Удаляем символическую ссылку на конфигурацию "по умолчанию", что досталась нам от инсталлятора Apache2, чтобы не вносить путаницу в дальнейшее конфигурирование:

# rm /etc/apache2/sites-enabled/default

Заставляем Apache2 перечитать свои конфигурационные файлы и принять изменения:

# /etc/init.d/apache2 reload

Если все, что мы проделали выше - правильно, то при запросе в браузере целевого ресурса мы сможем узреть вывод функции phpinfo().

По завершению конфигурирования Apache закрываем от постороннего взгляда директорию конфигурации:

# chown -R root:root /etc/apache
# chmod -R o-rwx /etc/apache

После проделанных описанных выше работ мы получаем web-сервер в базовой конфигурации с разделением пользовательских ресурсов. Учитывая то, вызов системных функций отключён, разрешения выставлены достаточно жёстко, web-сервер имеет право только на чтение данных, а исполняемые скрипты запускаются с правами владельца файлов, можно полагать, что пользовательские ресурсы достаточно надёжно изолированны друг от друга.


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )