<div id="articleBody" itemprop="articleBody"> <div itemscope="" itemtype="http://schema.org/ImageObject" itemprop="image" style="display: none;"> <link itemprop="url contentUrl" href="https://www.dmosk.ru/img/schema.org/instruktions/tmico_centos8-mega-webserver.png"> </div> <h1 itemprop="headline name">NGINX + Apache (httpd) + MariaDB (MySQL) + PHP + PHP-FPM (fastCGI) + FTP + PHPMyAdmin + Memcached + Postfix на CentOS 8</h1> <label class="checkbox-switch checkbox-switch-switched"> <div class="switch-box"> <div class="switch-tumb"> </div> <div class="switch-text">Описание</div> </div> <input type="checkbox"> </label> <div class="checkbox-switch-after"> </div> <p style="display: none;">Веб-сервер, настроенный по данной инструкции можно будет использовать для размещения собственных сайтов в локальной сети или сети Интернет. Данная инструкция проверена для CentOS 8.</p> <p style="display: none;">Тематические термины: <a href="/terminus.php?object=linux">Linux</a>, <a href="/terminus.php?object=centos">CentOS</a>, <a href="/terminus.php?object=nginx">NGINX</a>, <a href="/terminus.php?object=apache">Apache</a>, <a href="/terminus.php?object=mysql">MySQL</a>, <a href="/terminus.php?object=mariadb">MariaDB</a>, <a href="/terminus.php?object=php-fpm">PHP-FPM</a>, <a href="/terminus.php?object=ftp">FTP</a>, <a href="/terminus.php?object=phpmyadmin">phpMyAdmin</a>, <a href="/terminus.php?object=memcached">Memcached</a>, <a href="/terminus.php?object=postfix">Postfix</a>.</p> <p style="display: none;">Содержание:</p> <p style="display: none;"> <a class="self" href="#gen">Общая настройка системы</a> <br> <a class="self" href="#nginx">Установка NGINX</a> <br> <a class="self" href="#phpfpm">Установка PHP и PHP-FPM</a> <br> <a class="self" href="#sql">Установка MariaDB или MySQL</a> <br> <a class="self" href="#phpmyadmin">Установка phpMyAdmin</a> <br> <a class="self" href="#memcached">Установка Memcached</a> <br> <a class="self" href="#ftp">Установка и настройка FTP-сервера</a> <br> <a class="self" href="#apache">Apache (httpd)</a> <br> <a class="self" href="#postfix">Postfix</a> <br> <a class="self" href="#tuning">Тюнинг веб-сервера</a> <br> <a class="self" href="#firstsite">Создание первого сайта</a> </p> <h2> <a id="gen"> </a>Общая настройка системы</h2> <h3>Установка пакетов</h3> <p style="display: none;">1. Обновляем CentOS:</p> <div class="console"> <p>dnf update</p> </div> <p style="display: none;">2. Устанавливаем репозиторий EPEL и дополнительные пакеты для загрузки и распаковки:</p> <div class="console"> <p>dnf install epel-release wget unzip</p> </div> <h3>Время</h3> <p style="display: none;">1. Устанавливаем часовой пояс:</p> <div class="console"> <p>\cp /usr/share/zoneinfo/Europe/Moscow /etc/localtime</p> </div> <p style="display: none;"> <em>* данной командой мы установим часовой пояс по московскому времени.</em> </p> <p style="display: none;">2. Устанавливаем и запускаем службу для автоматической синхронизации времени:</p> <div class="console"> <p>dnf install chrony</p> </div> <div class="console"> <p>systemctl enable chronyd</p> </div> <div class="console"> <p>systemctl start chronyd</p> </div> <h3>Настройка безопасности</h3> <p style="display: none;">1. Отключаем SELinux:</p> <div class="console"> <p>sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config</p> </div> <div class="console"> <p>setenforce 0</p> </div> <p style="display: none;"> <em>* первая команда редактирует конфигурационный файл, чтобы <a href="/terminus.php?object=selinux">SELinux</a> не запускался автоматически, вторая — отключает его разово. Подробнее читайте статью <a href="/miniinstruktions.php?mini=selinux-centos">Как отключить SELinux</a>.</em> </p> <p style="display: none;">2. Открываем необходимые порты в <a href="/terminus.php?object=firewall">брандмауэре</a>:</p> <div class="console"> <p>firewall-cmd --permanent --add-port={80,443,8080}/tcp</p> </div> <div class="console"> <p>firewall-cmd --permanent --add-port={20,21,60000-65535}/tcp</p> </div> <div class="console"> <p>firewall-cmd --permanent --add-port={25,465,587}/tcp</p> </div> <div class="console"> <p>firewall-cmd --reload</p> </div> <p style="display: none;"> <em>* 80, 443 и 8080 порты для <a href="/terminus.php?object=web-server">веб-сервера</a>; 20, 21 порты нужны для работы FTP; </em>60000-65535<em> также необходимы для работы FTP (динамические порты для пассивного режима); 25, 465 и 587 порты нужны для работы почтового сервера по <a href="/terminus.php?object=smtp">SMTP</a>; последняя команда перезапускает firewalld, чтобы применить новые правила. Подробнее про <a href="/miniinstruktions.php?mini=firewalld-centos">настройку firewalld</a>.</em> </p> <h2> <a id="nginx"> </a>Установка NGINX</h2> <p style="display: none;">Устанавливаем NGINX:</p> <div class="console"> <p>dnf install nginx</p> </div> <p style="display: none;">Внесем небольшую корректировку в файл nginx.conf:</p> <div class="console"> <p>nano /etc/nginx/nginx.conf</p> </div> <p style="display: none;">В секцию http добавим строку:</p> <div class="editor"> <p>http {<br> ...<br> server_names_hash_bucket_size 64;<br> ....<br> }</p> </div> <p style="display: none;"> <em>* на практике, может встретиться ошибка <strong>could not build server_names_hash, you should increase server_names_hash_bucket_size: 32</strong>. Она возникает при большом количестве виртуальных серверов или если один из них будет иметь длинное название. Данная строка в конфиге исправит ситуацию.</em> </p> <p style="display: none;">Разрешаем автозапуск сервиса и запустим его:</p> <div class="console"> <p>systemctl enable nginx</p> </div> <div class="console"> <p>systemctl start nginx</p> </div> <p style="display: none;">Проверим, что веб-сервер работает. Для этого открываем браузер на другом компьютере, который находится в одной сети и вводим в адресной строке <a href="/terminus.php?object=ipaddr">IP-адрес</a> сервера. В итоге мы должны увидеть заголовок «Welcome to nginx!»:</p> <p style="display: none;"> <img alt="Заголовок Welcome to nginx!" src="https://www.dmosk.ru/img/instruktions/centos8-mega-webserver-01.jpg" style="width: 680px; height: 185px;" title="Welcome to nginx!"> </p> <p style="display: none;"> <em>* обратите внимание, что данное приветствие может иметь и другой вид.</em> </p> <h2> <a id="phpfpm"> </a>Установка PHP и PHP-FPM</h2> <p style="display: none;">Устанавливаем PHP и php-fpm следующей командой:</p> <div class="console"> <p>dnf install php php-fpm</p> </div> <p style="display: none;"> <em>* В CentOS 8 будет установлена версия php 7.2 и выше</em> </p> <p style="display: none;">Запускаем php-fpm и разрешаем его автозапуск:</p> <div class="console"> <p>systemctl enable php-fpm --now</p> </div> <h3>Настройка связки NGINX + PHP</h3> <p style="display: none;">Открываем файл для настройки виртуального домена по умолчанию:</p> <div class="console"> <p>vi /etc/nginx/nginx.conf</p> </div> <p style="display: none;">В секции <strong>location</strong> редактируем параметр <strong>index</strong> на следующее значение:</p> <div class="editor"> <p> location / {<br> index index.php index.html index.htm;<br> }</p> </div> <p style="display: none;"> <em>* добавляем <strong>index.php</strong> в начало списка. Если параметра <strong>index</strong> нет, создаем его.</em> </p> <p style="display: none;">А внутри секции <strong>server</strong> добавим следующее:</p> <div class="editor"> <p> location ~ \.php$ {<br> set $root_path /usr/share/nginx/html;<br> fastcgi_pass unix:/run/php-fpm/www.sock;<br> fastcgi_index index.php;<br> fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;<br> include fastcgi_params;<br> fastcgi_param DOCUMENT_ROOT $root_path;<br> }</p> </div> <p style="display: none;"> <em>* где <strong>/usr/share/nginx/html</strong> — корневой путь хранения скриптов; <strong>unix:/run/php-fpm/www.sock</strong> — файл для взаимодействия с php-fpm.</em> </p> <p style="display: none;">Открываем настройки php-fpm:</p> <div class="console"> <p>nano /etc/php-fpm.d/www.conf</p> </div> <p style="display: none;">Проверяем, что параметр listen настроен так:</p> <div class="editor"> <p>listen = /run/php-fpm/www.sock</p> </div> <p style="display: none;">... иначе, меняем значение. После перезагружаем php-fpm:</p> <div class="console"> <p>systemctl restart php-fpm</p> </div> <p style="display: none;"> <em>* в данном примере мы указываем, что php-fpm будет использовать сокетный файл <strong>/run/php-fpm/www.sock</strong> для взаимодействия. Этот файл мы указали выше в настройке NGINX.</em> </p> <p style="display: none;">Проверяем правильность настроек nginx:</p> <div class="console"> <p>nginx -t</p> </div> <p style="display: none;">И перезагружаем его:</p> <div class="console"> <p>systemctl restart nginx</p> </div> <p style="display: none;">Создаем index.php в каталоге сайта по умолчанию со следующим содержимым:</p> <div class="console"> <p>nano /usr/share/nginx/html/index.php</p> </div> <div class="editor"> <p><?php phpinfo(); ?></p> </div> <p style="display: none;">Открываем в браузере IP-адрес нашего сервера. Теперь мы должны увидеть сводную информацию по PHP и его настройкам, например:</p> <p style="display: none;"> <img alt="Информация о php (phpinfo)" src="https://www.dmosk.ru/img/instruktions/centos8-mega-webserver-02.jpg" style="width: 531px; height: 263px;" title="Информация о php (phpinfo)"> </p> <h2> <a id="sql"> </a>Установка MariaDB или MySQL</h2> <p style="display: none;">В данной статье мы установим MariaDB, но процедура установки и настройки MySQL аналогичная. Все расхождения будут отмечены явно в инструкции.</p> <p style="display: none;">Устанавливаем MariaDB следующей командой:</p> <div class="console"> <p>dnf install mariadb mariadb-server</p> </div> <p style="display: none;"> <em>* для установки mysql выполняем команду <strong>dnf install mysql</strong> </em> </p> <p style="display: none;">Разрешаем автозапуск и запускаем СУБД:</p> <div class="console"> <p>systemctl enable mariadb --now</p> </div> <p style="display: none;"> <em>* для работы с mysql меняем <strong>mariadb</strong> на <strong>mysql</strong>.</em> </p> <p style="display: none;">Сразу создаем пароль для учетной записи root:</p> <div class="console"> <p>mysqladmin -u root password</p> </div> <h3>PHP + MariaDB (MySQL)</h3> <p style="display: none;">Для возможности подключаться к базе данных скриптами PHP необходимо установить следующие модули:</p> <div class="console"> <p>dnf install php-mysqli</p> </div> <p style="display: none;">Если мы установили php5, также ставим php-mysql:</p> <div class="console"> <p>dnf install php-mysql</p> </div> <p style="display: none;">После перезагружаем php-fpm:</p> <div class="console"> <p>systemctl restart php-fpm</p> </div> <p style="display: none;">И открываем наш сайт в браузере. В phpinfo появится новая секция MySQL:</p> <p style="display: none;"> <img alt="В phpinfo появилась информация о поддержке MySQL" src="https://www.dmosk.ru/img/instruktions/centos-mega-webserver-03.jpg" style="width: 687px; height: 120px;" title="В phpinfo появилась информация о поддержке MySQL"> </p> <p style="display: none;"> <em>* нас не должно смущать, что установили мы mariadb, а заголовок mysql. Если посмотреть в таблицу, можно увидеть ячейку <strong>Client API version</strong>, в которой указано, что используется именно mariadb.</em> </p> <h2> <a id="phpmyadmin"> </a>Установка phpMyAdmin</h2> <p style="display: none;">Переходим на <a href="https://www.phpmyadmin.net/files/" target="_blank">сайт разработчика phpMyAdmin</a> и копируем ссылку на нужную нам версию, например, последнюю:</p> <p style="display: none;"> <img alt="Копируем ссылку на последнюю версию phpMyAdmin" src="https://www.dmosk.ru/img/instruktions/centos-mega-webserver-12.jpg" style="width: 449px; height: 210px;" title="Копируем ссылку на последнюю версию phpMyAdmin"> </p> <p style="display: none;">Воспользовавшись скопированной ссылкой, скачиваем архив с установочными файлами:</p> <div class="console"> <p>wget https://files.phpmyadmin.net/phpMyAdmin/5.0.2/phpMyAdmin-5.0.2-all-languages.zip</p> </div> <p style="display: none;">Распаковываем скачанный архив:</p> <div class="console"> <p>unzip phpMyAdmin-*-all-languages.zip</p> </div> <p style="display: none;">Создаем каталог для phpmyadmin:</p> <div class="console"> <p>mkdir /usr/share/phpMyAdmin</p> </div> <p style="display: none;">... и переносим в него содержимое распакованного архива:</p> <div class="console"> <p>mv phpMyAdmin-*-all-languages/* /usr/share/phpMyAdmin/</p> </div> <p style="display: none;">Задаем владельца для каталога:</p> <div class="console"> <p>chown -R apache:apache /usr/share/phpMyAdmin</p> </div> <p style="display: none;"> <em>* как правило, сервис, которых обрабатываем php-запросы работает от пользователя <strong>apache</strong>.</em> </p> <p style="display: none;">Устанавливаем модули php, необходимые для корректной работы phpMyAdmin:</p> <div class="console"> <p>dnf install php-json php-mbstring php-mysqli</p> </div> <p style="display: none;">Внесем небольшую настройку в конфигурацию phpMyAdmin.</p> <p style="display: none;">Сгенерируем случайную последовательность символов:</p> <div class="console"> <p>head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32 ; echo ''</p> </div> <p style="display: none;">Откроем на редактирование или создадим файл:</p> <div class="console"> <p>nano /usr/share/phpMyAdmin/config.inc.php</p> </div> <p style="display: none;">Внесем в него строку:</p> <div class="editor"> <p><?php<br> ...<br> $cfg['blowfish_secret'] = 'jd7n6yIcHOl55ikE7l5HAdNaWwunSHvR';<br> <br> ?></p> </div> <p style="display: none;"> <em>* где jd7n6yIcHOl55ikE7l5HAdNaWwunSHvR — последовательность, которую нам выдала команда head <strong>/dev/urandom ...</strong>; Также обратите внимание на </em> <strong><?php ?></strong> — если мы создали новый файл, необходимо указать данные теги, так как они открывают код PHP. В противном случае, настройка не применится.</p> <p style="display: none;">Теперь создадим для phpmyadmin отдельный виртуальный домен в NGINX:</p> <div class="console"> <p>nano /etc/nginx/conf.d/phpMyAdmin.conf</p> </div> <p style="display: none;">И добавим в него следующее содержимое:</p> <div class="editor"> <p>server {<br> listen 80;<br> server_name phpmyadmin.dmosk.local;<br> set $root_path /usr/share/phpMyAdmin;<br> <br> location / {<br> root $root_path;<br> index index.php;<br> }<br> <br> location ~ \.php$ {<br> fastcgi_pass unix:/run/php-fpm/www.sock;<br> fastcgi_index index.php;<br> fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;<br> include fastcgi_params;<br> fastcgi_param DOCUMENT_ROOT $root_path;<br> fastcgi_read_timeout 300;<br> }<br> }</p> </div> <p style="display: none;"> <em>* где <strong>phpmyadmin.dmosk.local</strong> — адрес для виртуального домена, именно этот адрес должен быть введен в адресную строку браузера, чтобы открылся нужный сайт. Поэтому если нет возможности зарегистрировать домен и имя узла в <a href="/terminus.php?object=dns">DNS</a>, можно воспользоваться локальным файлом hosts. <strong>/usr/share/phpMyAdmin</strong> — это каталог, в который по умолчанию устанавливается phpMyAdmin.</em> </p> <p style="display: none;">После перезапускаем NGINX:</p> <div class="console"> <p>systemctl reload nginx</p> </div> <p style="display: none;">Также нужно перезапустить php-fpm, так как в процессе установки были добавлены модули для PHP:</p> <div class="console"> <p>systemctl restart php-fpm</p> </div> <p style="display: none;">И открываем в браузере наш домен, в данном примере, <u>http://phpmyadmin.dmosk.local</u>. Откроется форма для авторизации — вводим логин root и пароль, который мы указали после установки и запуска mariadb.</p> <h2> <a id="memcached"> </a>Установка Memcached</h2> <p style="display: none;">Первым этапом мы установим и настроим сервис memcached. Вторым — модуль php-memcached.</p> <h3>Сервис memcached</h3> <p style="display: none;">Выполняем установку пакетов:</p> <div class="console"> <p>dnf install memcached libmemcached</p> </div> <p style="display: none;">Создаем или открываем на редактирование конфигурационный файл для запуска сервиса:</p> <div class="console"> <p>nano /etc/sysconfig/memcached</p> </div> <p style="display: none;">Приводим его к виду: </p> <div class="editor"> <p>PORT="11211"<br> USER="memcached"<br> MAXCONN="1024"<br> CACHESIZE="512"<br> OPTIONS="-l 127.0.0.1 -U 0"</p> </div> <p style="display: none;"> <em>* где <strong>PORT</strong> указываем на каком порту будет слушать сервис кэширования; <strong>USER</strong> — пользователь, под которым должен запускаться сервис; <strong>MAXCONN</strong> — максимальное число одновременных подключений; <strong>CACHESIZE</strong> — размер под кэш в мегабайтах; <strong>OPTIONS</strong> — параметры запуска (в данном примере наш сервис будет принимать запросы только с адреса локальной петли).</em> </p> <p style="display: none;">После разрешаем автозапуск и запускаем сервис кэширования:</p> <div class="console"> <p>systemctl enable memcached --now</p> </div> <h3>Модуль для php</h3> <p style="display: none;">Переходим на <a href="http://pecl.php.net/package/memcached" target="_blank">страницу загрузки memcached</a> сайта pecl.php.net и копируем ссылку на стабильную версию memcached:</p> <p style="display: none;"> <img alt="Копируем ссылку на исходник memcached" src="https://www.dmosk.ru/img/instruktions/centos-mega-webserver-07.jpg" style="width: 538px; height: 238px;" title="Копируем ссылку на исходник memcached"> </p> <div class="note" style="display: none;"> <p>Обратите внимание, что у каждой версии пакета есть свои требования к версии PHP. Внимательно изучаем, подойдет ли версия php-memcached для нашего сервера.</p> </div> <p style="display: none;">Скачиваем архив, ссылку на который мы скопировали:</p> <div class="console"> <p>wget http://pecl.php.net/get/memcached-3.1.5.tgz</p> </div> <p style="display: none;">Устанавливаем пакеты, необходимые для сборки php-pecl-memcached:</p> <div class="console"> <p>dnf install php-devel zlib-devel make</p> </div> <div class="console"> <p>dnf --enablerepo=PowerTools install libmemcached-devel</p> </div> <p style="display: none;">Распаковываем скачанный архив:</p> <div class="console"> <p>tar -xvzf memcached-*.tgz</p> </div> <p style="display: none;">Переходим в распакованный каталог:</p> <div class="console"> <p>cd memcached-*/</p> </div> <p style="display: none;">Запускаем компиляцию php-расширения:</p> <div class="console"> <p>phpize</p> </div> <p style="display: none;">Конфигурируем исходник:</p> <div class="console"> <p>./configure</p> </div> <p style="display: none;">Собираем расширение:</p> <div class="console"> <p>make</p> </div> <p style="display: none;">Копируем созданный модуль в каталог php-модулей:</p> <div class="console"> <p>cp modules/memcached.so /usr/lib64/php/modules/</p> </div> <p style="display: none;">Создаем конфигурационной файл для подключения расширения:</p> <div class="console"> <p>nano /etc/php.d/20-memcached.ini</p> </div> <div class="editor"> <p>extension=memcached.so</p> </div> <p style="display: none;">После установки модуля перезапускаем php-fpm:</p> <div class="console"> <p>systemctl restart php-fpm</p> </div> <p style="display: none;">Чтобы проверить, что модуль memcached работаем, открываем наш сайт в браузере — в phpinfo должна появиться новая секция:</p> <p style="display: none;"> <img alt="В phpinfo появилась информация о поддержке Memcached" src="/img/instruktions/centos-mega-webserver-13.jpg" style="width: 770px; height: 142px;" title="В phpinfo появилась информация о поддержке Memcached"> </p> <p style="display: none;">... или вводим команду:</p> <div class="console"> <p>php -m | grep memcached</p> </div> <p style="display: none;">Мы должны получить:</p> <div class="console-like" style="display: none;"> <p> <span style="color:#FF0000;">memcached</span> </p> </div> <h2> <a id="ftp"> </a>Установка и настройка FTP-сервера</h2> <p style="display: none;">В качестве FTP-сервера будем использовать ProFTPd, так как он позволяет авторизовываться под uid системных учетных записей.</p> <p style="display: none;">ProFTPd можно устанавливать командой:</p> <div class="console"> <p>dnf install proftpd</p> </div> <p style="display: none;">Загружаем скрипт ftpasswd:</p> <div class="console"> <p>wget http://www.castaglia.org/proftpd/contrib/ftpasswd -P /etc/proftpd</p> </div> <p style="display: none;">Разрешаем запуск на выполнение скрипта:</p> <div class="console"> <p>chmod +x /etc/proftpd/ftpasswd</p> </div> <p style="display: none;">Создаем виртуального пользователя:</p> <div class="console"> <p>/etc/proftpd/ftpasswd --passwd --file=/etc/proftpd/ftpd.passwd --name=ftpwww --uid=48 --gid=48 --home=/var/www --shell=/sbin/nologin</p> </div> <p style="display: none;"> <em>* где</em> </p> <ul style="display: none;"> <li> <em> <strong>/etc/proftpd/ftpd.passwd</strong> — путь до файла, в котором хранятся пользователи; </em> </li> <li> <em> <b>ftpwww </b>— имя пользователя (логин); </em> </li> <li> <em> <strong>uid</strong> и <strong>gid</strong> — идентификаторы пользователя и группы системной учетной записи (apache); </em> </li> <li> <em> <strong>/var/www</strong> — домашний каталог пользователя; </em> </li> <li> <em> <strong>/sbin/nologin</strong> — оболочка, запрещающая локальный вход пользователя в систему.</em> </li> </ul> <p style="display: none;">Изменим права для созданного файла с паролями:</p> <div class="console"> <p>chmod 440 /etc/proftpd/ftpd.passwd</p> </div> <p style="display: none;"> <em>* в противном случае, при запуске proftpd мы получим ошибку «...fatal: AuthUserFile: unable to use /etc/proftpd.d/ftpd.passwd: Operation not permitted...»</em> </p> <p style="display: none;">Открываем на редактирование конфигурационный файл proftpd:</p> <div class="console"> <p>nano /etc/proftpd.conf</p> </div> <p style="display: none;">И редактируем следующее (комментируем):</p> <div class="editor"> <p>#AuthOrder ...</p> </div> <p style="display: none;">Создадим конфигурационный файл со своими настройками:</p> <div class="console"> <p>nano /etc/proftpd/conf.d/custom.conf</p> </div> <p style="display: none;">И добавим следующее:</p> <div class="editor"> <p>UseIPv6 off<br> IdentLookups off<br> PassivePorts 60000 65535<br> <br> RequireValidShell off<br> AuthUserFile /etc/proftpd/ftpd.passwd<br> AuthPAM off<br> LoadModule mod_auth_file.c<br> AuthOrder mod_auth_file.c</p> </div> <p style="display: none;"> <em>* где <strong>60000</strong> - <strong>65535</strong> — диапазон динамических портов для пассивного режима.</em> </p> <p style="display: none;">Разрешаем автозапуск FTP-серверу и запускаем его:</p> <div class="console"> <p>systemctl enable proftpd --now</p> </div> <p style="display: none;">Пробуем подключиться к серверу, использую любые FTP-клиенты, например, FileZilla, Total Commander или тот же браузер.</p> <p style="display: none;">Это базовая и самая простая настройка ProFTPd, но если необходимо настроить TLS или хранить виртуальных пользователей в базе MySQL, читайте подробнее инструкцию по <a href="/instruktions.php?object=proftpd-centos7">настройке ProFTPd на CentOS</a>.</p> <h2> <a id="apache"> </a>Apache (httpd)</h2> <p style="display: none;">Несмотря на то, что мы установили и настроили PHP-FPM, Apache нам понадобится, как минимум, по двум причинам. Во-первых, многие сайты используют файл .htaccess, который читает Apache. Во-вторых, последний включает большое число модулей, которые может использовать портал.</p> <p style="display: none;">В некоторых случаях, можно обойтись без Apache, но в данной инструкции мы опишем процедуру его установки и настройки.</p> <p style="display: none;">И так, устанавливаем httpd:</p> <div class="console"> <p>dnf install httpd</p> </div> <p style="display: none;">Заходим в настройки:</p> <div class="console"> <p>vi /etc/httpd/conf/httpd.conf</p> </div> <p style="display: none;">И редактируем следующее:</p> <div class="editor"> <p>Listen 8080</p> </div> <p style="display: none;"> <em>* наш веб-сервер будет слушать на порту <strong>8080</strong>, так как на 80 уже работает NGINX.</em> </p> <div class="editor"> <p><IfModule dir_module><br> DirectoryIndex index.php index.html<br> </IfModule></p> </div> <p style="display: none;"> <em>* если не указан конкретный скрипт, сначала веб-сервер пытается найти и запустить <strong>index.php</strong>, затем <strong>index.html</strong> </em> </p> <p style="display: none;">Добавляем:</p> <div class="editor"> <p><Directory /var/www/*/www><br> AllowOverride All<br> Options Indexes ExecCGI FollowSymLinks<br> Require all granted<br> </Directory></p> </div> <p style="display: none;"> <em>* где <strong>Directory</strong> — разрешенные каталоги для запуска из apache; <strong>Options</strong> — разрешенные опции; <strong>Require</strong> — с каких IP-адресов можно открывать сайты, определенные в данном каталоге. Итого, мы разрешаем все каталоги в <strong>/var/www</strong>, но только если следующий каталог будет <strong>www</strong>; разрешаем опции <strong>Indexes</strong> (возвращает список файлов, если нет индексного файла, например, index.php), <strong>ExecCGI</strong> (разрешены сценарии CGI), <strong>FollowSymLinks</strong> (включены символические ссылки в этом каталоге); доступ для данных каталогов разрешен со всех адресов (<strong>all granted</strong>).</em> </p> <p style="display: none;">Проверяем синтаксис конфигурационного файла httpd:</p> <div class="console"> <p>apachectl configtest</p> </div> <p style="display: none;">И если получаем ответ:</p> <div class="console-like" style="display: none;"> <p>Syntax OK</p> </div> <p style="display: none;">... разрешаем автозапуск и запускаем службу:</p> <div class="console"> <p>systemctl enable httpd</p> </div> <div class="console"> <p>systemctl start httpd</p> </div> <p style="display: none;">Создаем php-файл со следующим содержимым:</p> <div class="console"> <p>nano /var/www/html/index.php</p> </div> <div class="editor"> <p><?php phpinfo(); ?></p> </div> <p style="display: none;">Открываем браузер и вводим в адресную строку IP-адрес нашего сервера и добавляем :8080 (<u>http://<IP-адрес нашего сервера>:8080</u>). Откроется привычная нам страница с информацией о PHP. В разделе «PHP Variables» мы должны увидеть Apache для опции $_SERVER['SERVER_SOFTWARE']:</p> <p style="display: none;"> <img alt="Страницу с phpinfo загрузил Apache" src="https://www.dmosk.ru/img/instruktions/centos-mega-webserver-10.jpg" style="width: 494px; height: 95px;" title="Страницу с phpinfo загрузил Apache"> </p> <h3>NGINX + Apache</h3> <p style="display: none;">Ранее нами была настроена связка nginx + php-fpm. Теперь проверяем совместную работу первого с apache.</p> <p style="display: none;">Открываем конфигурационный файл nginx:</p> <div class="console"> <p>nano /etc/nginx/nginx.conf</p> </div> <p style="display: none;">Находим наш настроенный location для php-fpm:</p> <div class="editor"> <p>...<br> location ~ \.php$ {<br> set $root_path /usr/share/nginx/html;<br> fastcgi_pass unix:/run/php-fpm/www.sock;<br> fastcgi_index index.php;<br> fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;<br> include fastcgi_params;<br> fastcgi_param DOCUMENT_ROOT $root_path;<br> }<br> ...</p> </div> <p style="display: none;">и меняем на:</p> <div class="editor"> <p>...<br> location ~ \.php$ {<br> proxy_pass http://127.0.0.1:8080;<br> proxy_redirect off;<br> proxy_set_header Host $host;<br> proxy_set_header X-Forwarded-Proto $scheme;<br> proxy_set_header X-Real-IP $remote_addr;<br> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br> }<br> ...</p> </div> <p style="display: none;">Проверяем, есть ли файл:</p> <div class="console"> <p>nano /etc/nginx/default.d/php.conf</p> </div> <p style="display: none;">... и если есть, комментируем его содержимое:</p> <div class="editor"> <p>#index index.php index.html index.htm;<br> #<br> #location ~ \.(php|phar)(/.*)?$ {<br> # fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;<br> #<br> # fastcgi_intercept_errors on;<br> # fastcgi_index index.php;<br> # include fastcgi_params;<br> # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;<br> # fastcgi_param PATH_INFO $fastcgi_path_info;<br> # fastcgi_pass php-fpm;<br> #}</p> </div> <p style="display: none;"> <em>* в данном примере мы отключили обработку всех php-файлов с помощью php-fpm, так как это у нас должен делать apache.</em> </p> <p style="display: none;">Проверяем и перезапускаем nginx:</p> <div class="console"> <p>nginx -t</p> </div> <div class="console"> <p>systemctl restart nginx</p> </div> <p style="display: none;">Пробуем снова открыть в браузере адрес <u>http://<IP-адрес нашего сервера</u>> (уже без 8080) — должна открыться та же страница, что при проверке Apache (с добавлением 8080):</p> <p style="display: none;"> <img alt="Страницу с phpinfo загрузил Apache" src="https://www.dmosk.ru/img/instruktions/centos-mega-webserver-10.jpg" style="width: 494px; height: 95px;" title="Страницу с phpinfo загрузил Apache"> </p> <h3>Apache Real IP</h3> <p style="display: none;">Так как все запросы на httpd приходят от NGINX, они воспринимаются как от IP-адреса 127.0.0.1. На практике, это может привести к проблемам, так как некоторым сайтам необходимы реальные адреса посетителей.</p> <p style="display: none;">Для решения проблемы будем использовать модуль mod_rpaf. Устанавливаем набор разработчика для apache:</p> <div class="console"> <p>dnf install httpd-devel gcc unzip redhat-rpm-config</p> </div> <p style="display: none;">Переходим в каталог /usr/local/src:</p> <div class="console"> <p>cd /usr/local/src</p> </div> <p style="display: none;">Скачиваем модуль:</p> <div class="console"> <p>wget https://github.com/gnif/mod_rpaf/archive/stable.zip</p> </div> <p style="display: none;">Распаковываем его:</p> <div class="console"> <p>unzip stable.zip</p> </div> <p style="display: none;">Переходим в распакованный каталог:</p> <div class="console"> <p>cd mod_rpaf-stable/</p> </div> <p style="display: none;">Собираем модуль и устанавливаем его:</p> <div class="console"> <p>make</p> </div> <div class="console"> <p>make install</p> </div> <p style="display: none;"> <em>* при возникновении ошибки <strong>./apxs.sh: line 15: -c: command not found</strong>, необходимо поставить <strong>which</strong> командой <strong>dnf install which</strong>.</em> </p> <p style="display: none;">Создаем конфигурационный файл со следующим содержимым:</p> <div class="console"> <p>nano /etc/httpd/conf.d/mod_rpaf.conf</p> </div> <div class="editor"> <p>LoadModule rpaf_module modules/mod_rpaf.so<br> RPAF_Enable On<br> RPAF_ProxyIPs 127.0.0.1<br> RPAF_SetHostName On<br> RPAF_SetHTTPS On<br> RPAF_SetPort On<br> RPAF_ForbidIfNotProxy Off</p> </div> <p style="display: none;">Перезапускаем httpd:</p> <div class="console"> <p>systemctl restart httpd</p> </div> <p style="display: none;">Для проверки открываем нашу страницу с phpinfo и находим $_SERVER['REMOTE_ADDR'] — его значение должно быть равно адресу компьютера, с которого мы открыли страницу:</p> <p style="display: none;"> <img alt="Реальный IP-адрес при обращении к Apache" src="https://www.dmosk.ru/img/instruktions/centos-mega-webserver-11.jpg" style="width: 464px; height: 111px;" title="Реальный IP-адрес при обращении к Apache"> </p> <h2> <a id="postfix"> </a>Postfix</h2> <p style="display: none;">Устанавливаем postfix командой:</p> <div class="console"> <p>dnf install postfix</p> </div> <p style="display: none;">Теперь нам необходимо сделать несколько простых настроек:</p> <div class="console"> <p>nano /etc/postfix/main.cf</p> </div> <p style="display: none;">Редактируем: </p> <div class="editor"> <p>...<br> myorigin = $mydomain<br> ...<br> inet_protocols = ipv4<br> ...</p> </div> <p style="display: none;">Добавляем:</p> <div class="editor"> <p>smtp_generic_maps = hash:/etc/postfix/generic_map</p> </div> <p style="display: none;"> <em>* <strong>myorigin</strong> — имя домена, которое будет подставляться всем отправляемым сообщениям без явного указания оного; <strong>inet_protocols</strong> — задает версию IP, с которой будет работать Postfix (если на нашем сервере используется ipv6, значение параметра стоит оставить <strong>all</strong>); <strong>smtp_generic_maps</strong> указывает на карту с общими правилами пересылки. </em> </p> <p style="display: none;">Открываем карту пересылки:</p> <div class="console"> <p>vi /etc/postfix/generic_map</p> </div> <p style="display: none;">И добавляем:</p> <div class="editor"> <p>@dmosk.local no-reply@dmosk.local</p> </div> <p style="display: none;"> <em>* данной настройкой мы будем подставлять всем отправляемым письмам без поля FROM адрес <strong>no-reply@dmosk.local</strong>.</em> </p> <p style="display: none;">Создаем карту:</p> <div class="console"> <p>postmap /etc/postfix/generic_map</p> </div> <p style="display: none;">Для применения настроек перезагружаем почтовый сервер:</p> <div class="console"> <p>systemctl restart postfix</p> </div> <h2> <a id="tuning"> </a>Тюнинг веб-сервера</h2> <h3>PHP</h3> <p style="display: none;">Открываем на редактирование следующий файл:</p> <div class="console"> <p>nano /etc/php.ini</p> </div> <p style="display: none;">И правим следующее:</p> <div class="editor"> <p>upload_max_filesize = 512M<br> ...<br> post_max_size = 512M<br> ...<br> short_open_tag = On<br> ...<br> date.timezone = "Europe/Moscow"</p> </div> <p style="display: none;">Перезапускаем php-fpm и httpd:</p> <div class="console"> <p>systemctl restart php-fpm</p> </div> <div class="console"> <p>systemctl restart httpd</p> </div> <h3>NGINX</h3> <p style="display: none;">Открываем на редактирование следующий файл:</p> <div class="console"> <p>nano /etc/nginx/nginx.conf</p> </div> <p style="display: none;">И внутри секции http добавляем:</p> <div class="editor"> <p>client_max_body_size 512M;</p> </div> <p style="display: none;">После перезапускаем nginx:</p> <div class="console"> <p>systemctl restart nginx</p> </div> <p style="display: none;">Подробнее про тюнинг NGINX в статье <a href="/instruktions.php?object=kak-optimizirovat-veb-server-nginx">Практические советы по тюнингу веб-сервера NGINX</a>.</p> <h3>Postfix</h3> <p style="display: none;">Чтобы отправляемая почта меньше попадала в СПАМ, необходимо выполнить следующие шаги:</p> <ol style="display: none;"> <li>Прописать <a href="/terminus.php?object=ptr">PTR-запись</a>.</li> <li>Создать <a href="/terminus.php?object=spf">запись SPF</a>.</li> <li> <a href="/instruktions.php?object=dkim-postfix">Настроить DKIM</a>. </li> </ol> <h2> <a id="firstsite"> </a>Создание первого сайта</h2> <p style="display: none;">Задаем переменную, значение которой будет домен сайта:</p> <div class="console"> <p>TMP_SITE=site1</p> </div> <p style="display: none;"> <em>* где <strong>site1</strong> — имя домена. Нам будет намного удобнее копировать и вставлять команды с переменной (не придется править после копипасты).</em> </p> <p style="display: none;">Создаем новый файл виртуального домена NGINX:</p> <div class="console"> <p>nano /etc/nginx/conf.d/$TMP_SITE.conf</p> </div> <p style="display: none;"> <em>* обязательно на конце должен быть <strong>.conf</strong>, так как только такие файлы веб-сервер подгружает в конфигурацию.</em> </p> <p style="display: none;">И добавляем следующее содержимое.</p> <p style="display: none;">Для HTTP:</p> <div class="editor"> <p>server {<br> listen 80;<br> server_name <strong>site1.local www.site1.local</strong>;<br> set $root_path /var/www/<strong>site1</strong>/www;<br> <br> access_log /var/www/<strong>site1</strong>/log/nginx/access_log;<br> error_log /var/www/<strong>site1</strong>/log/nginx/error_log;<br> <br> gzip on;<br> gzip_disable "msie6";<br> gzip_min_length 1000;<br> gzip_vary on;<br> gzip_proxied expired no-cache no-store private auth;<br> gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;<br> <br> root $root_path;<br> <br> location / {<br> proxy_pass http://127.0.0.1:8080/;<br> proxy_redirect off;<br> proxy_set_header Host $host;<br> proxy_set_header X-Forwarded-Proto $scheme;<br> proxy_set_header X-Real-IP $remote_addr;<br> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br> }<br> <br> location ~* ^.+\.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|ppt|tar|wav|bmp|rtf|js)$ {<br> expires modified +1w;<br> }<br> }</p> </div> <p style="display: none;"> <em>* где <strong>site1.local</strong> — домен, для которого создается виртуальный домен; <strong>/var/www/site1</strong> — каталог, в котором будет размещаться сайт.<br> ** все запросы будут переводиться на локальный сервер, порт 8080, на котором работает apache, кроме обращений к статическим файла (jpg, png, css и так далее).<br> *** обратите внимание на выделения полужирным — здесь нужно подставить свои данные.</em> </p> <p style="display: none;">Для HTTPS:</p> <div class="editor"> <p>server {<br> listen 80;<br> server_name <strong>site1.local www.site1.local</strong>;<br> return 301 https://$host$request_uri;<br> }<br> <br> server {<br> listen 443 ssl;<br> ssl on;<br> ssl_certificate /etc/nginx/ssl/cert.pem;<br> ssl_certificate_key /etc/nginx/ssl/cert.key;<br> <br> server_name <strong>site1.local www.site1.local</strong>;<br> set $root_path /var/www/<strong>site1</strong>/www;<br> <br> access_log /var/www/<strong>site1</strong>/log/nginx/access_log;<br> error_log /var/www/<strong>site1</strong>/log/nginx/error_log;<br> <br> gzip on;<br> gzip_disable "msie6";<br> gzip_min_length 1000;<br> gzip_vary on;<br> gzip_proxied expired no-cache no-store private auth;<br> gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;<br> <br> root $root_path;<br> <br> location / {<br> proxy_pass http://127.0.0.1:8080/;<br> proxy_redirect off;<br> proxy_set_header Host $host;<br> proxy_set_header X-Forwarded-Proto $scheme;<br> proxy_set_header X-Real-IP $remote_addr;<br> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br> }<br> <br> location ~* ^.+\.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|ppt|tar|wav|bmp|rtf|js)$ {<br> expires modified +1w;<br> }<br> }</p> </div> <p style="display: none;"> <em>* в первой секции server мы перенаправляем все запросы по незащищенному <strong>http</strong> на <strong>https</strong>.<br> ** <strong>ssl_certificate</strong> и <strong>ssl_certificate_key</strong> — пути к публичному и приватному ключам соответственно.<br> *** для получения бесплатного сертификата читайте статью <a href="/miniinstruktions.php?mini=get-letsencrypt">Получение бесплатного SSL сертификата Let's Encrypt</a>.</em> </p> <p style="display: none;">Теперь настроим виртуальный домен в Apache:</p> <div class="console"> <p>nano /etc/httpd/conf.d/$TMP_SITE.conf</p> </div> <div class="editor"> <p><VirtualHost *:8080><br> Define root_domain site1.local<br> Define root_path /var/www/site1<br> <br> ServerName ${root_domain}<br> ServerAlias www.${root_domain}<br> DocumentRoot ${root_path}/www<br> <br> ErrorLog ${root_path}/log/apache/error_log<br> TransferLog ${root_path}/log/apache/access_log<br> </VirtualHost></p> </div> <p style="display: none;">Создаем каталоги для сайта:</p> <div class="console"> <p>mkdir -p /var/www/$TMP_SITE/{www,tmp}</p> </div> <div class="console"> <p>mkdir -p /var/www/$TMP_SITE/log/{nginx,apache}</p> </div> <p style="display: none;">Создаем индексный файл со следующим содержимым:</p> <div class="console"> <p>vi /var/www/$TMP_SITE/www/index.php</p> </div> <div class="editor"> <p><?php echo "<h1>Hello from site1</h1>"; ?></p> </div> <p style="display: none;">Задаем права на папки:</p> <div class="console"> <p>chown -R apache:apache /var/www/$TMP_SITE</p> </div> <div class="console"> <p>chmod -R 775 /var/www/$TMP_SITE</p> </div> <p style="display: none;">Проверяем корректность настроек конфигурационных файлов:</p> <div class="console"> <p>nginx -t</p> </div> <div class="console"> <p>apachectl configtest</p> </div> <p style="display: none;">Перезапускаем веб-сервер:</p> <div class="console"> <p>systemctl reload nginx</p> </div> <div class="console"> <p>systemctl reload httpd</p> </div> <p style="display: none;">Открываем сайт в браузере.</p> <div class="note" style="display: none;"> <p>Не забываем, что обращаться к сайту нужно по его доменному имени. Например, если мы создали сайт site1.local, то нужно в браузере набрать <u>http://site1.local</u>. При этом, данное имя должно разрешаться в IP-адрес с помощью DNS или локального файла hosts.</p> </div> <p style="display: none;">При необходимости, создаем базу данных.</p> <div class="console"> <p>mysql -uroot -p</p> </div> <div class="console"> <p>> CREATE DATABASE site1 DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;</p> </div> <div class="console"> <p>> GRANT ALL PRIVILEGES ON site1.* TO dbuser@localhost IDENTIFIED BY 'password' WITH GRANT OPTION;</p> </div> <p style="display: none;"> <em>* данными sql-командами мы создаем базу данных <strong>site1</strong> и предоставляем к ней доступ для учетной записи <strong>dbuser</strong> с паролем <strong>password</strong>. При желании сделать соединение более безопасным, можно убрать </em> <strong>WITH GRANT OPTION</strong>.</p> </div>