Добавление nginx в качестве обратного прокси
Обзор
Идея простая: запускать Apache на порту 8080, а nginx — на порту 80. nginx намного быстрее отдаёт статические файлы и кеш Boost, поэтому он будет напрямую проверять кеш-директорию и отдавать файл, если он есть, минуя Apache. Если кеша нет либо запрос — POST или от залогиненного пользователя, nginx перенаправляет запрос на Apache.
Важно: чтобы в логах Apache отображался реальный IP клиента (а не 127.0.0.1 от nginx), используем модуль mod-rpaf, который берёт последний IP из заголовка X-Forwarded-For.
Шаг 1 — установка nginx и mod-rpaf
Выполните:
apt-get install nginx libapache2-mod-rpafШаг 2 — перевести Apache на порт 8080
Отредактируйте конфигурацию портов Apache:
vi /etc/apache2/ports.conf| # If you just change the port or add more ports here, you will likely also # have to change the VirtualHost statement in # /etc/apache2/sites-enabled/000-default # This is also true if you have upgraded from before 2.2.9-3 (i.e. from # Debian etch). See /usr/share/doc/apache2.2-common/NEWS.Debian.gz and # README.Debian.gz NameVirtualHost *:8080 Listen 8080 |
Измените порт в ваших виртуальных хостах, например:
vi /etc/apache2/sites-available/www.example.com.vhost| |
Затем перезапустите Apache:
/etc/init.d/apache2 restartШаг 3 — отключить Boost-правила переписывания (htaccess)
Поскольку nginx будет отдавать кешированные файлы напрямую, прежние правила переписывания Boost в .htaccess можно закомментировать или удалить:
vi /var/www/www.example.com/web/.htaccess| [...] ## ### BOOST START ### ## ## # Allow for alt paths to be set via htaccess rules; allows for cached variants (future mobile support) ## RewriteRule .* - [E=boostpath:normal] ## ## # Caching for anonymous users ## # Skip boost IF not get request OR uri has wrong dir OR cookie is set OR request came from this server OR https request ## RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [OR] ## RewriteCond %{REQUEST_URI} (^/(admin|cache|misc|modules|sites|system|openid|themes|node/add|comment/reply))|(/(edit|user|user/(login|password|register))$) [OR] ## RewriteCond %{HTTPS} on [OR] ## RewriteCond %{HTTP_COOKIE} DRUPAL_UID ## RewriteRule .* - [S=3] ## ## # GZIP ## RewriteCond %{HTTP:Accept-encoding} !gzip ## RewriteRule .* - [S=1] ## RewriteCond %{DOCUMENT_ROOT}/cache/%{ENV:boostpath}/%{HTTP_HOST}%{REQUEST_URI}_%{QUERY_STRING}\.html -s ## RewriteRule .* cache/%{ENV:boostpath}/%{HTTP_HOST}%{REQUEST_URI}_%{QUERY_STRING}\.html [L,T=text/html,E=no-gzip:1] ## ## # NORMAL ## RewriteCond %{DOCUMENT_ROOT}/cache/%{ENV:boostpath}/%{HTTP_HOST}%{REQUEST_URI}_%{QUERY_STRING}\.html -s ## RewriteRule .* cache/%{ENV:boostpath}/%{HTTP_HOST}%{REQUEST_URI}_%{QUERY_STRING}\.html [L,T=text/html] ## ## ### BOOST END ### [...] |
Шаг 4 — конфигурация nginx (новый default vhost)
Резервная копия и очистка:
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default_orig
cat /dev/null > /etc/nginx/sites-available/default
vi /etc/nginx/sites-available/default| server { listen 80; # fill in the correct domain server_name www.example.com; # fill in the correct document root root /var/www/www.example.com/web; client_body_buffer_size 1m; proxy_buffering on; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; # Avoid image hotlinking from other sites and allow browsers to cache location ~* \.(js|css|jpg|jpeg|gif|png|svg|ico)$ { valid_referers www.example.com blocked none ; if ($invalid_referer) { return 403; break; } if (-f $request_filename) { expires 30d; add_header Cache-Control public; break; } } # Make sure files with the following extensions do not get loaded by nginx because nginx would display the source code, and these files can contain PASSWORDS! location ~* \.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|\.php_ { deny all; } # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac). location ~ /\. { deny all; access_log off; log_not_found off; } # Pass on all PHP requests to the Apache backend location ~* \.php$ { proxy_pass http://localhost:8080; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { try_files $uri @cache; } location @cache { if ($query_string ~ ".+") { return 405; } # pass requests from logged-in users to Apache if ($http_cookie ~ "DRUPAL_UID" ) { return 405; } # pass POST requests to Apache if ($request_method !~ ^(GET|HEAD)$ ) { return 405; } error_page 405 = @drupal; # do not allow browsers to cache HTML add_header Expires "Sun, 19 Nov 1978 05:00:00 GMT"; add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"; # serve requested content from the cache if available, otherwise pass the request to Apache try_files /cache/normal/$host/${uri}_.html /cache/perm/$host/${uri}_.css /cache/perm/$host/${uri}_.js /cache/$host/0$uri.html /cache/$host/0${uri}/index.html @drupal; } # This sends the php to Apache, running on port 8080 location @drupal { proxy_pass http://localhost:8080; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } error_page 404 = index.php; # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } |
В комментариях файла показано, что делает каждая часть. Обратите внимание на блоки, которые запрещают отдачу файлов с опасными расширениями — это критично, иначе nginx может показать исходники конфигураций и файлов с паролями:
# Make sure files with the following extensions do not get loaded by nginx because nginx would display the source code, and these files can contain PASSWORDS!
location ~* \.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|\.php_ {
deny all;
}
# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}Если, например, посетитель попытается загрузить файл с расширением .inc (например, www.example.com/includes/common.inc), nginx вернёт 403 Forbidden:

(Список запрещённых расширений взят из .htaccess Drupal с добавлениями.)
Шаг 5 — общие настройки nginx и gzip
Отредактируйте /etc/nginx/nginx.conf для включения gzip и подстройки worker’ов:
vi /etc/nginx/nginx.conf| user www-data; worker_processes 4; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; # multi_accept on; } http { include /etc/nginx/mime.types; access_log /var/log/nginx/access.log; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 2; tcp_nodelay on; # Enable gzip compression, see https://www.howtoforge.com/how-to-save-traffic-with-nginxs-httpgzipmodule-debian-squeeze gzip on; gzip_http_version 1.1; gzip_vary on; gzip_comp_level 6; gzip_proxied any; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js; gzip_buffers 16 8k; gzip_disable "MSIE [1-6]\\.(?!.*SV1)"; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } [...] |
Запустите nginx:
/etc/init.d/nginx startТестирование и ожидания
- Анонимные пользователи теперь должны получать кешированные страницы напрямую от nginx. Это сокращает задержку отдачи и общую нагрузку на Apache.
- Для нагрузочного теста можно использовать Apache Benchmark (ab) — вы должны увидеть значительное ускорение отдачи статических и кешированных страниц.
Безопасность и подводные камни
Important: никогда не разрешайте nginx отдавать файлы с конфигурациями, бэкапами или исходниками (см. запрещённые расширения выше). Файлы с паролями или секретами в корне сайта должны быть недоступны.
Notes:
- Проверьте права на директорию кеша; nginx работает от имени www-data в примере.
- Убедитесь, что mod-rpaf/remoteip настроен и корректно получает X-Forwarded-For, иначе в логах и приложении будут адреса 127.0.0.1.
Когда это не сработает (кратко)
- Если сайт интенсивно использует динамическую персонализацию для анонимных пользователей, кеш Boost может быть неприменим.
- Если у вас специфические rewrite-правила или модули Apache, которые манипулируют содержимым перед отдачей, nginx может их обходить; проверьте логи и поведение после внедрения.
Альтернативные подходы
- Использовать nginx как SSL-терминатор и проксировать к Apache по HTTP/HTTPS.
- Использовать Varnish в качестве frontend-кеша (подходит для более сложных режимов кеширования).
- Полностью перейти на nginx+php-fpm (убирая Apache), если нет критических зависимостей от модулей Apache.
Роль‑ориентированные чек‑листы
Для администратора:
- Резервная копия конфигураций Apache и nginx.
- Перевод виртуальных хостов на порт 8080 и проверка доступности.
Для тестировщика:
- Проверить отдачу кешированных страниц для анонимных пользователей.
- Проверить доступ и поведение при залогиненных пользователях и при POST-запросах.
Для инженера безопасности:
- Убедиться, что запрещённые расширения действительно недоступны.
- Проверить заголовки и возможные утечки исходников.
Критерии приёмки
- Анонимный GET-запрос к кешируемой странице возвращается nginx без обращения к Apache.
- Залогиненный пользователь и POST-запросы корректно проксируются на Apache.
- В логах Apache видны реальные IP клиентов (не 127.0.0.1).
- Невозможно получить доступ к файлам с запрещёнными расширениями.
Краткий словарь
- reverse proxy — сервер, принимающий внешние запросы и пересылающий их на внутренние службы.
- mod-rpaf / remoteip — модуль Apache для корректного логирования реального IP клиента.
- Boost — модуль Drupal для генерации статических HTML-страниц для анонимных пользователей.
Итог
nginx как фронтенд перед Apache даёт заметное ускорение отдачи статических и кешированных страниц, снижая нагрузку на Apache и ускоряя отклик сайта. Внедрять следует осторожно: проверьте правила запрещённых расширений, логи и поведение динамических страниц.
Ссылки
- Drupal: http://drupal.org/
- Boost: http://drupal.org/project/boost
- nginx: http://nginx.org/
- nginx Wiki: http://wiki.nginx.org/
- Debian: http://www.debian.org/
Об авторе
Falko Timme — владелец Timme Hosting (быстрый nginx-хостинг). Он — ведущий мейнтейнер HowtoForge (с 2005) и один из основных разработчиков ISPConfig (с 2000). Также участвовал в подготовке книги O’Reilly «Linux System Administration».
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента