Настройка веб-сервера Nginx на Debian как front-end к Apache

Опубликовано admin - пн, 03/26/2012 - 20:42

Продолжаем серию статей по обучению системных администраторов для Drupal проектов.
В предыдущей статье Настройка веб-сервера на Debian и установка Drupal мы сделали базовую настройку веб-сервера и установили Drupal.
У этого решения есть некоторые недостатки:

  1. При работе с клиентами, у которых медленные каналы связи, оперативная память сервера будет занята процессом Apache до тех пор пока он полностью не отдаст запрошенный контент.
  2. Каждый раз когда клиент запрашивает статический контент будет запущен процесс Apache для выдачи этого контента, что тоже будет "отъедать" драгоценную оперативную память сервера.

Отличным способом устранения недостатков нашего решения является использования веб-сервера Nginx в качестве front-end к Apache. Все запросы к статике будет обслуживать Nginx, а запросы к динамических страницам Nginx будет проксировать на Apache. В этой статье мы рассмотрим подробную настройку этого решения.

Почему Nginx?

Nginx — это быстрый HTTP сервер и обратный прокси-сервер (reverse proxy), разработанный Игорем Сысоевым. Основным функционалом Nginx является обслуживание статических запросов, обратное проксирование (reverse proxy) и балансировка нагрузки. С этими задачами веб-сервер Nginx справляется значительно лучше, чем Apache, за счет своей архитектуры. Поэтому в нашей задаче мы вынесем обработку статических запросов из Apache в Nginx и настроим Nginx как обратный прокси-сервер (reverse proxy) для остальных запросов.

Схема работы Nginx в качество front-end к Apache

В результате внедрения в работу Nginx схема работы нашего веб-сервера изменится:
Nginx as front-end to apache
Из схемы видно, что все запросы принимает Nginx, после чего динамические запросы Nginx отправляет на Apache, а все статические запросы Nginx обрабатывает самостоятельно.

Конфигурация Apache

Настраиваем в Apache возможность прослушивания порта 8080 В файле /etc/apache2/ports.conf изменяем строки NameVirtualHost и Listen на следующие:

NameVirtualHost 127.0.0.1:8080
Listen 8080

Вносим изменения в конфигурацию Apache в файле /etc/apache2/sites-enabled/drupaladmin-example.com . Настраиваем Apache на порт 8080, т.к. на порту 80 будет слушать запросы Nginx

<VirtualHost 127.0.0.1:8080>
        ServerAdmin info@drupaladmin-example.com
        ServerName www.drupaladmin-example.com
        ServerAlias drupaladmin-example.com
        DocumentRoot /home/webmaster/domains/drupaladmin-example.com/html
        <Directory /home/webmaster/domains/drupaladmin-example.com/html>
          AllowOverride All
          Options -Indexes +FollowSymLinks
          Require all granted        
        </Directory>
        ErrorLog /home/webmaster/domains/drupaladmin-example.com/logs/apache_errors.log
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        # LogLevel warn
        CustomLog /home/webmaster/domains/drupaladmin-example.com/logs/apache_access.log combined

        php_admin_value upload_tmp_dir "/home/webmaster/domains/tmp"
        php_admin_value session.save_path "/home/webmaster/domains/tmp"
        AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
        AddType application/x-httpd-php-source .phps
</VirtualHost>

Перезапускаем Apache

/etc/init.d/apache2 restart

Установка и настройка Nginx

Устанавливаем Nginx из пакетов Debian:

apt-get install nginx

Создаем виртуальный хост Nginx для сайта drupal-admin.ru в файле /etc/nginx/sites-available/drupaladmin-example.com

