Введение
Как настроить nginx в качестве frontend к apache и зачем это нужно — написано неоднократно, в том числе и на Хабре. Мой случай немного отличается от классического. Начиналось все как обычно, проект на apache, увеличение количества посетителей и, связанная с ним, недостаточность ресурсов сервера. Но проект использовал SSL для защиты обмена данными с клиентами. С чем я столкнулся и как решил проблемы я расскажу под катом.
Проблемы
Поскольку непосредственный прием запросов клиентов перешел на плечи nginx то и работу с SSL надо переносить на него же. Apache, который теперь висел но loopback 127.0.0.1:8080, в поддержке SSL не нуждался. Первая проблемка заключалась в том, что сертификат был от Thawte, а они требовали использования промежуточного сертификата. Nginx для работы с такими сертификатами не имеет специальной директивы. В конфиге apache было так:
<VirtualHost 1.2.3.4:443>
...
SSLEngine on
SSLCertificateFile /usr/local/ssl/www.blabla.ru/public.crt
SSLCertificateKeyFile /usr/local/ssl/www.blabla.ru/private.key
SSLCACertificateFile /usr/local/ssl/www.blabla.ru/intermediate.crt
...
</VirtualHost>
Как быть с SSLCACertificateFile в nginx? Оказалось надо просто «срастить» два файла, поместив их содержимое в один (публичный сертификат, следом промежуточный):
cd /usr/local/ssl/www.blabla.ru
cp public.crt public_concat.crt
cat intermediate.crt >> public_concat.crt
Все, теперь в nginx просто пишем:
server {
listen 1.2.3.4:443;
server_name www.blabla.ru;
ssl on;
ssl_certificate /usr/local/ssl/www.blabla.ru/public_concat.crt;
ssl_certificate_key /usr/local/ssl/www.blabla.ru/private.key;
...
}
Редирект с незащищенного сайта на защищенный сложностей в настройке не вызвал:
server {
listen 1.2.3.4:80;
server_name www.blabla.ru blabla.ru;
# rewrite ^(.*) https://www.blabla.ru$1 permanent;
return 301 https://www.blabla.ru$request_uri;
}
Сложности начались при работе ajax. Асинхронные запросы к серверу выполнялись с префиксом http:// что вызывало губительный для ajax редирект 301. Появилась необходимость передавать переменные окружения, в частности имя протокола, из nginx в apache, сделано это было так:
в nginx:
server {
...
location / {
...
proxy_set_header X-Forwarded-Proto $scheme;
...
}
...
}
Самое главное в apache надо в определении виртуального хоста прописать:
<VirtualHost 127.0.0.1:8080>
ServerName www.blabla.ru
...
SetEnvIf X-Forwarded-Proto https HTTPS=on
...
</VirtualHost>
Теперь все ajax запросы идут на https:// что и требовалось. Для этого трюка модуль apache setenvif_module должен быть установлен и включен в конфиге:
LoadModule setenvif_module libexec/apache22/mod_setenvif.so
Также стоит иметь ввиду что некоторые приложения могут сами определять свой путь по переменным окружения. Так например phpMyAdmin, так нужный разработчикам ресурса, в случае если у него в конфиге не указан полный путь будет формировать его сам с указанием порта. Так получалось у меня нечто вида:
https://www.blabla.ru:80/myadmin
Вот это самое :80 сильно все портило, phpMyAdmin не открывался с руганью что ошибка защиты SSL. Вылечилось, как указано выше, прямым указанием пути в конфиге phpMyAdmin-а:
$cfg['PmaAbsoluteUri'] = 'https://www.blabla.ru/myadmin';
Еще не стоит забывать о передаче реальных IP адресов посетителей в apache для сохранения имеющейся схемы ведения логов. Это расписано неоднократно, копайте в сторону модуля apache rpaf_module.
PS: Все делалось под FreeBSD 8.2, Apache 2.2.22_5, nginx-1.0.14,1. Полные тексты конфигов не выкладывал чтобы не раздувать заметку. По этой же причине на заострялся на передаче реальных IP клиентов и модуле rpaf_module. Если потребуется — выложу.