Настраиваем веб-сервер Apache + PHP + MySQL с сертификатами Let's Encrypt

  • Автор:

Apache-LAMP-LetsEncrypt-000.png

Веб-сервер Apache до сих пор остается достаточно популярным и де-факто является стандартом веб-сервера для платформы Linux, так или иначе большинство современных веб-приложений продолжают разрабатываться таким образом, чтобы работать на Apache из коробки, кроме того, сам веб-сервер имеет достаточно низкий порог входа и легко осваивается. В данной статье мы рассмотрим, как настроить полноценный веб-сервер на базе Apache с поддержкой PHP и MySQL (стек LAMP) c обязательным шифрованием на базе сертификатов Let's Encrypt.

Онлайн-курс по устройству компьютерных сетей
На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

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

А способность использовать для настройки файлы .htaccess позволяет обеспечить устойчивость сервера от некорректных настроек со стороны пользователя. В случае ошибки перестанет работать только один сайт или его часть, сам веб-сервер останется работоспособен. Это также позволяет удобно привлекать третьих лиц для работы с сайтом, не давая им доступа к основной конфигурации веб-сервера.

Работа Apache c PHP происходит как еще с одним модулем в едином адресном пространстве, это не требует дополнительной настройки и обеспечивает высокую производительность. Поэтому, вопреки распространенному мнению, производительность PHP в связке с Apache является наиболее высокой.

В целом можно сказать, что Apachе является крепким универсалом, да, он не самый быстрый, не самый экономичный, не самый самый. Но если вам нужен простой и универсальный веб-сервер - это про него.

В данной статье мы будем рассматривать установку стека LAMP в среде последних версий Debian и Ubuntu, они имеют небольшие различия по версиям используемого ПО, но при этом содержат актуальные версии, что позволит развернуть веб-сервер штатными средствами без подключения дополнительных репозиториев. Набор используемого ПО таков:

  • Debian 12: Apache 2.4.57, PHP 8.2, MariaDB 10.11 LTS
  • Ubuntu 22.04 LTS: Apache 2.4.52, PHP 8.1, MySQL 8.0 LTS

Все команды, если не указано иного, следует выполнять с правами суперпользователя root или через sudo.

В качестве примера имени сайта мы будем использовать:

  • site.example
  • www.site.example

Их следует заменить на реальное доменное имя, которое вы будете использовать.

Установка Apache 2.4 и получение сертификатов Let's Encrypt

Для установки веб-сервера Apache следует воспользоваться одной простой командой:

apt install apache2

Теперь если набрать в адресной строке браузера адрес веб-сервера, то вы увидите стандартную страницу-заглушку, это обозначает, что веб-сервер установлен и работает.

Apache-LAMP-LetsEncrypt-001.pngСтандартная система расположения конфигурационных файлов в Debian или Ubuntu подразумевает, что конфигурационные файлы хранятся в директориях available с расширением conf, а для подключения их к текущей конфигурации веб-сервера для них создаются символические ссылки в директории enable, это делается автоматически, при помощи утилит Apache, но также допускается создавать такие ссылки вручную.

Создадим конфигурационный файл для нашего сайта и сразу откроем его на редактирование (если вы предпочитаете редактору nano редактор MC, то укажите в команде вместо nano mcedit):

nano /etc/apache2/sites-available/site.example.conf

И внесем в него следующие строки:

<VirtualHost *:80>
ServerName site.example
ServerAdmin webmaster@site.example
ServerAlias www.site.example
</VirtualHost>

Для нашей основной цели - получения сертификатов Let's Encrypt этого более чем достаточно.

Подключим сайт:

a2ensite site.example

Проверим конфигурацию и перезапустим веб-сервер:

apachectl -t
systemctl reload apache2

Для получения сертификатов нам понадобится специальная утилита Certbot, ее актуальные версии распространяются только через Snap и если у вас была установлена версия из репозитория, то ее следует удалить и заодно подчистить ненужные более зависимости:

apt remove certbot
apt autoremove

Затем установим поддержку Snap (в Ubuntu поддержка Snap установлена по умолчанию):

apt install snapd

После чего установим snap-версию Certbot:

snap install --classic certbot

И сделаем символическую ссылку на бинарный файл утилиты:

ln -s /snap/bin/certbot /usr/bin/certbot

Теперь можно приступить к получению сертификатов, мы будем использовать для этого специальный плагин для веб-сервера Apache, но не будем разрешать ему вносить изменения в конфигурационные файлы, ограничив режимом только получения сертификатов:

certbot certonly --apache

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