server {
   listen 80; 
   server_name drupaladmin-example.com www.drupaladmin-example.com;
   root /home/webmaster/domains/drupaladmin-example.com/html;
   index index.php;
   access_log /home/webmaster/domains/drupaladmin-example.com/logs/nginx_access.log;
   error_log /home/webmaster/domains/drupaladmin-example.com/logs/nginx_error.log;
   
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header Host $http_host;
   proxy_hide_header 'X-Drupal-Cache';
   proxy_hide_header 'X-Generator';

   if ($bad_bot) {
      return 444;
   }
   if ($bad_referer) {  
      return 444;  
   }
   if ($not_allowed_method) {
      return 405;
   }
   proxy_http_version 1.1;
   add_header X-XSS-Protection '1; mode=block';
   add_header X-Frame-Options deny;
   add_header X-Content-Options nosniff;
   
   location ~* ^/.well-known/ { 
      allow all;  
   }
   location / {
      location ~* /system/files/ {
         proxy_pass http://127.0.0.1:8080/index.php?q=$uri;
         proxy_set_header Connection '';
         log_not_found off; 
      }
      location ~*  /sites/default/files/private/ { 
         internal;  
      }
      location ~* /imagecache/ {
         expires 30d;
         try_files $uri @drupal; 
      }
      location ~*  /sites/default/files/styles/ {
         expires 30d;
         try_files $uri @drupal;
      }
      location ~* /sites/.+/files/.+\.txt {
         expires 30d;
         tcp_nodelay off;
         open_file_cache max=3000 inactive=120s;
         open_file_cache_valid 45s;
         open_file_cache_min_uses 2;
         open_file_cache_errors off;        
      }
      location ~* /sites/.+/files/advagg_css/ {
         expires max;
         add_header X-XSS-Protection '1; mode=block';
         add_header X-Frame-Options deny;
         add_header X-Content-Options nosniff;
         add_header ETag '';
         add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT';
         add_header Accept-Ranges '';
         location ~* /sites/.*/files/advagg_css/css[_[:alnum:]]+\.css$ { 
            try_files $uri @drupal;          
         } 
      }
      location ~* /sites/.+/files/advagg_js/ {
         expires max;
         add_header X-XSS-Protection '1; mode=block';
         add_header X-Frame-Options deny;
         add_header X-Content-Options nosniff;         
         add_header ETag '';
         add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT';
         add_header Accept-Ranges '';
         location ~* /sites/.*/files/advagg_js/js[_[:alnum:]]+\.js$ { 
            try_files $uri @drupal;  
         } 
      }
      location ~* /admin/reports/hacked/.+/diff/ { 
         try_files $uri @drupal;  
      }
      location ~* ^.+\.xml {  
         try_files $uri @drupal;  
      }
      location ~* ^.+\.(?:css|ico|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff2?|svg|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf|woff|ogg|mp4|wav|aac|skin)$ {
         expires 30d;
         tcp_nodelay off;
         open_file_cache max=3000 inactive=120s;
         open_file_cache_valid 45s;
         open_file_cache_min_uses 2;
         open_file_cache_errors off;
         location ~* ^.+\.svgz$ {
            gzip off;
            add_header X-XSS-Protection '1; mode=block'; 
            add_header X-Frame-Options deny;    
            add_header X-Content-Options nosniff;             
            add_header Content-Encoding gzip;  
         } 
      }
      location ~* ^.+\.(?:pdf|pptx?)$ {
         expires 30d;
         tcp_nodelay off; 
      }
      location ~* ^(?:.+\.(?:htaccess|make|txt|yml|twig|engine|inc|info|install|module|profile|po|pot|sh|.*sql|test|theme|tpl(?:\.php)?|xtmpl)|code-style\.pl|/Entries.*|/Repository|/Root|/Tag|/Template|composer\.(json|lock))$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ {  
         deny all;   
      }
      try_files $uri @drupal;
   }
   location @drupal {
        proxy_pass http://127.0.0.1:8080/index.php?q=$uri;
        proxy_set_header Connection '';
   }
   location = /authorize.php {
      proxy_pass http://127.0.0.1:8080; 
   }
   location = /cron.php {
      proxy_pass http://127.0.0.1:8080;
   }
   location = /index.php {
      proxy_pass http://127.0.0.1:8080;
   }
   location = /install.php {
      proxy_pass http://127.0.0.1:8080;
   }
   location = /update.php { 
      proxy_pass http://127.0.0.1:8080;
   }
   location = /xmlrpc.php {
      proxy_pass http://127.0.0.1:8080;
   }
   location ^~ /.bzr { 
      return 404; 
   }
   location ^~ /.git { 
      return 404; 
   }
   location ^~ /.hg { 
      return 404; 
   }
   location ^~ /.svn {
      return 404;
   }
   location ^~ /.cvs { 
      return 404;
   }
   location ^~ /patches { 
      return 404; 
   }
   location ^~ /config {   
      return 404; 
   }
   location ^~ /backup { 
      return 404;
   }
   location = /robots.txt { 
      try_files $uri @drupal;  
    }
   location = /favicon.ico {
      expires 30d;
      try_files /favicon.ico @empty; 
   }
   location @empty {
      expires 30d;
      empty_gif; 
   }
   location ~* ^.+\.php$ { 
      return 404; 
   }
}

