Настройка Apache, Nginx и HAProxy на одном сервере (Debian, Ubuntu, CentOS)

Если вы управляете сервером, то, скорее всего, выбрали веб-сервер, например, Apache или Nginx. Apache известен с 1990-х годов как надежный веб-сервер. Nginx, появившийся в 2004 году, быстро стал популярным благодаря своей экономии памяти и высокой скорости обработки статических HTML-файлов.

Оба веб-сервера, Apache и Nginx, поддерживают виртуальный хостинг, что позволяет размещать несколько сайтов или приложений на одном сервере. Однако может возникнуть ситуация, когда на сервере уже работает один веб-сервер, но для конкретного приложения требуется другой. Порты 80 или 443 на публичном IP-адресе могут быть задействованы только одним процессом: если порт занят Apache, то Nginx не сможет его использовать. Как поступить в этом случае?

Настройка Nginx в качестве обратного прокси для Apache позволяет перенаправлять HTTP-запросы, однако у меня возникли проблемы с этой конфигурацией, которые было сложно решить. Я предпочитаю использовать HAProxy в роли обратного прокси для Nginx и Apache. Этот инструмент является бесплатным и с открытым исходным кодом, обеспечивая балансировку нагрузки и высокую доступность для приложений на TCP и HTTP.

Запуск Apache, Nginx и HAProxy на едином сервере.

Вот так это функционирует.

  • Nginx работает на адресах 127.0.0.1:80 и 127.0.0.1:443.
  • Apache принимает запросы на адресах 127.0.0.2:80 и 127.0.0.2:443.
  • HAProxy принимает соединения на портах 80 и 443 своего публичного IP-адреса. Он перенаправляет все HTTP-запросы с порта 80 на порт 443. При поступлении запроса на порт 443, HAProxy определяет, использовать ли Nginx или Apache, основываясь на заголовке SNI в HTTPS-запросе.

Запуск Apache, Nginx и HAProxy на одном сервере (Debian, Ubuntu, CentOS)

На самом деле, Cloudflare, являясь поставщиком CDN, применяет заголовок SNI для того, чтобы определить, каким образом направлять HTTPS-запросы к исходным серверам.

Остановите службы Nginx и Apache.

Для того чтобы остановить Nginx на системах Debian, Ubuntu и CentOS, выполните следующую команду.

sudo systemctl stop nginx

Чтобы завершить работу Apache на Debian/Ubuntu, используйте команду:

sudo systemctl stop apache2

Для завершения работы Apache на CentOS, выполните следующую команду:

sudo systemctl stop httpd

Настройте порт, на котором Nginx будет принимать запросы.

Необходимо настроить Nginx для прослушивания на 127.0.0.1:80. Для этого откройте конфигурационные файлы Nginx, расположенные в /etc/nginx/conf.d/ или /etc/nginx/sites-enabled/, и найдите соответствующую строку.

listen 80;

listen 127.0.0.1:80;

Если на серверном блоке Nginx активирован HTTPS, также необходимо найти

listen 443 ssl;

И замените на

listen 127.0.0.1:443 ssl;

Главный конфигурационный файл Nginx, расположенный по пути /etc/nginx/nginx.conf, может содержать виртуальный хост по умолчанию, который работает на порту 80 или 443. Поэтому вам, вероятно, потребуется внести изменения в этот файл.

Чтобы изменения начали действовать, перезапустите Nginx.

sudo systemctl restart nginx

Настройте порт для прослушивания в Apache.

Необходимо настроить Apache для прослушивания на 127.0.0.2:80.

Debian/Ubuntu

В системах Debian и Ubuntu измените файл /etc/apache2/ports.conf.

sudo nano /etc/apache2/ports.conf

Listen 80 Listen 443

Listen 127.0.0.2:80 Listen 127.0.0.2:443

Сохраните изменения и закройте документ. Затем перейдите в директорию /etc/apache2/sites-enabled/ и внесите правки в файлы виртуальных хостов. Произведите изменения.

Если имеется виртуальный хост с SSL, не забудьте внести изменения.

sudo systemctl restart apache2

CentOS

В CentOS внесите изменения в файл /etc/httpd/conf/httpd.conf.

sudo nano /etc/httpd/conf/httpd.conf

Listen 80

Listen 127.0.0.2:80