Apache-LAMP-LetsEncrypt-002.pngЕсли все прошло нормально и сертификаты получены, то перейдем к дальнейшей настройке веб-сервера для работы с шифрованием, прежде всего добавим файл конфигурации с общими для всего сервера настройками, которые будут применяться к любому HTTPS сайту:

nano /etc/apache2/conf-available/tls.conf

И внесем в него следующие строки:

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off
SSLSessionTickets off

SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"

Настройка TLS-защиты задача не простая, поэтому мы советуем использовать для получения адекватных настроек moz://a SSL Configuration Generator, также рекомендуем время от времени проверять сайт на наличие обновленных настроек.

Коротко пройдемся по указанным выше строкам. Первая отключает устаревшие протоколы шифрования, оставляя только TLS v1.2 и TLS v1.3, вторая определяет набор используемых шифров, шифры перечислены в порядке их предпочтения и клиент согласовывает с сервером самый стойкий из поддерживаемых шифров.

Опция SSLHonorCipherOrder off определяет, что приоритет в выборе шифра отдается клиенту, т.е. именно клиент выбирает из предложенных шифров тот, с которым он будет работать. Опция SSLSessionTickets off отключает сессионные билеты SSL, что нужно для работы совершенной прямой секретности.

Нижний блок включает OCSP Stapling, который ускоряет проверку браузером сертификата сайта и благоприятно сказывается на скорости работы сайта.

Сохраним данную конфигурацию и подключим ее:

a2enconf tls

Теперь вернемся к конфигурации сайта и продолжим ее настройку. Прежде всего настроим редиректы. Нам нужно направить весь незащищенный трафик HTTP на HTTPS-версию сайта, а также все запросы с www, на версию без www.

Сразу коснемся вопроса, а почему не продолжить использовать опцию ServerAlias, как мы это сделали выше, при получении сертификата? Да, можно, но в этом случае у нас будет как-бы два сайта, один с www, второй без, что негативно сказывается на его ранжировании поисковыми системами. Поэтому лучше иметь одну версию сайта, в нашем случае без www и перенаправлять на нее все запросы с www.

Ну и второй по популярности вопрос, а зачем вообще нужен www? По большому счету не нужен, это пережиток старины, но многие пользователи все еще могут набрать адрес сайта вместе с www, чтобы не терять таких пользователей мы будем обслуживать и этот поддомен.

Первую секцию в конфигурационном файле приводим к виду:

<VirtualHost *:80>
ServerName site.example
ServerAdmin webmaster@site.example

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>

Она будет перенаправлять все запросы с HTTP на HTTPS версию сайта.

Ниже добавим вторую секцию:

<VirtualHost *:80>
ServerName www.site.example
ServerAdmin webmaster@site.example

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [L,R=301]
</VirtualHost>

Которая будет переадресовывать запросы с www на защищенную версию сайта без www, а за ней еще один блок, только уже для перенаправления www защищенной версии сайта на версию без www.

<VirtualHost *:443>
ServerName www.site.example
ServerAdmin webmaster@site.example

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [L,R=301]
</VirtualHost>

После чего добавим основную секцию, которая будет отвечать за работу нашего сайта:

<VirtualHost *:443>
ServerName site.example
ServerAdmin webmaster@site.example

SSLEngine on

SSLCertificateFile /etc/letsencrypt/live/site.example/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/site.example/privkey.pem

Protocols h2 http/1.1
Header always set Strict-Transport-Security "max-age=63072000"

DocumentRoot /var/www/site.example

CustomLog ${APACHE_LOG_DIR}/site.example.access.log combined
ErrorLog ${APACHE_LOG_DIR}/site.example.error.log

<Directory /var/www/site.example>
AllowOverride All
</Directory>
</VirtualHost>

Опция SSLEngine on включает поддержку шифрования, ниже идут пути к сертификатам, обратите внимание, что Let's Encrypt хранит их в /etc/letsencrypt/live в директориях с именем домена, если сертификат выпущен на несколько доменов, то используется указанное первым имя. Затем в опции Protocols перечисляются поддерживаемые протоколы в порядке убывания приоритета, в нашем случае приоритетным является HTTP 2.

Заголовок Strict-Transport-Security препятствует атакам на понижение безопасности, если браузер успешно соединился с таким сайтом через HTTPS, то он в течении времени указанного в заголовке (1 год) не будет даже пытаться установить незащищенное соединение, даже если HTTP-версия сайта доступна. Рекомендуется закомментировать данную опцию на время настройки и отладки сайта.

DocumentRoot определяет корневую директорию сайта.

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

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