Активируем виртуальный хост Nginx путем установки ссылки

ln -s /etc/nginx/sites-available/drupaladmin-example.com /etc/nginx/sites-enabled/drupaladmin-example.com

Создаем файл конфигурации Nginx  /etc/nginx/conf.d/nginx_additional.conf с дополнительными настройками для определения переменных:

map $http_user_agent $bad_bot {
    default 0;
    ~*^Lynx 0; # Let Lynx go through
    libwww-perl                      1;
    ~(?i)(httrack|htmlparser|libwww) 1;
}

map $http_referer $bad_referer {
    default 0;
    ~(?i)(adult|babes|click|diamond|forsale|girl|jewelry|love|nudit|organic|poker|porn|poweroversoftware|sex|teen|webcam|zippo|casino|replica) 1;
}

map $request_method $not_allowed_method {
    default 1;
    GET 0;
    HEAD 0;
    POST 0;
}

Перезапускаем Nginx

/etc/init.d/nginx restart

Готово. Мы оптимизировали наш веб-сервер, мы снизили нагрузку на Apache с помощью веб-сервера Nginx, который позволил нам быстро обрабатывать запросы по выдаче пользователям статического контента.
Но еще есть над чем работать, в следующих статьях будем разбираться что еще можно необходимо сделать для веб-сервера.

У меня на предпоследнем действии ошибка выходит
root@drupal-admin.ru:/# ls -s /etc/nginx/sites-available/drupal-admin.ru /etc/nginx/sites-enabled/drupal-admin.ru
ls: cannot access /etc/nginx/sites-enabled/drupal-admin.ru: No such file or directory
4 /etc/nginx/sites-available/drupal-admin.ru