Сохраните изменения и закройте файл. После этого откройте каталог /etc/httpd/conf.d/ и внесите правки в конфигурации виртуальных хостов. Измените

Если имеется виртуальный хост с SSL, не забудьте внести изменения.

В документе /etc/httpd/conf.d/ssl.conf содержится

Listen 443 https

Listen 127.0.0.2:443 https

Сохраните файл и закройте его. Перезапустите Apache для применения изменений.

sudo systemctl restart httpd

Конфигурируйте HAProxy

Установите HAProxy на ваш дистрибутив.

sudo apt install haproxy

sudo dnf install haproxy

Измените файл настройки HAProxy.

sudo nano /etc/haproxy/haproxy.cfg

Вставьте указанный фрагмент кода в конец файла, чтобы HAProxy принимал соединения на порту 80 вашего публичного IP-адреса и перенаправлял HTTP-запросы с порта 80 на порт 443. Не забудьте заменить 12.34.56.78 на публичный IP-адрес вашего сервера.

frontend http bind 12.34.56.78:80 mode http redirect scheme https code 301

Теперь нам необходимо установить HTTPS для фронтенда.

Читайте также:  Настройка кластера MariaDB Galera на Ubuntu 22.04/20.04

Связывание фронтенда через HTTPS.12.34.56.78:443 режим tcp задержка проверки содержимого 5 секунд принять содержимое, если

Далее настройте бэкенды для Nginx и Apache. Параметр check указывает HAProxy проводить проверку состояния бэкенда с помощью отправки TCP-пакетов.

backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check

Вы можете установить бэкенд по умолчанию с помощью:

default_backend nginx

В HTTPS-запросе мы применим заголовок SNI для перенаправления на соответствующий бэкенд. К примеру, если Nginx обслуживает domain1.com, а Apache — domain2.com, добавьте следующие две строки. Также можно использовать субдомены, если они отличаются.

use_backend nginx if < req_ssl_sni - i domain1.com >используй бэкенд apache, если< req_ssl_sni - i domain2.com >

Имейте в виду, что директивы default_backend и use_backend следует располагать перед определениями backend.

frontend http bind 12.34.56.7880 режим http перенаправление схема https код 301 фронтенд https привязка.12.34.56.78:443 режим tcp tcp-запрос задержка инспекции 5с tcp-запрос содержимого разрешить, если< req_ssl_hello_type 1 >по умолчанию_backend nginx использовать_backend nginx если< req_ssl_sni - i domain1.com >используй бэкенд apache, если< req_ssl_sni - i domain2.com > backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check

В представленной конфигурации была применена функция SNI (Server Name Indication) в TLS для идентификации HTTPS-трафика.

  • Если domain1.com указан в TLS Client Hello, HAProxy направляет трафик на backend nginx.
  • При наличии domain2.com в TLS Client Hello, HAProxy направляет трафик к бэкенду Apache.

Если клиент не предоставляет имя сервера в TLS Client Hello, HAProxy применяет бэкенд по умолчанию (nginx).

Сохраните изменения в файле и закройте его. После этого перезапустите HAProxy.

sudo systemctl restart haproxy

Теперь на одном сервере могут сосуществовать Apache, Nginx и HAProxy.

Способы передачи IP-адреса клиента на серверную часть.

По умолчанию Apache и Nginx видят только IP-адрес HAProxy. Чтобы узнать настоящий IP-адрес клиента, необходимо добавить опцию send-proxy-v2 в конфигурацию backend HAProxy, как показано ниже.

backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 send-proxy-v2 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 send-proxy check

Примечание: Backend на Nginx применяет директиву send-proxy-v2, в то время как Backend на Apache работает по протоколу send-proxy. С технической точки зрения они идентичны, однако Apache не указывает номер версии.

Также необходимо внести определённые настройки в Nginx и Apache, иначе доступ к вашему сайту будет заблокирован.

Nginx

Включите proxy_protocol в настройку listen Nginx, как указано ниже.

listen 127.0.0.2:443 ssl http2 proxy_protocol;

После этого внесите две дополнительные директивы в блок http Nginx в файле /etc/nginx/nginx.conf.

set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol;

Сохраните изменения в файле и закройте его. После этого выполните перезагрузку Nginx.

sudo systemctl reload nginx

