Nginx как веб-сервер и прокси-сервер для Apache в Ubuntu 16.04
Apache и Nginx – популярные веб-серверы с открытым исходным кодом, которые часто используются для работы с PHP. Их можно использовать на одной виртуальной машине для поддержки нескольких веб-сайтов с разными требованиями. Обычно два веб-сервера в одной системе используют для работы с несколькими IP-адресами или различными портами.
Серверы с поддержкой адресов IPv4 и IPv6 можно настроить для обслуживания Apache на одном протоколе и Nginx на другом. Но это не очень практично, так как IPv6 до сих пор не получил широкого распространения. Можно также установить для второго веб-сервера другой номер порта, но использовать порты в ссылках очень неудобно.
Данное руководство поможет настроить Nginx как веб-сервер и прокси-сервер для Apache на одном сервере Ubuntu 16.04. При этом может понадобиться изменить код приложения, чтобы включить поддержку обратного прокси в Apache (особенно это касается сайтов с SSL). Чтобы избежать этого, можно установить специальный модуль Apache, mod_rpaf, который переопределяет некоторые переменные среды, благодаря чему Apache может напрямую обслуживать запросы клиентов.
В руководстве показано, как разместить четыре домена на одном сервере. Два из них будут обслуживаться Nginx: example.com (стандартный виртуальный хост) and sample.org. Другие два – Apache: foobar.net и test.io.
Требования
- Свежий сервер Ubuntu 16.04.
- Пользователь с правами sudo (инструкции по созданию такого пользователя – здесь).
- Доменные имена, направленные на IP-адрес сервера.
Дополнительные рекомендации
Для выполнения руководства нужны навыки работы с виртуальными хостами Apache и Nginx и SSL-сертификатами. Возможно, вам пригодятся следующие статьи:
- Настройка виртуальных хостов Apache в Ubuntu 16.04
- Настройка виртуальных хостов Nginx в Ubuntu 16.04
- Установка нескольких SSL-сертификатов на один IP с помощью Nginx
1: Установка Apache и PHP-FPM
Сначала нужно установить Apache и PHP-FPM. Также для работы понадобится модуль Apache для PHP FastCGI под названием libapache2-mod-fastcgi.
Обновите индекс пакетов:
sudo apt-get update
Установите необходимые программы:
sudo apt-get install apache2 libapache2-mod-fastcgi php-fpm
Теперь нужно настроить веб-сервер.
2: Настройка Apache и PHP-FPM
Теперь нужно настроить порт Apache (8080) и подготовить веб-сервер к работе с PHP-FPM с помощью модуля mod_fastcgi. Откройте конфигурационный файл Apache:
sudo nano /etc/apache2/ports.conf
Найдите строку:
Listen 80
Измените её:
Listen 8080
Сохраните и закройте файл.
Примечание: Обычно 127.0.0.1:8080 прослушивают прокси-серверы, но это позволит установить в качестве значения переменной окружения РНР server_addr loopback IP-адрес вместо внешнего IP сервера. В данном случае целью является такая настройка Apache, при которой веб-сайты, поддерживаемые Apache, не увидят обратного прокси-сервера. Таким образом, Apache нужно настроить для прослушивания порта 8080 на всех IP-адресах.
После этого нужно отредактировать стандартный виртуальный хост Apache. Директива <VirtualHost> в этом файле обслуживает сайты только на порт 80, это нужно изменить. Откройте файл:
sudo nano /etc/apache2/sites-available/000-default.conf
Первая строка должна выглядеть так:
<VirtualHost *:80>
Измените её:
<VirtualHost *:8080>
Сохраните и закройте файл. Перезапустите Apache.
sudo systemctl reload apache2
Убедитесь, что порт изменился:
sudo netstat -tlpn
Вывод должен выглядеть так:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1086/sshd
tcp6 0 0 :::8080 :::* LISTEN 4678/apache2
tcp6 0 0 :::22 :::* LISTEN 1086/sshd
3: Настройка модуля mod_fastcgi
По умолчанию Apache обслуживает PHP-страницы с помощью модуля mod_php. Но в данном случае нужен дополнительный модуль для PHP-FPM.
Примечание: Если вы выполняете руководство на сервере с LAMP и включенным модулем mod_php, сначала отключите модуль:
sudo a2dismod php7.0
Добавьте блок настроек для mod_fastcgi. Этот блок зависит от mod_action. Чтобы включить mod_action, введите:
sudo a2enmod actions
Эти директивы передают запросы для файлов .php на UNIX-сокет PHP-FPM.
sudo nano /etc/apache2/mods-enabled/fastcgi.conf
Добавьте в конец блока <IfModule mod_fastcgi.c> . . . </IfModule> следующие строки:
AddType application/x-httpd-fastphp .php
Action application/x-httpd-fastphp /php-fcgi
Alias /php-fcgi /usr/lib/cgi-bin/php-fcgi
FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -socket /run/php/php7.0-fpm.sock -pass-header Authorization
<Directory /usr/lib/cgi-bin>
Require all granted
</Directory>
Сохраните и закройте файл. Проверьте конфигурации:
sudo apachectl -t
Если команда вернула Syntax OK, перезапустите Apache. Если на экране появилось предупреждение:
Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message.
Проигнорируйте его.
sudo systemctl reload apache2
4: Тестирование PHP
Убедитесь, что PHP работает должным образом. Создайте файл phpinfo() и откройте его в браузере.
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php
Чтобы открыть файл в браузере, перейдите по ссылке:
http://your_ip_address:8080/info.php
На экране появится список настроек PHP.
В верхней части страницы найдите Server API, в этой строке должно быть указано FPM/FastCGI. Затем найдите раздел PHP Variables, строку SERVER_SOFTWARE. Она должна содержать Apache и Ubuntu. Это подтверждает, что mod_fastcgi включен и Apache поддерживает PHP-FPM для обработки файлов PHP.
5: Создание виртуального хоста Apache
Создайте виртуальные хосты Apache для доменов foobar.net и test.io. Сначала создайте каталоги document root для обоих сайтов.
sudo mkdir -v /var/www/{foobar.net,test.io}
Затем создайте index-файлы для каждого сайта:
echo "<h1 style='color: green;'>Foo Bar</h1>" | sudo tee /var/www/foobar.net/index.html
echo "<h1 style='color: red;'>Test IO</h1>" | sudo tee /var/www/test.io/index.html
Чтобы протестировать PHP, создайте phpinfo() для каждого сайта.
echo "<?php phpinfo(); ?>" | sudo tee /var/www/foobar.net/info.php
echo "<?php phpinfo(); ?>" | sudo tee /var/www/test.io/info.php
Затем создайте файл виртуального хоста для домена foobar.net.
sudo nano /etc/apache2/sites-available/foobar.net.conf
Поместите в него следующий код:
<VirtualHost *:8080>
ServerName foobar.net
ServerAlias www.foobar.net
DocumentRoot /var/www/foobar.net
<Directory /var/www/foobar.net>
AllowOverride All
</Directory>
</VirtualHost>
Примечание: AllowOverride All включает поддержку .htaccess.
Теперь файл содержит базовые директивы виртуального хоста. Подробнее процесс создания виртуальных хостов описан здесь.
Сохраните и закройте файл.
Теперь создайте такой же файл для test.io.
sudo nano /etc/apache2/sites-available/test.io.conf
<VirtualHost *:8080>
ServerName test.io
ServerAlias www.test.io
DocumentRoot /var/www/test.io
<Directory /var/www/test.io>
AllowOverride All
</Directory>
</VirtualHost>
Итак, теперь виртуальные хосты Apache готовы. Чтобы включить сайты, используйте команду a2ensite, которая создаст символьные ссылки на виртуальные хосты в каталоге sites-enabled.
sudo a2ensite foobar.net
sudo a2ensite test.io
Проверьте синтаксис Apache:
sudo apachectl -t
Если ошибок нет, перезапустите веб-сервер:
sudo systemctl reload apache2
Чтобы убедиться, что сайты работают и что каждый сайт отображает содержимое файла index.html, откройте в браузере:
http://foobar.net:8080
http://test.io:8080
На экране появится:
Foo Bar
и
Test IO
Убедитесь, что PHP работает. Для этого откройте файлы info.php каждого сайта. Эти файлы доступны по ссылкам:
http://foobar.net:8080/info.php
http://test.io:8080/info.php
На экране должен появиться список настроек PHP (как в шаге 4).
Теперь Apache обслуживает два сайта на порте 8080.
6: Установка и настройка Nginx
Теперь нужно установить Nginx и настроить виртуальные хосты для доменов example.com и sample.org.
Примечание: Подробные инструкции по созданию виртуальных хостов Nginx можно найти здесь.
Установите Nginx:
sudo apt-get install nginx
Удалите символьную ссылку стандартного виртуального хоста, он в дальнейшем не понадобится.
sudo rm /etc/nginx/sites-enabled/default
Теперь нужно создать новые виртуальные хосты для сайтов. Сначала создайте каталоги:
sudo mkdir -v /usr/share/nginx/{example.com,sample.org}
Затем создайте файлы index и phpinfo():
echo "<h1 style='color: green;'>Example.com</h1>" | sudo tee /usr/share/nginx/example.com/index.html
echo "<h1 style='color: red;'>Sample.org</h1>" | sudo tee /usr/share/nginx/sample.org/index.html
echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/example.com/info.php
echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/sample.org/info.php
Теперь создайте виртуальный хост для example.com.
sudo nano /etc/nginx/sites-available/example.com
В этом файле создайте блок server для первого сайта, example.com. Директива default_server сделает этот файл виртуальным хостом по умолчанию. Он будет обрабатывать HTTP-запросы, которые не соответствуют другим виртуальным хостам.
Вставьте в файл следующий код:
server {
listen 80 default_server;
root /usr/share/nginx/example.com;
index index.php index.html index.htm;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
include snippets/fastcgi-php.conf;
}
}
Сохраните и закройте файл. Теперь создайте виртуальный хост для sample.org.
sudo nano /etc/nginx/sites-available/sample.org
Вставьте в файл:
server {
root /usr/share/nginx/sample.org;
index index.php index.html index.htm;
server_name sample.org www.sample.org;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
include snippets/fastcgi-php.conf;
}
}
Сохраните и закройте файл. Чтобы включить сайты, создайте символьные ссылки для них:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo ln -s /etc/nginx/sites-available/sample.org /etc/nginx/sites-enabled/sample.org
Проверьте синтаксис Nginx:
sudo nginx -t
Если ошибок нет, перезапустите веб-сервер:
sudo systemctl reload nginx
Теперь попробуйте открыть в браузере файлы phpinfo() для виртуальных хостов Nginx.
http://example.com/info.php
http://sample.org/info.php
Проверьте раздел PHP Variables.
Строка [“SERVER_SOFTWARE”] должна показывать nginx (это значит, что файлы обслуживаются сервером Nginx). В [“DOCUMENT_ROOT”] должен находиться путь к root-каталогу сайта.
Теперь веб-сервер Nginx установлен и поддерживает два сайта.
7: Настройка Nginx для поддержки виртуальных хостов Apache
Теперь нужно создать дополнительный хост Nginx для нескольких доменов. Запросы к этим доменам будут проксироваться на Apache.
Создайте новый файл:
sudo nano /etc/nginx/sites-available/apache
Добавьте в него следующий блок настроек. Он задаёт имена сайтов Apache и проксирует их запросы. В proxy_pass укажите внешний IP.
server {
listen 80;
server_name foobar.net www.foobar.net test.io www.test.io;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Сохраните и закройте файл. Создайте символьную ссылку:
sudo ln -s /etc/nginx/sites-available/apache /etc/nginx/sites-enabled/apache
Проверьте настройки:
sudo nginx -t
Перезапустите Nginx, если ошибок не обнаружено.
sudo systemctl reload nginx
Откройте браузер и перейдите по ссылке:
http://foobar.net/info.php
Найдите раздел PHP Variables. Переменные SERVER_SOFTWARE и DOCUMENT_ROOT подтверждают, что запрос был обработан Apache. Переменные HTTPXREAL_IP и HTTPXFORWARDED_FOR добавлены сервером Nginx и отображают внешний IP-адрес текущей машины.
Теперь Apache использует Nginx в качестве обратного прокси-сервера. Теперь нужно установить переменную Apache, REMOTE_ADDR. Она позволяет «скрыть» прокси-сервер.
8: Установка и настройка mod_rpaf
Теперь нужно установить модуль mod_rpaf, который будет переопределять значения REMOTE_ADDR, HTTPS и HTTP_PORT с помощью значений, предоставленных обратным прокси-сервером. Без этого модуля некоторые приложения PHP
могут потребовать изменений в коде. Модуль можно найти в репозитории Ubuntu, его пакет называется libapache2-mod-rpaf. Однако этот пакет устаревший и не поддерживает некоторых директив. Потому лучше скомпилировать модуль из исходного кода.
Чтобы собрать модуль, установите пакеты:
sudo apt-get install unzip build-essential apache2-dev
Загрузите последний релиз с GitHub:
wget https://github.com/gnif/mod_rpaf/archive/stable.zip
Распакуйте его:
unzip stable.zip
Перейдите в рабочий каталог:
cd mod_rpaf-stable
Скомпилируйте и установите модуль:
make
sudo make install
В каталоге mods-available создайте файл для модуля rpaf.
sudo nano /etc/apache2/mods-available/rpaf.load
Вставьте в файл:
LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.so
Создайте файл для настроек модуля:
sudo nano /etc/apache2/mods-available/rpaf.conf
Добавьте в конфигурационный файл следующие строки:
<IfModule mod_rpaf.c>
RPAF_Enable On
RPAF_Header X-Real-Ip
RPAF_ProxyIPs your_server_ip
RPAF_SetHostName On
RPAF_SetHTTPS On
RPAF_SetPort On
</IfModule>
Этот файл содержит следующие настройки:
- RPAF_Header: хедер для клиентского IP-адреса.
- RPAF_ProxyIPs: IP прокси-сервера, для которого нужно отредактировать запросы.
- RPAF_SetHostName: обновление имени виртуального хоста для ServerName и ServerAlias.
- RPAF_SetHTTPS: настраивает переменную среды HTTPS на основе значения X-Forwarded-Proto.
- RPAF_SetPort: устанавливает переменную среды SERVER_PORT (эта настройка полезна для Apache на SSL).
Сохраните файл rpaf.conf и включите модуль:
sudo a2enmod rpaf
Эта команда создаст символьную ссылку файлов rpaf.load и rpaf.conf в каталоге mods-enabled. Проверьте настройки:
sudo apachectl -t
Перезапустите Apache, если ошибок не обнаружено.
sudo systemctl reload apache2
Откройте страницу phpinfo() одного из сайтов Apache и найдите раздел PHP Variables. Переменная REMOTE_ADDR теперь должна содержать IP локального сервера.
9: Настройка сайтов HTTPS (опционально)
Теперь нужно создать SSL-сертификаты для сайтов Apache. Nginx поддерживает терминацию SSL, потому можно настроить SSL, не изменяя настроек Apache.
Модуль mod_rpaf установит все переменные Apache, необходимые для поддержки SSL.
Создайте каталог для SSL-сертификатов и закрытых ключей:
sudo mkdir /etc/nginx/ssl
В данном руководстве используются самоподписанные сертификаты, действительные в течение 10 лет. Чтобы создать такие сертификаты, введите:
sudo openssl req -x509 -sha256 -newkey rsa:2048 -keyout /etc/nginx/ssl/foobar.net-key.pem -out /etc/nginx/ssl/foobar.net-cert.pem -days 3650 -nodes
sudo openssl req -x509 -sha256 -newkey rsa:2048 -keyout /etc/nginx/ssl/test.io-key.pem -out /etc/nginx/ssl/test.io-cert.pem -days 3650 -nodes
После запуска каждой команды программа предложит вам указать данные о сайте. В поле Common Name нужно указать доменное имя.
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:8host Inc
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:foobar.net
Email Address []:
Откройте файл виртуального хоста Apache, который проксирует запросы с Nginx на Apache.
sudo nano /etc/nginx/sites-available/apache
Каждый домен имеет индивидуальный сертификат и ключ. Эти данные нужно указать в отдельных блоках server { . . . }. Удалите текущее содержимое файл аи вставьте в него новый код:
server {
listen 80;
listen 443 ssl;
server_name test.io www.test.io;
ssl on;
ssl_certificate /etc/nginx/ssl/test.io-cert.pem;
ssl_certificate_key /etc/nginx/ssl/test.io-key.pem;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
listen 443 ssl;
server_name foobar.net www.foobar.net;
ssl on;
ssl_certificate /etc/nginx/ssl/foobar.net-cert.pem;
ssl_certificate_key /etc/nginx/ssl/foobar.net-key.pem;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Исходный код блока разделен на два отдельных блока. Также теперь Nginx прослушивает порт 443.
Сохраните файл и проверьте синтаксис:
sudo nginx -t
Если ошибок нет, перезапустите Nginx:
sudo systemctl reload nginx
Откройте любой из доменов Apache в браузере с префиксом https://:
https://foobar.net/info.php
Примечание: Поскольку в руководстве используется самоподписанный сертификат, браузер, скорее всего, сообщит о том, что этот сайт небезопасен. Это нормально, просто браузер не может найти подписи ЦС, которому он мог бы доверять.
Перейдите в раздел PHP Variables. Переменная SERVER_PORT имеет значение 443, переменная HTTPS – значение on (поскольку доступ к сайту Apache был получен по HTTPS). С такими настройками вам не придётся переписывать код PHP-приложения.
10: Блокирование прямого доступа к Apache (опционально)
Apache слушает порт 8080 на внешнем IP-адресе, потому доступ к нему может получить любой желающий. Этот доступ можно заблокировать с помощью брандмауэра IPtables.
sudo iptables -I INPUT -p tcp --dport 8080 ! -s your_server_ip -j REJECT --reject-with tcp-reset
Примечание: Вместо your_server_ip укажите IP-адрес сервера.
Теперь порт 8080 блокируется брандмауэром, и доступ к Apache закрыт.
Откройте браузер и попробуйте получить доступ к одному из сайтов Apache.
http://example.com:8080
Браузер должен выдать сообщение об ошибке Unable to connect или Webpage is not available. Директива tcp-reset позволяет скрыть от посторонних разницу между портами.
Примечание: Правила IPtables сбрасываются при каждой перезагрузке сервера. Чтобы сохранить их, используйте iptables-persistent. Больше информации о IPTables – по этой ссылке.
11: Обслуживание статических файлов с помощью Nginx
Когда Nginx проксирует запросы доменов Apache, он отправляет Apache запрос каждого файла. Nginx быстрее, чем Apache, обслуживает статические файлы (изображения, JavaScript, стили). Отредактируйте виртуальный хост apache, чтобы настроить отправку PHP-запросов.
Откройте файл apache
sudo nano /etc/nginx/sites-available/apache
Добавьте два блока location в каждый блок server и отредактируйте существующие блоки location.
Примечание: Вы можете просто заменить содержимое файла предложенными ниже конфигурациями.
Также нужно указать Nginx, где хранятся статические файлы каждого сайта.
server {
listen 80;
server_name test.io www.test.io;
root /var/www/test.io;
index index.php index.htm index.html;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
proxy_pass http://your_ip_address:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ /\. {
deny all;
}
}
server {
listen 80;
server_name foobar.net www.foobar.net;
root /var/www/foobar.net;
index index.php index.htm index.html;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
proxy_pass http://your_ip_address:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ /\. {
deny all;
}
}
Примечание: Чтобы настроить HTTPS, оставьте строку listen 443 ssl; и другие параметры SSL (шаг 9).
Директива try_files позволяет Nginx просматривать файлы в document root и сразу обслуживать их. Если у файла расширение .php, запрос будет передан Apache. Если файла нет в document root, запрос будет передан Apache.
Предупреждение: Директива location ~ /\. очень важна. Она блокирует обслуживание файлов htaccess и .htpasswd.
Сохраните и закройте файл. Проверьте код на наличие ошибок:
sudo nginx -t
Перезапустите Nginx:
sudo service nginx reload
Убедитесь, что всё работает. Откройте лог-файлы Apache (/var/log/apache2) и просмотрите запросы GET для файлов info.php сайтов test.io и foobar.net. Команда tail выведет последние строки файла, а флаг –f покажет его изменения.
sudo tail -f /var/log/apache2/other_vhosts_access.log
Откройте в браузере:
http://test.io/info.php
А затем проверьте ответ лога. Apache вернёт:
test.io:80 your_server_ip - - [01/Jul/2016:18:18:34 -0400] "GET /info.php HTTP/1.0" 200 20414 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36"
Проверьте страницу index.html каждого сайта. Вы не увидите записей от Apache. Все запросы обрабатывает Nginx.
Чтобы остановить команду tail, нажмите CTRL+C.
Единственным недостатком этой настройки является то, что Apache не сможет ограничивать доступ к статическим файлам. Доступ можно ограничить с помощью файла виртуального хоста apache.
Tags: Apache, NGINX, php-fpm, Ubuntu 16.04
1 комментарий
Как потом правильно добавлять хосты через apache2 ?
А то я пытался вроде работает, но не пойму в nginx нужно что прописывать или нет.
Он и без записей начал работать это нормально?