С этой командой пишет:
root@drupal-admin.ru:/# ln -s /etc/nginx/sites-available/drupal-admin.ru /etc/nginx sites-enabled/drupal-admin.ru
ln: target `sites-enabled/drupal-admin.ru' is not a directory

После перзапуска nginx , открывая сайт - запускается страница var/www/index.html (

Да, точно) Сайт открылся корректно. Но вот у меня был мультисайтинг который при чистом apache работал. Сам этот сайт мультисайтинга нигде не прописывался, только создал папку вида sitename.ru в папке sites и все т.е. ни в Virtualhost нигде бытонибыло еще его я не прописывал. Он сразу сам заработал. А nginx не работает - "404 Not Found nginx/0.7.67" , хотя основной сайт работает

По ощущениям после установки Nginx , сайт стал значительно тормозить...

В данной конфигурации Nginx поможет снизить нагрузку на Apache в том случае, если на сайте много статики, или много мобильных клиентов. В случаях когда много динамики, то нужно применять кэширование. В следующих статьях я напишу про кэширование Varnish, Nginx, также можно попробовать Boost, но для этого нужно будет специальный конфиг для Nginx - про это тоже напишу.

А что имеется в виду под статикой и динамикой? У меня обычный сайт со статьями и картинками и комментариями, views'ами, panels. т.е. стандартный сайт.

Статика - это файлы (картинки и т.д.)
Динамика - это запросы, которые требуют запуска PHP.
В вашем случае точно поможет APC, Memcache для начала.
Если посетители в основном анонимы, то поможет Boost (его просто настроить), можно Varnish - этот посложнее.
Про кэширование в Varnish есть статья. В принципе можете написать в контактную форму, указав обратный адрес, можно по почте обсудить ускорение Вашего сайта.

Мои знакомые на крупных сайтах (более 100К хитов в сутки) используют связку nginx+fastcgi+eaccelerator , было бы интересно почитать как это настраивается.

Обязательно рассмотрим и этот вариант. Сейчас уже большая очередь статей в работе. В ближайшем будущем опубликую перевод статей о кэшировании от спецов Acquia.

Подскажите, какие то особенности по установке phpmyadmin на nginx+apache2 есть?

В общем-то нет, все нормально работает. Главное, чтобы адрес по которому заходите на phpmyadmin пробрасывался на apache2.

Пример, например если захожу http://example.com/phpmyadmin то все будет работать само или нужно в /etc/nginx/sites-available/drupal-admin.ru/mysite прописывать что то для apache2? Или пробрасывание будет само автоматически?

403 Forbidden: [error] 20519#0: *3 directory index of "/var/www/" is forbidden, client: *.*.*.*, server: localhost, request: "GET / HTTP/1.1", host: "**.*.*"
В чем может быть проблема? установку всю делал по вашему материалу

Нужно проверить корректно ли работает Apache. То есть нужно зайти на сайт минуя Nginx указав порт на котором висит Apache. например: http://drupal-admin.ru:8080
Если все ок, то необходимо проверить конфиг nginx, если все ок, то пишите на info@drupal-admin.ru я посмотрю.

Попробовал по вашему совету открыть сайт по порту 8080. Вначале выдал ошибку, но ее я исправил
выставил DocumentRoot "/var/www" в конфигах апача.
После перезагрузки апача и нджайнкса ошибка прежняя

2012/01/06 06:43:59 [error] 3832#0: *1 directory index of "/var/www/" is forbidden, client: *.*.*.*, server: localhost, request: "GET / HTTP/1.1", host: "*.*.*.*"

По порту 8080 открывается только главная страница. При переходе на sitename/ru или sitename/user
ошибка апача

[Fri Jan 06 06:48:44 2012] [error] [client *.*.*.*] File does not exist: /var/www/ru, referer: http://*.*.*.*:8080/
[Fri Jan 06 06:49:05 2012] [error] [client *.*.*.*] File does not exist: /var/www/user

Заметил что сайт ссылки открывают нормально если открывать следующим образом
http://sitename:8080/index.php?q=ru/user

Написал вам на почту.

Похоже проблемы на apache либо .htaccess
В целом прежде чем настраивать nginx нужно убедиться что нет проблем с apache.

Вы мне можете дать доступ к серверу я посмотрю и тогда проясним в чем проблема.

Я подлкючусь, проверю конфиг apache, после того как сайт заработает через apache разберемся с Nginx.

Если хотите самостоятельно, то посмотрите мою инструкцию по настройке apache она уже опробована на практике несколькими пользователями.

Письмо видел, ответ отправил, готов помочь.

Большое спасибо, Роман! Проблема решилась, благодаря вашим советам.
Итак, я отключил дефолтный конфиг апача (a2dissite default) и настроил его по указаной статье.
Все заработал :)

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

Нужно в settings.php указать, что работаем через reverse proxy. Параметры
'reverse_proxy' TRUE
'reverse_proxy_addresses' 127.0.0.1, внешний IP сервера

Да, еще нужно добавить в конфиг nginx рядом с proxy_pass:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Из этого заголовка Drupal будет брать реальный адрес клиента

а если я таким образом добавляю новый виртуальный хост(допустим xhprof.loc) ,
в корень хоста добавляю файлы xhprof и потом обращаюсь к его каталогу xhprof_html (xhprof.loc/xhprof_html),
внутри которого лежит файл index.php ,а сервер отвечает "not found"
почему?

Установил Nginx фронтедом к Apache как в этом руководстве. Nginx запустился, но не отдает статику Drupal-сайта: css, js, картинки.

В nginx_error отчеты вида: 2018/01/15 15:43:47 [error] 9463#0: *4 open() /home/user/domains/example.com/html/modules/system/system.admin.css" failed (13: Permission denied), client: xx.xx.xx.xx, server: example.com, request: "GET /modules/system/system.admin.css?p2lkjh HTTP/1.1", host: "example.com"
. Permission denied - "доступ запрещен". Как открыть этот доступ?

Разобрался. Дело в том, что на сервере установлен mod_ruid2. Исправил в настройках NGINX строку user nginx; на user my_user; (от имени которого работает Apache). Теперь сайт доступен через прокси-сервер NGINX.

Решено. Надо было в настройках виртуального хоста конфигурации Apache в строку AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml добавить .php7 (так как на CentOS 7 для работы сайта на Dripal 8 я установил PHP 7.1). Теперь стили css не слетают.

Добавить комментарий

Filtered HTML

  • Допустимые HTML-теги: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd>
  • Строки и абзацы переносятся автоматически.
  • Web page addresses and email addresses turn into links automatically.