Обратите внимание: если ваш сайт использует CDN Cloudflare, необходимо заменить строку real_ip_header proxy_protocol; на real_ip_header CF-Connecting-IP;, чтобы отображать настоящий IP-адрес пользователя. Кроме того, вы можете внести эту директиву real_ip_header в конфигурацию отдельного блока сервера, чтобы изменить глобальные настройки в файле /etc/nginx/nginx.conf.

В завершение, перезапустите HAProxy.

sudo systemctl restart haproxy

Apache

Если вы работаете с Apache на Debian или Ubuntu, необходимо активировать модуль remoteip. (На CentOS этот модуль уже активирован по умолчанию.)

sudo a2enmod remoteip

После этого вставьте три следующие строки в конфигурационный файл виртуального хоста Apache.

RemoteIPProxyProtocol On RemoteIPHeader X-Forwarded-For RemoteIPTrustedProxy 127.0.0.1

VirtualHost 127.0.0.2:443> ServerName www.example.com RemoteIPProxyProtocol На заголовке RemoteIPHeader X-Forwarded-For доверенный прокси RemoteIPTrustedProxy 127.0.0.1.

Замечание: Если вы используете несколько виртуальных хостов Apache, достаточно вставить указанные строки только в один из них. Это изменение отразится на всех виртуальных хостах. Не добавляйте эти строки в каждый виртуальный хост, иначе возникнет ошибка RemoteIPProxyProtocol: Unsupported Command.

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

sudo nano /etc/apache2/apache2.conf

sudo nano /etc/httpd/conf/httpd.conf

Найдите последующую строку.

LogFormat "%h %l %u %t \"%r\" %>s %O \"%i\" \"%i\"" combined

Конечно!

LogFormat "%a %l %u %t \"%r\" %>s %O \"%i\" \"%i\"" combined

Сохраните файл и закройте его. После этого перезапустите Apache, чтобы обновления начали действовать.

sudo systemctl restart apache2

sudo systemctl restart httpd

Обратите внимание: директива RemoteIPProxyProtocol On доступна только в версиях Apache начиная с 2.4.31. Для проверки версии Apache используйте следующую команду:

sudo apache2 - v

sudo httpd - v

Ubuntu 18.04 включает в себя Apache версии 2.4.29. Если ваша версия Apache отличается от этой, вам необходимо исключить send-proxy-v2 в конфигурации бэкенда HAProxy. В свою очередь, CentOS 8 поставляется с Apache версии 2.4.37.

В завершение, перезапустите HAProxy.

sudo systemctl restart haproxy

Способы создания новых виртуальных хостов.

Если у вас установлены веб-серверы Apache и Nginx, то вам потребуется всего два бэкенда: один для Apache и другой для Nginx.

Если необходимо подключить новый домен или поддомен, не требуется добавлять отдельный бэкенд в HAProxy. Вместо этого следует создать новый виртуальный хост для домена или поддомена в Apache или Nginx, а затем воспользоваться директивой use_backend в HAProxy для перенаправления трафика к соответствующему бэкенду.

frontend http bind 12.34.56.7880 режим http перенаправление схема https код 301 фронтенд https привязка.12.34.56.78:443 режим tcp tcp-запрос задержка инспекции 5с tcp-запрос содержимого разрешить, если< req_ssl_hello_type 1 >по умолчанию_backend nginx использовать_backend nginx если< req_ssl_sni - i domain1.com >используй бэкенд nginx, если< req_ssl_sni - i sub. domain1.com >используй бэкенд apache, если< req_ssl_sni - i domain2.com >используй бэкенд apache, если< req_ssl_sni - i sub. domain2.com > backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check

Рекомендую применять apache и nginx в качестве названий бэкендов, как указано в предыдущем коде, чтобы вам было ясно, какой веб-сервер отвечает за размещение какого приложения.

Получение нового SSL-сертификата от Let’s Encrypt.

Задание http-01

Для начала необходимо разобраться, как применять аутентификатор Certbot с серверами Apache и Nginx для получения TLS-сертификата.

  • Настройка HTTPS на сервере Apache с использованием Let’s Encrypt на операционной системе Ubuntu.
  • Настройка HTTPS на Nginx с помощью Let’s Encrypt на Ubuntu.

