Настройка Nginx на Debian Squeeze как front-end к Apache

Статья про оптимизацию Drupal. В статье описано как можно настроить веб-сервер Nginx фронтэндом к Apache. В данном случае Nginx принимает все пользовательские запросы и сам отдает всю статику, а динамические запросы отправляет на Apache.

Продолжаем серию статей по обучению системных администраторов для 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_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, который позволил нам быстро обрабатывать запросы по выдаче пользователям статического контента.
Но еще есть над чем работать, в следующих статьях будем разбираться что еще можно необходимо сделать для веб-сервера.