Nginx в качестве проксирующего сервера Apache
В предыдущей статье, "Веб сервер Nginx, обзор функциональных возможностей", речь шла об основных функциональных возможностях сервера Nginx, а так-же затронут вопрос его использования в качестве проксирующего фронтенд-сервера в связке с веб сервером Apache. Здесь хотелось-бы рассказать о практической стороне вопроса, то есть перейти непосредственно к установке и настройке вышеупомянутой связки, Nginx - Apache. Так как всем остальным *nix системам, я предпочитаю FreeBSD, на ней и будем все это поднимать.
Итак, имеем операционную систему FreeBSD 7.1 STABLE платформа amd64, с установленным веб сервером Apache/2.2.9. Общая схема работы, то есть взаимодействия, клиент - Nginx - Apache, будет выглядеть следующим образом:
В операционной системе FreeBSD, стандартным способом установки приложений, является система портов, поэтому не будем изобретать велосипед с исходниками ( хотя иногда конечно может и это понадобиться ), а воспользуемся портами, во первых это удобней, во-вторых установка по-умолчанию, подходит для большинства ситуаций, ну и в третьих, при установке из портов, приложение автоматически попадает в базу данных установленных пакетов /var/db/pkg, и в последствии доступно для таких программ как pkg_info и portupgrade.
Установка веб сервера Nginx из портов FreeBSD
vds-admin /# cd /usr/ports Переходим в каталог портов vds-admin /usr/ports# make search name=nginx Ищем нужный порт Port: nginx-0.7.61 Стабильная версия сервера Nginx Path: /usr/ports/www/nginx Info: Robust and small WWW server Maint: osa@FreeBSD.org B-deps: pcre-7.9 R-deps: pcre-7.9 WWW: http://sysoev.ru/nginx/ Port: nginx-devel-0.8.4 Версия для разработки Path: /usr/ports/www/nginx-devel Info: Robust and small WWW server Maint: osa@FreeBSD.org B-deps: pcre-7.9 R-deps: pcre-7.9 WWW: http://sysoev.ru/nginx/ vds-admin /usr/ports# cd www/nginx Ставить будем стабильную версию, туда и идем vds-admin /usr/portswww/nginx# make install clean
После запуска утилиты make на экран лезет довольно внушительный список дополнительных модулей, которые можно включить или выключить. Никакой экзотики нам в данном случае не нужно, я все оставил по-умолчанию. Честно говоря я не пользуюсь данными опциями а предпочитаю запускать скрипт configure, он предоставляет возможность более гибкой настройки параметров сборки и установки, например, выбор директории для установки, расположение конфигурационных файлов, лог файлов, бинарников, и прочее. Итак, вот весь список предлагаемых опций с краткими описаниями.
[ ] DEBUG Режим отладки. Полезно на стадии тестирования и отладки конфигурации [ ] IPV6 Поддержка протокола IP 6-й версии [ ] GOOGLE_PERFTOOLS Включить поддержку google-perftools [X] HTTP_MODULE Включение функций HTTP сервера [ ] HTTP_ACCESSKEY_MODULE Модуль для генерации защищенных ссылок [ ] HTTP_ADDITION_MODULE Фильтр, добавляющий текст до и после ответа [ ] HTTP_DAV_MODULE Модуль для поддержки WebDAV методов PUT, DELETE, MKCOL, COPY и MOVE [ ] HTTP_EVAL_MODULE Разбирает ответ проксируемого сервера или memcached сервера на переменные [ ] HTTP_FANCYINDEX_MODULE Модуль позволяющий строить листинг файлов с добавлением стилей [ ] HTTP_FLV_MODULE Модуль для стриминга флэш-видео в формате flv [ ] HTTP_GZIP_STATIC_MODULE Модуль для отдачи клиенту предварительно сжатого файла с тем-же именем но с расширением ".gz". [ ] HTTP_MOGILEFS_MODULE Поддержка файловой системы mogilefs. [ ] HTTP_PERL_MODULE Встроенный Perl. [ ] HTTP_RANDOM_INDEX_MODULE Модуль, выдает в качестве индексного файла, случайный файл из каталога. [ ] HTTP_REALIP_MODULE Модуль для замены адреса клиента в заголовке. [ ] HTTP_RESPONSE_MODULE Модуль для отдачи произвольного текста, прописанного в директивы модуля. [X] HTTP_REWRITE_MODULE Модуль для изменения URI с помощью регулярных выражений, выдачи редиректов и выбора конфигурации в зависимости от переменных. [ ] HTTP_SECURE_LINK_MODULE Модуль для проверки правильности запрошенной ссылки. [ ] HTTP_SSL_MODULE Модуль поддержки SSL. [X] HTTP_STATUS_MODULE Модуль, показывающий информационную страницу о текущем статусе Nginx. [ ] HTTP_SUB_MODULE Модуль для замены в ответе, одной строки, на другую. [ ] HTTP_UPLOAD_MODULE Модуль для аплоадов multipart/form-data. [ ] HTTP_UPLOAD_PROGRESS В силу особенностей реализации nginx, без данного модуля не получится организовать показ статуса загрузки файлов. [ ] HTTP_UPSTREAM_FAIR Модуль для балансировки нагрузки. Отправляет входящие запросы на наименее загруженный бакэнд. [ ] HTTP_UPSTREAM_KEEPALIVE Поддержка keepalive- соединений с бакэндами, в том числе memcached. [ ] HTTP_XSLT_MODULE XSLT фильтр. [ ] HTTP_ZIP_MODULE Модуль для создания zip архивов "на лету". [ ] MAIL_MODULE Модуль для работы nGinx в качестве почтового прокси сервера. [ ] MAIL_IMAP_MODULE Модуль IMAP4 прокси. [ ] MAIL_POP3_MODULE Модуль POP3 прокси. [ ] MAIL_SMTP_MODULE Модуль SMTP прокси. [ ] MAIL_SSL_MODULE Модуль для поддержки SSL/TLS для POP3/IMAP/SMTP. [ ] PASSENGER_MODULE Аналог апачевского mod_rails ( Phusion Passenge ). [X] WWW Стандартный набор HTML файлов для проверки.
После нажатия [ Ok ], начинается процесс конфигурирования, сборки и установки веб сервера Nginx. По окончанию, проверяем, что и как у нас установилось:
vds-admin /usr/ports/www/nginx# rehash Перечитать пути к исполняемым файлам. vds-admin /usr/ports/www/nginx# nginx -v Версия Nginx. nginx version: nginx/0.7.61 vds-admin /usr/ports/www/nginx# nginx -V Параметры с которыми был установлен Nginx. nginx version: nginx/0.7.61 configure arguments: --prefix=/usr/local/etc/nginx --with-cc-opt='-I /usr/local/include' --with-ld-opt='-L /usr/local/lib' --conf-path=/usr/local/etc/nginx/nginx.conf --sbin-path=/usr/local/sbin/nginx --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx-error.log --user=www --group=www --http-client-body-temp-path=/var/tmp/nginx/client_body_temp --http-proxy-temp-path=/var/tmp/nginx/proxy_temp --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi_temp --http-log-path=/var/log/nginx-access.log --with-http_stub_status_module --with-pcre
Настройка сервера Nginx в качестве reverse-proxy сервера
Итак, веб сервер Nginx установлен. Всю интересующую информацию по расположению директорий и файлов Nginx, выдает вышеприведенная команда, nginx -V.
Рабочая директория располагается в /usr/local/etc/nginx ( если при запуске configure, не указано иное ), там-же находится главный конфигурационный файл /usr/local/etc/nginx/nginx.conf, бинарный файл nginx, расположен по пути, /usr/local/sbin/nginx ( опять-же если указано иное ). Директории, client_body_temp, proxy_temp, fastcgi_temp, являются служебными и предназначены для хранения временных файлов различными модулями сервера Nginx. Кроме того, были установлены пользователь и группа от имени которых будут запускаться рабочие процессы, по-умолчанию это www.
Теперь нужно пересадить сервер Apache на другой адрес или порт. Здесь есть несколько вариантов, все зависит от конкретной ситуации. Например у вас один внешний IP адрес, именно на нем, на 80-м порту, должен слушать Nginx и принимать входящие HTTP соединения, соответственно Apache там быть не должно, его можно посадить на локальный адрес 127.0.0.1, порт может быть любой, например, тоже 80, внешние соединения все равно не попадут на него, либо можно оставить Apache на том-же адресе, но назначить порт, отличный от 80, например 8080, либо, если есть такая необходимость, сделать и то и другое.
Правим конфигурационные файлы Apache. Сначала изменим адрес или порт на котором Apache принимает соединения, файл httpd.conf, находим директиву Listen и устанавливаем следующее значение:
Listen 127.0.0.1:80 Мы оставим именно это значение, что-бы не устраивать путаницу.
Как было сказано ранее, в зависимости от вашей ситуации, можно поставить и так:
listen внешний_IP_адрес:8080
или так:
Listen 12345
Все приведенные значения одинаково рабочие.
Если вы планируете обслуживать несколько виртуальных хостов, придется подправить соответствующий файл конфигурации, в Apache2, это /extra/httpd-vhosts.conf:
NameVirtualHost *:80
ServerAdmin webmaster@nginxhost
DocumentRoot "/usr/home/nginxhost/public_html"
ServerName nginxhost
ServerAlias nginxhost
ErrorLog "/var/log/nginxhost"
CustomLog "/var/log/nginxhost_custom" common
Не забываем перезапустить Apache. Для этого можно использовать и стартовый скрипт в /usr/local/etc/rc.d, но мне привычней так:
vds-admin /# /usr/local/sbin/apachectl configtest Syntax OK vds-admin /# /usr/local/sbin/apachectl graceful
Смотрим что у нас показывает netstat -Lan:
vds-admin /# netstat -Lan Current listen queue sizes (qlen/incqlen/maxqlen) Proto Listen Local Address tcp4 0/0/128 127.0.0.1.80 Вот наш Apache ....................... .......................
Вроде все работает, но есть один нюанс, сервер Apache не будет видеть реальные IP адреса клиентов, для него все запросы будут приходить с адреса 127.0.0.1, его он и будет писать в свои лог файлы. Естественно это неправильно. Что-бы исправить ситуацию, необходимо установить для Apache, дополнительный модуль, mod_fpaf, а из Nginx передавать дополнительные заголовки, устанавливая их специальными директивами конфигурационного файла. Этим сейчас и займемся.
vds-admin /usr/ports# make search name=mod_rpaf Ищем в портах необходимый модуль. v Port: mod_rpaf-0.6 Этот нам не интересен, он для Apache 1.3 Path: /usr/ports/www/mod_rpaf Info: Make proxied requests appear with client IP Maint: apache@FreeBSD.org B-deps: apache-1.3.41_1 expat-2.0.1 perl-5.8.9_3 R-deps: apache-1.3.41_1 expat-2.0.1 perl-5.8.9_3 WWW: http://stderr.net/apache/rpaf/ Port: mod_rpaf-ap2-0.6 Этот мы и будем ставить Path: /usr/ports/www/mod_rpaf2 Info: Make proxied requests appear with client IP Maint: apache@FreeBSD.org B-deps: apache-2.0.63_3 expat-2.0.1 libiconv-1.13 perl-5.8.9_3 R-deps: apache-2.0.63_3 expat-2.0.1 libiconv-1.13 perl-5.8.9_3 WWW: http://stderr.net/apache/rpaf/ vds-admin /usr/ports# cd www/mod_rpaf2 vds-admin /usr/ports/www/mod_rpaf2# make install clean
Установка длится меньше минуты. Когда все закончится, снова идем в файл конфигурации Apache, httpd.conf. При установке mod_rpaf в конфигурационный файл, должна была добавиться следующая строка:
LoadModule rpaf_module libexec/apache22/mod_rpaf.so После установки, строка закомментирована.
Раскомментируйте строку загрузки модуля, если нужно mod_rpaf, а ниже допишите следующие строки, это такой мини-конфиг модуля:
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1
RPAFheader X-Forwarded-For
Проверяем конфигурационный файл на предмет синтаксических ошибок и перезагружаем Apache. С ним вроде закончили.
vds-admin /# /usr/local/sbin/apachectl configtest Syntax OK vds-admin /# /usr/local/sbin/apachectl graceful
Я использую вышеприведенный вариант по привычке, мне так удобней, вы можете сделать все это с помощью стартового скрипта из /usr/local/etc/rc.d
Теперь перейдем к Nginx. Настроим минимальную рабочую конфигурацию, при которой все запросы будут уходить на Apache, кроме картинок.
user www; #Имя пользователя, под которым запускаются рабочие процессы сервера Nginx. worker_processes 1; #Количество рабочих процессов Nginx. error_log logs/error.log; #Файл ошибок. events { worker_connections 1024; #Количество соединений на рабочий процесс. Кроме того в данную секцию прописываются методы обработки соединений сервером Nginx } http { #В блоке http, прописываются глобальные настройки, которые могут быть переопределены во вложенных дочерних блоках Server или Location. include mime.types; #Включение файла с перечисленными типами данных. default_type application/octet-stream; #Тип данных по-умолчанию. log_format main '$remote_addr - $remote_user [$time_local] "$request" ' #Настройка формата логов. '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; sendfile on; tcp_nopush on; keepalive_timeout 65; gzip on; server { #Секция настроек конкретного виртуального сервера. listen 192.168.50.20:80; #Внешний адрес и порт на которых сервер Nginx будет принимать соединения. server_name nginxhost; #Имя виртуального хоста. access_log logs/nginxhost.access.log main; location / { #Отсюда, все запросы будут отправлены на Apache. proxy_pass http://127.0.0.1; #Apache у нас на 80 порту, поэтому достаточно указать адрес. Установка необходимых заголовков, для передачи Apache имени виртуального хоста и реального IP адреса клиента. proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~* \.(jpg|jpeg|gif|png|ico) { #В данной секции используется регулярное выражение, под которое подпадают все файлы, с перечисленными расширениями, как видите это картинки. Nginx будет сам обрабатывать запросы попадающие в этот блок. root /usr/home/test/public_html; #Корень дерева документов для данного Location. } ################### Обработка ошибок ######################## error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/local/www/nginx-dist; } ################### Обработка ошибок ######################## } }
Проверяем правильность конфигурационного файла командой nginx -t.
[emerg]: open() "/usr/local/etc/nginx/logs/error.log" failed (2: No such file or directory) configuration file /usr/local/etc/nginx/nginx.conf test failed
Ага.. ошибка. Nginx не может найти папку logs, указанную в пути для лог файла, в файле конфигурации. Просто создадим ее:
vds-admin /usr/local/etc/nginx# mkdir logs Создать директорию. vds-admin /usr/local/etc/nginx# nginx -t Проверяем. the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok configuration file /usr/local/etc/nginx/nginx.conf test is successful
Проверка конфигурации закончилась успешно. Запускаем веб сервер Nginx и смотрим netstat -Lan:
vds-admin /# nginx vds-admin /# netstat -Lan Current listen queue sizes (qlen/incqlen/maxqlen) Proto Listen Local Address tcp4 0/0/128 192.168.50.20.80 А вот и он. ................................... ...................................
Теперь можно проверить. В папку, которая указана у нас как корень дерева документов в настройках виртуального хоста Apache, то есть /usr/home/nginxhost/public_html, я положил небольшой файл, index.php, следующего содержания:
<?php
echo $_SERVER['DOCUMENT_ROOT'];
?>
Набираем в браузере адрес, на котором Nginx ожидает соединений, 192.168.50.20. Запрос сначала попадает к Nginx, в location /, оттуда будет отправлен на Apache, который и сгенерирует контент, вернув готовый ответ серверу Nginx, а Nginx в свою очередь выдаст его в браузер. В браузере мы получим:
/usr/home/nginxhost/public_html
Если заглянуть в лог файл хоста Apache, /var/log/nginxhost_custom, можно увидеть наш запрос. Если же в директорию с документами, рядом с index.php, положить какой-нибудь графический файл, например image.jpg и запросить его через браузер 192.168.50.20/image.jpg, и после этого снова проверить /var/log/nginxhost_custom, этого запроса мы там не увидим, вместо этого он появился в лог файле Nginx'а, то есть в /usr/local/etc/nginx/logs/nginxhost.access.log. Это результат работы блока Location с регулярным выражением, \.(jpg|jpeg|gif|png|ico), которое соответствует любому файлу с одним из перечисленных расширений, конфигурационного файла Nginx.
Если вы обратили внимание, в лог файле сервера Apache, IP адрес, запросов приходящие от сервера Nginx, прописываются как локальные, 127.0.0.1, то есть Apache видит адрес проксирующего сервера а не реальные адреса клиентов. Для того что-бы это исправить, необходимо установить специальный модуль
Вот мы и настроили простейший вариант связки, фронтэнд ( Nginx ) -- бакэнд ( Apache ).
P.S. Целью данной статьи не является, предоставление готового рабочего решения для какого-то конкретного сервера, это лишь описание принципа взаимодействия Nginx - Apache, на рабочем, максимально упрощенном, примере.
Комментарии
Есть ли смысл устанавливать связку Nginx(фронтэнд) - Apache(бакэнд), если на вебсервере планируется разместить несколько сайтов с CMS Joomla 1.5 - 1.7 или можно обойтись Nginx - FastCGI?
ну можно обойтись, если руки правильно заточены :)
))) это точно. Если я правильно понимаю, то можно настроить Nginx - FastCGI (для обработки php) и правильно прописать RewriteRule и настройки вирт.хостов как у вас в статье http://vds-admin.ru/nginx/zamena-rewriterule-v-nginx-dlya-razlichnykh-cms. Этого будет достаточно для правильной работы? Если появятся вопросы могу обратиться за помощью и консультацией???
да, конечно )
здравствуйте,
что-то не получилось у меня работа в такой схеме,
почти ничего не менял, но тестовый файлик пытается обработать сам гникс.
и поскольку в нем нет модуля для работы с пхп, то он его выводит как текст.
подскажите, что не так настроил?
ну так а как апач настроен, по первым ощущениям у вас апач не так настроен
Спасибо за статью! Помогли избавиться от 502 ошибки, просидел за компом 12 часов, настроил за 5 минут.
пожалуйста :)
Здравствуйте! А если апач настроен на тот же ip только другой порт, как у вас тут:
есть ли смысл в модуле rpaf_module ?
Отправить комментарий