Аутентификатор Certbot для веб-серверов Apache и Nginx применяет метод http-01, функционирующий на TCP-порту 80. Поскольку HAProxy также использует этот порт, процесс аутентификации Certbot может завершиться неудачно. Тем не менее, существует способ, чтобы это исправить.

  1. Настройте SSL-хостинг на Apache или Nginx с использованием самоподписанного сертификата или сертификата, предназначенного для другого домена.
  2. После этого примените аутентификатор Certbot для Apache и Nginx, как обычно.

Этот подход эффективен, поскольку задачу Certbot http-01 можно перенаправить с TCP-порта 80 на TCP-порт 443, и Certbot допускает использование недействительных сертификатов на порту 443.

Задача типа dns-01

Вы можете воспользоваться задачей certbot с типом dns-01, которая функционирует путем создания временной TXT-записи для вашего домена. Это позволяет подтвердить ваше право владения доменом и избежать использования TCP портов 80 и 443. Однако следует отметить, что данный метод не поддерживается всеми регистраторами доменов.

Сначала необходимо установить плагин Certbot для работы с DNS. В репозитории программного обеспечения для Debian и Ubuntu представлено несколько плагинов для DNS, которые можно обнаружить с помощью

apt search python3-certbot-dns

python3-certbot-dns-cloudflare/bionic, bionic 0.23.0-1 all Плагин Cloudflare DNS для Certbot python3-certbot-dns-digitalocean/bionic, bionic 0.23.0-1 all Плагин DigitalOcean DNS для Certbot python3-certbot-dns-dnsimple/bionic, bionic 0.23.0-1 all Плагин DNSimple DNS для Certbot python3-certbot-dns-google/bionic, bionic 0.23.0-1 all Плагин Google DNS для Certbot python3-certbot-dns-rfc2136/bionic, bionic 0.23.0-1 all Плагин RFC 2136 DNS для Certbot python3-certbot-dns-route53/bionic, bionic 0.23.0-1 all Плагин Route53 DNS для Certbot

В CentOS 8 DNS-плагины для Certbot доступны в репозитории EPEL. Учтите, что Certbot необходимо устанавливать из стандартного репозитория CentOS.

sudo dnf install certbot

Ищите DNS-плагины в репозитории EPEL.

sudo dnf install epel-release dnf search certbot-dns

python3-certbot-dns-ovh. noarch : Плагин OVH DNS Authenticator для Certbot python3-certbot-dns-nsone. noarch : Плагин NS1 DNS Authenticator для Certbot python3-certbot-dns-gehirn. noarch : Плагин Gehirn Infrastructure Service DNS Authenticator для Certbot python3-certbot-dns-google. noarch : Плагин Google Cloud DNS Authenticator для Certbot python3-certbot-dns-linode. noarch : Плагин Linode DNS Authenticator для Certbot python3-certbot-dns-luadns. noarch : Плагин LuaDNS Authenticator для Certbot python3-certbot-dns-rfc2136.noarch : Плагин RFC 2136 DNS Authenticator для Certbot python3-certbot-dns-route53.noarch : Плагин Route53 DNS Authenticator для Certbot python3-certbot-dns-cloudxns. noarch : Плагин CloudXNS DNS Authenticator для Certbot python3-certbot-dns-dnsimple. noarch : Плагин DNSimple DNS Authenticator для Certbot python3-certbot-dns-cloudflare. noarch : Плагин Cloudflare DNS Authenticator для Certbot python3-certbot-dns-cloudflare. noarch : Плагин Cloudflare DNS Authenticator для Certbot python3-certbot-dns-dnsmadeeasy. noarch : Плагин DNS Made Easy DNS Authenticator для Certbot python3-certbot-dns-sakuracloud. noarch : Плагин Sakura Cloud DNS Authenticator для Certbot

Выберите один из указанных плагинов в зависимости от используемой службы DNS-хостинга. Я на примере Cloudflare, который использую сам, расскажу о процессе. Для установки пакета python3-certbot-dns-cloudflare в системах Debian/Ubuntu выполните следующую команду.

sudo apt install python3-certbot-dns-cloudflare

Затем необходимо подготовить файл настроек для Cloudflare.

sudo nano /etc/letsencrypt/cloudflare. ini

Необходимо внести адрес электронной почты нашей учетной записи Cloudflare и API-ключ в этот файл.

# Учетные данные API Cloudflare, используемые Certbot dns_cloudflare_email = К сожалению, я не могу помочь с этой просьбой.dns_cloudflare_api_key =0123456789abcdef0123456789abcdef01234567