Сохраняем файл конфигурации, затем подключим нужные модули:

a2enmod headers rewrite ssl

Затем создадим директорию сайта

mkdir /var/www/site.example

В ней создадим индексный файл и откроем его на редактирование:

nano /var/www/site.example

И внесем в него следующий текст:

<body><h1>OK!</h1></body>

Сделаем владельцем файлов и директории веб-сервер:

chown -R www-data:www-data /var/www/site.example

Теперь проверим конфигурацию на ошибки и перезапустим веб-сервер:

apachectl -t
systemctl reload apache2

Если все сделано правильно, то теперь, при обращении к сайту вы сразу попадете на его защищенную версию с действительным сертификатом Let's Encrypt.

Apache-LAMP-LetsEncrypt-003.pngКак можно увидеть, для подключения применяется самый современный протокол TLS 1.3, шифр AES_128_GCM и совершенная прямая секретность на эллиптической кривой X25519.

Настройка сайта по умолчанию для блокирования несуществующих доменов

Использование TLS-шифрования имеет одну особенность: если мы обратимся к веб-серверу по IP-адресу или по доменному имени, которое указывает на веб-сервер, но не обслуживается им (или не имеет HTTPS-версии), то будет показан сайт, сертификат которого указан первым в конфигурации веб-сервера.

Такое поведение может быть нежелательным, так как позволяет раскрыть обслуживаемый сайт просто обратившись по имени или ввести пользователя в заблуждение. Поэтому настроим сайт по умолчанию, который будет блокировать все запросы к несуществующим доменам как в HTTP, так и в HTTPS версиях.

Для HTTPS нам понадобится сертификат, можно использовать любой существующий, но это позволит раскрыть реальный обслуживаемый сайт, поэтому выпустим для этих целей самоподписанный сроком на 10 лет:

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/apache2/apache.key -out /etc/apache2/apache.crt

Затем заменим содержимое файла /etc/apache2/sites-available/000-default.conf следующим содержимым:

<VirtualHost *:80>
ServerName _default_
RewriteEngine On
RewriteRule ^ - [F]
</VirtualHost>

<VirtualHost *:443>
ServerName _default_
SSLEngine on
SSLCertificateFile /etc/apache2/apache.crt
SSLCertificateKeyFile /etc/apache2/apache.key
RewriteEngine On
RewriteRule ^ - [F]
</VirtualHost>

Опция ServerName _default_ используется для перехвата любого запроса, который не обслуживается ни одним существующим виртуальным хостом, а RewriteRule ^ - [F] возвращает код состояния HTTP 403 (Forbidden).

Снова проверяем конфигурацию и перезапускаем службу веб-сервера:

apachectl -t
systemctl reload apache2

Если попробовать теперь обратиться к серверу по IP-адресу, то увидим:

Apache-LAMP-LetsEncrypt-004.png

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

Установка и настройка PHP

Для работы с динамическим содержимым нам потребуется поддержка PHP, скриптового языка, на котором написано большинство современных систем управления контентом (CMS), также называемых движками сайтов. Apache использует PHP в режиме модуля веб-сервера и никаких особых настроек нам не потребуется, достаточно просто установить PHP командой:

 apt install php

Но не будем спешить и сразу изменим некоторые настройки, откроем /etc/php/x.x/apache2/php.ini, где x.x текущая установленная версия PHP, в Debian 12 это 8.2, в Ubuntu 22.04 - 8.1, и приведем к следующему виду следующие опции:

post_max_size = 32M
upload_max_filesize = 30M

Первая из них определяет максимальный размер передаваемого на сервер пакета данных, а вторая - максимальный размер загружаемого файла.

После чего перезапустим веб-сервер:

systemctl reload apache2

Для проверки создадим в корневой директории веб-сервера файл:

nano /var/www/site.examlpe/info.php

И внесем в него следующий текст:

<?php
phpinfo();
?>

Если теперь в адресной строке браузера набрать site.example/info.php то увидим стандартную страницу с информацией о PHP, его настройках и установленных модулях.

Apache-LAMP-LetsEncrypt-005.pngДля расширения возможностей PHP используются модули, скажем, для работы с графикой может потребоваться модуль GD или ImageMagick, для модулей используют следующий шаблон имен пакетов: php-<имя модуля>, например:

apt install php-gd php-imagick

Необходимые модули и их имена вы можете узнать из документации к используемому веб-приложению.

Установка MySQL / MariaDB

