Хотите воспользоваться скриптом автоматической установки? Переходите к скрипту
Не хотите читать предисловие – можно сразу перейти к настройке.
Предисловие
В последнее время в интернете распространяется стойкое убеждение, что сервер apache тормозной и пожирает кучу памяти, и если ты хочешь нормальную производительность для своего сервера - ставь nginx + apache или еще лучше nginx в голом виде и будет тебе счастье. И если надо http/2 - тоже ставь nginx.
Неужели все так плохо с apache?
NGINX лучше APACHE. Так ли это?
Неужели разработчики Apache не могут решить проблему ругаемого везде режима prefork? Неужели прошло столько времени и никто не предпринял ничего для решения известной проблемы?
Давайте разберемся – в старых версиях apache для каждого обращения к серверу выделялся отдельный процесс. В каждом процессе обрабатывался только один поток на одно соединение. В каждом процессе загружался модуль php и все библиотеки, которые были вместе с ним установлены.
Что это значит?
Предположим загружается одна страница сайта, на которой у нас есть подгрузка картинок, стилей css, js библиотек и может быть еще каких-либо вспомогательных файлов (видео или аудио). На загрузку каждого статического файла (например картинки или файла стилей CSS) apache создавал отдельный поток, в котором загружал модуль php и все сопутствующие библиотеки. Все это долго и чрезвычайно расточительно по потреблению памяти. И самое главное – зачем загружать php, если apache просто должен вернуть файл, который у нас хранится на сервере?
Почему Nginx такой хороший?
Да просто потому что для вызова php он использует интерфейс php-cgi (php-fpm), а для обслуживания статики используются потоки, которые менее ресурсоемки, нежели процессы системы. При запуске php его память не смешивается с памятью, потребляемой сервером.
А что в apache нельзя было сделать что-то подобное?
Вы не поверите!...
Проблема была давно понятна и так же давно эту проблему попытались решить. Долгое время решение носило статус беты, но уже несколько лет оно перешло в статус stable и начиная в версии Apache 2.4.17 устанавливается по умолчанию в новых установках сервера. Apache имеет модульную структуру и тот модуль, который отвечает за способ приема запросов и их обработки называется MPM (мульти-процессный модуль).
По-умолчанию в старых версиях apache используется MPM prefork, который создает отдельный процесс в системе на каждое обращение к серверу. Сейчас доступны MPM worker и MPM event. Самый современный и экономный в плане ресурсов памяти и процессора - это MPM event. Именно он устанавливается по умолчанию в новых версиях apache (начиная с 2.4.17).
http/2
Начиная с версии 2.4.17, в apache доступна возможность использовать http/2 для всех соединений. Для этого должен быть включен MPM event и сайт должен использовать https.
Использование MPM event означает, что нельзя использовать php в традиционном режиме в виде модуля (хотя такая возможность существует и эта связка даже запустится на тестовых сайтах). PHP в виде модуля с MPM event приведет к периодическим падениям и ошибкам работы с памятью.
Лучше всего в связке с MPM event показывает себя PHP-FPM. Эта комбинация дает нам, то чем похваляются любители NGINX. Это малое потребление памяти, ресурсов процессора и отдача статических страниц без загрузки PHP и сопутствующих библиотек. Такая комбинация показывает в реальном окружении производительность сравнимую с производительностью чистого NGINX + PHP-FPM.
А если нет разницы - зачем ставить что-то другое?
В реальном применении привычность и стабильность поведения сервера значит очень многое. Apache – это стандарт де-факто практически для любой системы и Joomla в частности. Работа с файлами htaccess описана практически в каждом руководстве.
В синтетических тестах комбинация apache+php-fpm показывает сравнимое с NGINX потребление ресурсов и скорость ответа. Реальная скорость работы будет зависеть от опытности системного администратора и конфигурации физического сервера, на котором исполняются программы.
По моим опытам в нагруженных системах комбинация apache+php-fpm значительно превосходила традиционную комбинацию nginx + apache (это оказалось самой тормознутой комбинацией из всех – хуже был только apache + mod_php) и особо не уступала чистому NGINX.
Поэтому лично я в своих серверах использую именно такую комбинацию.
Как настроить apache + php-fpm + http/2?
А вот здесь лично меня ожидало жестокое разочарование. Несмотря на то, что в интернете существует не одно описание настройки подобных комбинаций, как оказалось – никто из авторов не утруждал себя реальными тестами на боевых серверах. Логи не разделялись по виртуальным хостам, а система все равно периодически падала по неизвестным причинам. Потоки php не убивались, как это должно было быть и в результате вся система вела себя нестабильно. Хотя на тестовых сайтах все работало чудесно.
Огромное количество времени ушло на понимание причин такого поведения и способов решения. Как оказалось, рабочего решения в интернете не существует (ну или я не умею гуглить, яндексить и бинговать). Про ProxySet disablereuse=on почему-то никто в интернете не пишет... (теперь в интернете гуглится мой вопрос и мой же ответ на stackoverflow.com). Спасибо ребятам из systemintegra.ru за то, что помогли разобраться в проблеме. Опрос знакомых сисадминов к сожалению ни к чему не привел...
В результате родилось это руководство, по которому вы сумеете самостоятельно установить и настроить сервер apache, который поддерживает соединение по протоколу http/2, использует php-fpm и MPM event. На данный момент времени это одна из самых стабильных, и эффективных конфигураций apache, которые можно использовать на рабочем сервере.
Если вы хотите отблагодарить автора за его труд - я могу порекомендовать хороший хостинг для ваших VPS - https://firstvds.ru/
При покупке сервера вы можете использовать промокод 648341969
. Вы получите скидку и отблагодарите меня за счет реферальной программы. Хостинг хороший и надежный. Только выбирать надо сервера с SSD дисками.
В качестве операционной системы выберем CentOS.
Начало установки
Для установки всего программного обеспечения позднее будет выложен скрипт, который значительно облегчит весь процесс.
Далее детально мы описываем сам процесс, следуя которому, вы сумеете полностью настроить VPS для использования в качестве оптимизированного рабочего вебсервера.
Начинаем с обновления установленной системы CentOS.
yum update
Для дальнейшей работы нам понадобится утилита wget. Чаще всего она уже установлена, но в минимальном варианте CentOS ее может не быть. Поэтому поставьте ее (или убедитесь что она уже установлена).
yum install wget
Теперь нужно проверить – выключен ли selinux?
Эта проверка важна на физических серверах, виртуальных машинах и в системе виртуализации KVM. Если сервер OpenVZ, то можно даже не проверять – там selinux отключен по умолчанию.
Команда sestatus
показывает включен ли selinux.
Если включен - его надо отключить в файле: /etc/sysconfig/selinux
Найти строку и установить параметр:SELINUX=disabledsestatus
Устанавливаем любимый файловый менеджер:
yum install mc
Устанавливаем локаль utf-8, чтобы корректно отображался русский шрифт и различные спец символы (в частности те, которые используются mc).
localectl set-locale LANG=en_US.UTF-8
На случай если подключение будет через локаль windows ubuntu и если локали не совпадут – то все переключится на ANSI кодировку. Локали должны совпадать. Поэтому убедитесь, что локаль вашей windows системы совпадает с локалью на сервере (по умолчанию в windows включается русская локаль). Установите одинаковые локали везде.
С windows компьютеров доступ к серверам привычно осуществляется с помощью программы Putty. Для удобного использования лучше создать ключи доступа.
генерируем ключ rsa:
ssh-keygen -t rsa
cd .ssh
если нет файла authorized_keys:
cp id_rsa.pub authorized_keys
Если такой файл есть:
cat id_rsa.pub >> authorized_keys
Не забываем установить права доступа на указанный файл:
chmod 600 authorized_keys
Забираем приватный ключ id_rsa к себе на локальный компьютер.
Самый простой способ – скопировать через буфер обмена себе на компьютер и создать новый файл с этим ключом.
Затем нужно будет преобразовать файл в формат, пригодный для использования программой putty. Если вы будете пользоваться системой bash на windows – можете обойтись без промежуточных преобразований.
Преобразование осуществляется программой puttygen.exe.
Получить саму программу putty и все сопутствующие утилиты можно по ссылке https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
Устанавливаем (или убеждаемся что они уже установлены) программы cronie
и logrotate
:
yum install cronie
yum install logrotate
Установка apache
Устанавливаем репозитарий epel. Полностью epel репозиторий называется так — Extra Packages for Enterprise Linux. Это хранилище пакетов, созданное группой специалистов операционной системы Fedora. Пакеты из epel репозитория никогда не конфликтуют и не переустанавливают базовые пакеты RHEL.
yum install epel-release
Теперь установим репозитарий codeit для получения последних версий apache:
cd /etc/yum.repos.d
wget https://repo.codeit.guru/codeit.el`rpm -q --qf "%{VERSION}" $(rpm -q --whatprovides redhat-release)`.repo
yum install httpd mod_ssl
systemctl enable httpd
systemctl start httpd
Если у вас установлен firewall – конфигурируем его для открытия портов web сервера:
firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --zone=public --permanent --add-service=https
firewall-cmd --reload
делаем рестарт сервера
apachectl restart
На случай если получаем сообщение по типу httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
при перезапуске httpd (сервера апача), идем и в файле /etc/httpd/conf/httpd.conf
ищем вот эти строки:
ищем вот эти строки:
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
ServerName пишем сюда IP адрес сервера
После ServerName прописываем IP адрес нашего сервера.
В файле /etc/httpd/conf.modules.d/00-proxy.conf
лучше будет закомментировать этот модуль#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
Практически наверняка вы его не будете использовать.
А лишние подлюченные модули только создают проблемы.
Установка PHP
Если у вас уже был установлен php в виде модуля апача, то перед установкой php-fpm нужно будет удалить предыдущие версии php:
yum remove mod_php* php*
Для установки новой версии php в CentOS приходится использовать сторонний репозитарий.
Для CentOS на выбор есть два популярных репозитария: webtatic и Remi. После некоторого тестирования и реального использования в боевом сервере репозитарий от Remi показал себя наиболее полным и стабильно поддерживаемым. Поэтому при выборе репозитария я советую использовать Remi.
Если хотите установить из репозитария webtatic (Сайт проектка https://webtatic.com/), инструкция здесь:
Команда установки:
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
yum install php72w-fpm php72w-opcache php72w-cli php72w-gd php72w-mbstring php72w-mcrypt php72w-mysqlnd php72w-xml php72w-soap php72w-xmlrpc
Если устанавливать через репозитарий Remi, то инструкция такая:
wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm
rpm -Uvh remi-release-7*.rpm
yum install yum-utils
Выбираем какую версию php будем устанавливать:
yum-config-manager --enable remi-php72
Теперь ставим PHP:
yum install php-fpm php-opcache php-cli php-gd php-mbstring php-mcrypt php-mysqlnd php-xml php-soap php-xmlrpc
После установки php-fpm надо будет еще правильно его настроить. Идеи настройки были взяты из руководства https://www.stephenrlang.com/2018/02/centos-7-apache-2-4-with-php-fpm/ и доработаны для стабильной работы в условиях боевого сервера. К сожалению, если полностью скопировать настройки оттуда – сервер ведет себя нестабильно.
Создаем файл /etc/httpd/conf.d/php.conf
со следующим содержимым:
# Tell the PHP interpreter to handle files with a .php extension
# Proxy declaration
<Proxy "unix:/var/run/php-fpm/default.sock|fcgi://php-fpm">
ProxySet disablereuse=on connectiontimeout=10 timeout=60
</Proxy>
# Redirect to the proxy
<FilesMatch \.php$>
SetHandler proxy:fcgi://php-fpm
</FilesMatch>
#
# Allow php to handle Multiviews
#
AddType text/html .php
#
# Add index.php to the list of files that will be served as directory
# indexes.
#
DirectoryIndex index.php
#
# Uncomment the following lines to allow PHP to pretty-print .phps
# files as PHP source code:
#
#<FilesMatch \.phps$>
# SetHandler application/x-httpd-php-source
#</FilesMatch>
#<LocationMatch "/status">
# SetHandler proxy:fcgi://php-fpm
#</LocationMatch>
#ProxyErrorOverride on
Директива ProxyErrorOverride on
нужна для нормальной работы кастомных ошибок, которые настраиваются через htaccess в каждом сайте с помощью директивы ErrorDocument 404. Нужно учитывать, что в этом случае вместо 500 ошибок так же будет выводиться кастомная страница или стандартное сообщение об ошибке Apache. Если для написания сайта используется php фреймворк (например Laravel или Joomla) лучше оставить директиву ProxyErrorOverride
отключенной – иначе сайт может работать неверно (например не будет работать перевод сайта в offline). Связано это с действием директив php throw. В том случае, если вы пишите сайт на голом php – возможно включение этой директивы поможет вам в работе. Ее можно включить на уровне виртуальных хостов (и это самый лучший способ так сделать).
Теперь приступаем к редактированию файла /etc/php-fpm.d/www.conf
Ищем в нем строку listen = 127.0.0.1:9000
, закрываем ее комментарием и добавляем строки, которые указаны ниже. В итоге должно получиться вот так:
listen = /var/run/php-fpm/default.sock
listen.allowed_clients = 127.0.0.1
listen.owner = apache
listen.group = apache
listen.mode = 0660
user = apache
group = apache
Если вы хотите чтобы в apache логи php-fpm разбивались индивидуально по сайтам, а не сваливались в одну кучу в одном файле, нужно будет закомментировать еще две строки в этом же файле (/etc/php-fpm.d/www.conf
):
;php_admin_value[error_log] = /var/log/php-fpm/www-error.log
;php_admin_flag[log_errors] = on
Если есть экзотическое желание заставить работать страницы .html как .php (чтобы в них могли исполняться php скрипты), то придется исправить еще одну строку в этом файле:
security.limit_extensions = .php .html
Здесь мы добавляем расширение .html для того, чтобы в нем могли исполняться php скрипты.
Директории для сессий при установке php могут быть не созданы. Проверьте в конце файла наличие строк:
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache
и если необходимо - создайте эти подкаталоги:
mkdir /var/lib/php/session
mkdir /var/lib/php/wsdlcache
Теперь проверим что конфигурационный файл php-fpm корректен:
php-fpm -t
Если надо установить отладку (учтите что для версии php 7.3 пока еще отладка не доступна), установите пакет rpm php72w-pecl-xdebug (не делайте этого на рабочем сервере! – это только дома для тестирования!):
yum install php72w-pecl-xdebug
Пишу еще раз! Не устанавливайте xdebug на продакшен сервере! Это только для домашнего тестирования и отладки!
Теперь запустим PHP и сделаем так, чтобы при перезагрузке сервера, он так же запускался автоматически:
systemctl enable php-fpm
systemctl start php-fpm
Продолжаем настройку PHP – в файле /etc/php.ini
найдите эти параметры и исправьте на приведенные значения (или на те, которые вас устроят):
memory_limit = 256M
upload_max_filesize = 32M
post_max_size = 32M
Устанавливаем MariadDB вместо MySQL
cd /etc/yum.repos.d/
echo "# MariaDB 10.3 CentOS repository list - created 2018-10-22 16:03 UTC" > MariaDB.repo
echo "# http://downloads.mariadb.org/mariadb/repositories/" >> MariaDB.repo
echo "[mariadb]" >> MariaDB.repo
echo "name = MariaDB" >> MariaDB.repo
echo "baseurl = http://yum.mariadb.org/10.3/centos7-amd64" >> MariaDB.repo
echo "gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB" >> MariaDB.repo
echo "gpgcheck=1" >> MariaDB.repo
yum install MariaDB-server MariaDB-client
systemctl start mariadb
systemctl enable mariadb
Теперь выполним настройки безопасности MySQL и установим пароль доступа к ней. Запускаем команду:
mysql_secure_installation
Когда будет задан вопрос о root пароле, то устанавливаем его. На остальные вопросы просто жмем Enter.
После выполнения этой процедуры лучше разрешить подключение к mysql только через локальные подключения.
В конфигурационном файле /etc/my.cnf.d/server.cnf в разделе [mysqld] раскомментируем строку bind-address и задаем значение 127.0.0.1:
bind-address=127.0.0.1
Полезная утилита zip для разархивирования установщиков скриптов:
yum install unzip
Нужно создать папку для сайта с именем 000-default в директории /var/www/html . Затем создать из нее сайт.
Это на случай, если кто-то решит воспользоваться плохим конфигурированием вашего сервера. По умолчанию для сайтов, которые не существуют на вашем сервере, нужно возвращать 403 код ошибки. Иначе, по вашей ошибке или по злому намерению других людей, возможно создание дублей ваших сайтов.
Установка certbot на CentOS
yum install python2-certbot-apache
Настройка редактора по умолчанию
Если вы будете менять crontab, то лучше поменять vim (стандартный редактор, установленный по умолчанию) на что-то более удобоваримое, например, редактор nano или стандартный редактор mc - mcedit.
Если выберете nano – вначале убедитесь что он установлен:
yum install nano
Затем в файле .bashrc
добавить строку в конце
export EDITOR=nano
или
export EDITOR=mcedit
В зависимости от выбранного редактора. (Я советую mcedit - он проще)
Установка времени
Изменим время на московское:
mv /etc/localtime /etc/localtime.bak
ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime
Генерируем самоподписанный сертификат SSL на 10 лет:
openssl req -new -days 3650 -x509 -nodes -out /etc/pki/tls/certs/localhost.crt -keyout /etc/pki/tls/private/localhost.key
Указываем только страну, остальное Enter.
Автоматическая установка с помощью скрипта
В результате развития указанного подхода был создан набор скриптов RISH, который позволяет установить данную конфигурацию на сервер и выполнять основные задачи управления им.
Ссылка на это решение сайт RISH