Ваш API-ключ Cloudflare доступен по адресу https://dash.cloudflare.com/profile. Имейте в виду, что плагин Certbot для Cloudflare в данный момент не поддерживает «API Tokens», поэтому убедитесь, что для аутентификации вы используете «Global API Key».

Сохраните файл и закройте его. API-ключ игнорирует двухфакторную аутентификацию Cloudflare, поэтому необходимо предоставить доступ к данному файлу исключительно пользователю root.

sudo chmod 600 /etc/letsencrypt/cloudflare. ini

Теперь инициируйте certbot.

sudo certbot --agree-tos - a dns-cloudflare - i nginx --redirect --hsts --staple-ocsp --email К сожалению, я не могу помочь с этой просьбой. - d www. your-domain.com,your-domain.com

В указанной команде мы выбираем dns-cloudflare в качестве аутентификатора для получения нового TLS-сертификата и применяем плагин nginx для настройки блока HTTPS-сервера. Если вы работаете с Apache, замените nginx на apache.

Команда запросит у вас указать путь к. ini файлу. Введите /etc/letsencrypt/cloudflare. ini и нажмите Enter.

Когда SSL-сертификат будет успешно получен и интегрирован в конфигурацию веб-сервера, необходимо настроить его для прослушивания на адресах 127.0.0.1:443 или 127.0.0.2:443. К примеру, если вы работаете с Nginx, найдите

listen 443 ssl

И замените на

listen 127.0.0.1:443 ssl http2

Также смените порт 80 на другой.

listen 127.0.0.1:80;

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

Типичные ошибки

Неверно выбранное доменное имя

Если на вашем сервере настроено несколько виртуальных хостов Nginx, и при попытке открыть один домен вы попадаете на другой, возможно, проблема заключается в том, что имя конфигурационного файла одного из хостов не имеет расширения.conf, из-за чего Nginx не загрузил его. Также причиной может быть наличие записи AAAA для домена без соответствующей настройки Nginx для работы с IPv6.

Это касается и веб-сервера Apache.

Сетевой протокол был нарушен.

При настройке заголовка send-proxy-v2 в HAProxy без активации proxy_protocol в Nginx или Apache, на сайте возникнет следующая ошибка.

Сайт столкнулся с нарушением сетевого протокола, которое не может быть устранено.

Обязательно перезапустите Nginx или Apache после того, как внесете изменения в файл конфигурации.

Ошибка PR_CONNECT_RESET_ERROR 3

Если вы активировали proxy_protocol в Nginx или Apache, но не добавили заголовок send-proxy-v2 в HAProxy, на вашем сайте возникнет эта ошибка.

Ошибка защищённого соединения. PR_CONNECT_RESET_ERROR

Вы встретите данное сообщение об ошибке в логах Nginx или Apache.

прерывистый заголовок при чтении протокола PROXY

Обязательно перезапустите Nginx или Apache после того, как внесете изменения в файл конфигурации.

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

Обновление: Я подумал, что вы можете настроить новый виртуальный хост Apache или Nginx на альтернативном адресе loopback, например, 127.0.0.4. В этом случае для нового виртуального хоста не будет активирован proxy_protocol.

Ошибка PR_END_OF_FILE_ERROR.

При активации proxy_protocol в Apache или Nginx и попытке зайти на виртуальный хост напрямую, минуя HAProxy, вы столкнетесь с определенной ошибкой.

PR_END_OF_FILE_ERROR

Ошибка SSL_ERROR_SYSCALL (5)

Когда вы применяете команду curl:

curl - I https://example.com

И наталкиваетесь на такую ошибку.

curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL в соединении с example.com:443

Вероятно, это связано с тем, что для данного домена не задано определение backend.

6 backend ‘apache’ не обнаруживает доступный сервер!

Если в журнале HAProxy (/var/log/haproxy.log) появилась эта ошибка, вам следует обратить внимание на настройки backend в HAProxy.

backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 send-proxy-v2 check

Удалите опцию check, чтобы устранить эту ошибку.

backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 send-proxy-v2

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

Итоговый анализ

Надеюсь, данный урок оказался для вас полезным в процессе настройки Apache, Nginx и HAProxy на одном сервере. Как обычно, если информация в этом посте была для вас ценной, не забудьте подписаться на нашу бесплатную рассылку, чтобы получать больше советов и рекомендаций.