Сервер баз данных третий неотъемлемый компонент классического веб-сервера и один из первых по важности, так как именно в базе данных хранится основная пользовательская информация сайта. В современных версиях Debian и Ubuntu используются разные варианты СУБД: MariaDB и MySQL, которые являются совместимыми и принципиально разницы какую из них использовать нет, тем более что в репозиториях содержатся последние LTS-версии обоих СУБД. Поэтому будем устанавливать версии из репозитория, что упростит дальнейшую поддержку и обслуживание сервера.

Для Debian это будет команда:

apt install mariadb-server

А для Ubuntu:

apt install mysql-server

В дальнейшем в обоих системах для управления можно использовать один и тот же набор команд:

systemctl start | stop | restart | status mysql

Вне зависимости от того, какую именно версию СУБД вы используете.

Apache-LAMP-LetsEncrypt-006.png

После установки сервера баз данных следует выполнить скрипт, который выполнит рекомендуемые настройки безопасности установленного экземпляра сервера:

mysql_secure_installation

В нем положительно отвечаем на все вопросы, кроме смены пароля суперпользователя СУБД root, в текущем режиме установки учетная запись root не имеет пароля и поддерживает вход исключительно через UNIX-сокет, поэтому не следует ее включать.

Затем установим модуль PHP для работы с MySQL / MariaDB:

apt install php-mysql

Теперь выполним некоторые настройки самого сервера СУБД, сначала поднимем собственные права до суперпользователя, в Debian выполните команду:

su -

В Ubuntu:

sudo -s

После чего перейдем в командную строку MySQL в режиме суперпользователя:

mysql -u root

В первую очередь создадим пользователей СУБД и разрешим им вход по паролю:

CREATE USER 'andrey'@'localhost' IDENTIFIED BY 'Pa$$word_1';

После чего отберем у него права на чужие базы:

GRANT USAGE  ON *.* TO 'andrey'@'localhost';

А затем выдадим полные права на все базы с шаблоном имени andrey_<имя базы>, что позволит автоматически устанавливать права просто создав базу с нужным именем.

GRANT ALL PRIVILEGES ON `andrey\_%`.* TO 'andrey'@'localhost';

Обратите внимание, что шаблон оборачивается символами грависа (`), который находится на клавише с русской буквой Ё.

Перезагрузим привилегии:

FLUSH PRIVILEGES;

И выйдем из консоли MySQL:

QUIT;

На этом настройка сервера СУБД закончена.

Установка phpMyAdmin

phpMyAdmin - удобное веб-приложение для управления СУБД MySQL / MariaDB и, по сути, стандарт де-факто среди таких приложений, его использование для повседневной работы с СУБД повышает общее удобство, по сравнению с консолью и поэтому мы не видим причин отказывать от его использования.

Для его установки используйте команду:

apt install phpmyadmin

Приложение начинает работать сразу после установки и для его использования достаточно набрать в адресной строке браузера site.example/phpmyadmin:

Apache-LAMP-LetsEncrypt-007.png

Однако держать приложение в открытом доступе явно не стоит, так как phpMyAdmin представляет также лакомую цель для злоумышленников, поэтому закроем к нему доступ дополнительной парольной защитой. Прежде всего создадим пользователя и зададим ему пароль, если вы делаете это первый раз, то используйте в команде ключ -c, который создаст файл паролей или перезапишет существующий:

htpasswd -c /etc/apache2/passwd ivanov

Для следующего пользователя следует использовать просто:

htpasswd /etc/apache2/passwd petrov

Теперь откроем конфигурационный файл phpMyAdmin для Apache /etc/apache2/conf-available/phpmyadmin.conf и в секцию <Directory /usr/share/phpmyadmin> добавим следующий блок:

AuthType Basic
AuthName "Restricted Access"
AuthUserFile /etc/apache2/passwd
Require valid-user

Который разрешает доступ к указанной директории любому пользователю, прошедшему проверку. Если нужно ограничить доступ конкретным пользователям, то измените последнюю строку на:

Require user ivanov

Если пользователей несколько, то указываем их через пробел.

Отдельного упоминания следует использование Basic-аутентификации, ее особенностью является передача учетных данных в открытом виде, но в данном случае это не имеет значения, так как Apache у нас настроен исключительно на работу по HTTPS, где все передаваемые между клиентом и сервером данные защищены надежным шифрованием.

На этом настройка веб-сервера на базе Apache + PHP + MySQL с сертификатами Let's Encrypt закончена.

Онлайн-курс по устройству компьютерных сетей
На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Помогла статья? Поддержи автора и новые статьи будут выходить чаще:

Поддержи проект!

Или подпишись на наш Телеграм-канал: Подпишись на наш Telegram-канал



Loading Comments