Помощь Настройка сервера под Magento 2

Вот пример, подробно, с комментами

Все настройки, касающиеся таймаутов и буферов желательно сбросить до дефолтных по оригинальному конфигу magento

Стандартные конфиги из установки magento желательно сверить с текущими версиями.
Во-первых, местами они перепилены, во-вторых не обновлялись больше года точно.

Основной конфиг /etc/nginx/nginx.conf

Код:
# Мануал http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
pcre_jit         on;

error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    multi_accept                  on;
    accept_mutex                  off;
    worker_connections 1024;
    use epoll;
}

http {
    # реальный ip выводится в логе через $http_x_forwarded_for
    log_format  main  '$remote_addr - $http_x_forwarded_for [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent"';

    access_log off;

    sendfile            on;
    types_hash_max_size 2048;
  
    # обязательно вместе с Varnish
    port_in_redirect    off;


    # Таймауты ++++++++++++++++++++++++++++++++++++++++++++
    send_timeout                  1m;
    client_header_timeout         1m;
    client_body_timeout           1m;
    http2_recv_timeout            1m;
    http2_idle_timeout            2m;
    resolver_timeout              5s;
    fastcgi_connect_timeout       1s;
    fastcgi_send_timeout          10m;
    fastcgi_read_timeout          10m;
    keepalive_timeout             240s 240s;
      
    # MIME +++++++++++++++++++++++++++++++++++++++++++++++++  
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    charset_types       text/xml text/css text/plain text/vnd.wap.wml text/javascript application/javascript application/rss+xml application/json application/xml;
    types {
      application/x-font-ttf    ttf;
      text/plain        code;
    }

  
    # Настройки соединений +++++++++++++++++++++++++++++++++++++++++++++++++  
    tcp_nopush                    on;
    tcp_nodelay                   on;
    reset_timedout_connection     on;
    ignore_invalid_headers        off;
    server_tokens                 off;     # прячем версию nginx
    server_name_in_redirect       off;
  
    # Лимиты соединений +++++++++++++++++++++++++++++++++++++++++++++++++  
    limit_conn_zone               $binary_remote_addr zone=perip:10m;
    limit_req_zone                $binary_remote_addr zone=dynamic:10m rate=8r/s;

    # FastCGI +++++++++++++++++++++++++++++++++++++++++++++++++  
    fastcgi_buffering             on;
    fastcgi_ignore_client_abort   off;
    fastcgi_next_upstream         error timeout;
    fastcgi_intercept_errors      on; # Перехват ошибок PHP и вывод собственных сообщений об ошибках
    # Gzip ++++++++++++++++++++++++++++++++++++++++++++++++++++  
    gzip                          on;
    gzip_buffers                  64 4k;
    gzip_comp_level               1;
    gzip_disable                  "msie6";
    gzip_min_length               1024;
    gzip_proxied                  any;
    gzip_vary                     on;
    gzip_types                    text/plain text/css text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml application/javascript application/x-javascript application/json application/ld+json text/x-json application/x-web-app-manifest+json application/manifest+json application/vnd.geo+json text/x-component application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon application/x-font-opentype application/x-font-truetype font/eot font/otf image/vnd.microsoft.icon image/bmp text/cache-manifest text/vcard text/vnd.rim.location.xloc text/vtt text/x-cross-domain-policy;
  
    # глобальные переменные ++++++++++++++++++++++++++++++++++
    map $host $admin_ip {
      default 123.45.67.89;  # пример
    }
  
    # апстримы +++++++++++++++++++++++++++++++++++++++++++++++
    # под системный сервер
    upstream upstream_system {
        server    unix:/run/php-fpm/system.sock;
    }
    # под мадженто
    upstream upstream_magento {
        server    unix:/run/php-fpm/magento.sock;
    }
    # под консольные скрипты
    upstream upstream_yii {
        server    unix:/run/php-fpm/yii.sock;
    }

    # системный виртуальный хост - phpmyadmin, роботы, консольные php-скрипты и т.п...
    include conf.d/vh_system.conf;

  
  
    # Виртуальные хосты ++++++++++++++++++++++++++++++++++++++

    # флажок доступа к закрытым локациям по ip
    geo $private_access {
      default        0;
      123.45.67.89    1; # админ 1
      123.45.67.89/21    1; # подсеть 2
    
    }
  
    # открытый 80 - перехват всего нешифрованного трафика
    server {
        listen 80;
      
        # блокировка ботов  
        include conf.d/redirect_bots.conf;
      
        # вход для сертбота
        location /.well-known {
            root /var/www/_certbot;
        }
      
        # на закрытый 81
        location / {
            proxy_pass http://127.0.0.1:81;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
  
    # закрытый 81 - редирект всех доменов с www на без www
    server {
        listen 81;    
        server_name "~^www\.([^\.]+\.[^\.]+)$";
        return 301 http://$1$request_uri;
    }
  
  
    # хост магазина
    # домен: magento.domain
    # папка хоста: /var/www/mag.dom
    # установка magento: /var/www/mag.dom/magento
    # document root: /var/www/mag.dom/magento/pub
    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
    # закрытый 81 - перехват нешифрованного трафика
    server {
    listen       81;
        server_name magento.domain;
      
        set_real_ip_from 127.0.0.1; real_ip_header X-Forwarded-For;
      
        #error_log /var/log/vhosts/magento.domain_81.error.log;
        #access_log /var/log/vhosts/magento.domain_81.access.log;
      
        include conf.d/server_to_https.conf; # редирект на https
        #include conf.d/server_to_content.conf; # передача в контент-сервер
        #include conf.d/server_to_varnish.conf; # передача в ваниш на закрытом 6081
    }
  
    # открытый 443 - терминация SSL
    server {
        include conf.d/server_443__magento.domain.conf;
        server_name  magento.domain www.magento.domain;
      
        error_log /var/log/vhosts/magento.domain_443.error.log;
        access_log /var/log/vhosts/magento.domain_443.access.log;
  
        # режим maintenance - вывод заглушки
        set $runtime_root /var/www/mag.dom/magento/var;
        include conf.d/maintenance.conf;
      
        #include conf.d/server_to_content.conf; # передача в контент-сервер
        include conf.d/server_to_varnish.conf; # передача в ваниш на закрытом 6081
    }
  
    # закрытый 8080 - контент-сервер
    server {
        listen 8080;
        server_name magento.domain;
        client_max_body_size 128M;
  
        set_real_ip_from 127.0.0.1; real_ip_header X-Forwarded-For;
          
        #error_log /var/log/vhosts/magento.domain_8080.error.log;
        #access_log /var/log/vhosts/magento.domain_8080.access.log;
      
        set $MAGE_ROOT /var/www/mag.dom/magento;
      
        #блокировка по ip админки и прочих приватных зон
        include conf.d/location_private.conf;  
      
        #конфиг установки magento
        include /var/www/mag.dom/magento/nginx.conf;
    }
  
}

Вложенные конфиги

conf.d/server_to_https.conf

Код:
location / {
    return 301 https://$host$request_uri;
}



conf.d/server_443__magento.domain.conf

Код:
listen  443 ssl;
  
ssl_certificate /etc/letsencrypt/live/magento.domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/magento.domain/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/magento.domain/chain.pem;

include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

ssl_stapling on;
ssl_stapling_verify on;
#resolver 127.0.0.1 8.8.8.8; # через гугловский днс

#блокировка ботов
include conf.d/redirect_bots.conf;


conf.d/server_to_varnish.conf

Код:
location / {
  proxy_pass http://127.0.0.1:6081;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $remote_addr;
}


conf.d/maintenance.conf;

Код:
set $maintenance off;
set $docs_root /var/www/docs; # в этой папке - страницы ошибок и прочие заглушки

if (-f $runtime_root/.maintenance.flag) {
  set $maintenance on;
}

if ($private_access = 1) {
  set $maintenance off;
}

if ($maintenance = on) {
  return 503;
}

error_page 503 @maintenance;

location @maintenance {
  expires -1;
  add_header Cache-Control "max-age=0, no-cache, no-store, must-revalidate, no-transform" always; # Запрещаем кэширование

  root $docs_root;
  rewrite ^(.*)$ /maintenance.html break; # заглушка
}


Конфиг установки magento
/var/www/mag.dom/magento/nginx.conf;

Код:
root $MAGE_ROOT/pub;

index index.php;
autoindex off;
charset UTF-8;
error_page 404 403 = /errors/404.php;


# запароленный доступ яндекс-боту к yml/xml
location /for-yandex-only/my-yml.yml {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

# редиректы ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
port_in_redirect off;

# редирект с www на без www для трафика с 443
if ($host ~* www\.(.*)) {
    set $host_without_www $1;
    rewrite ^(.*)$ http://$host_without_www$1 permanent;
}
# прочие редиректы перемещенных страниц/разделов, ошибок по вембастеру и т.п.



# сервисные разделы magento ++++++++++++++++++++++++++++++++++++++++++++++++++++

# запрещаем установку на продакшене
location ~* ^/setup($|/) {
    root $MAGE_ROOT;
    location ~ ^/setup/(?!pub/). {
        deny all;
    }
    location ~ ^/setup/pub/ {
        add_header X-Frame-Options "SAMEORIGIN";
    }
}

# запрещаем обновление на продакшене
location ~* ^/update($|/) {
    root $MAGE_ROOT;
    location ~ ^/update/(?!pub/). {
        deny all;
    }
    location ~ ^/update/pub/ {
        add_header X-Frame-Options "SAMEORIGIN";
    }
}


# корень ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
location / {
    try_files $uri $uri/ /index.php$is_args$args;
}

location /pub/ {
    location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) {
        deny all;
    }
    alias $MAGE_ROOT/pub/;
    add_header X-Frame-Options "SAMEORIGIN";
}


# кеширование статики +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
location /static/ {
    # Uncomment the following line in production mode
    expires max;

    # Remove signature of the static files that is used to overcome the browser cache
    location ~ ^/static/version {
        rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
    }

    location ~* \.(js|css|html|txt)$ {
        add_header Cache-Control "public";
        add_header X-Frame-Options "SAMEORIGIN";
        expires +1d;

        if (!-f $request_filename) {
            rewrite ^/static/?(.*)$ /static.php?resource=$1 last;
        }
    }

    location ~* \.(ico|jpg|jpeg|png|gif|svg|swf|eot|ttf|otf|woff|woff2)$ {
        add_header Cache-Control "public";
        add_header X-Frame-Options "SAMEORIGIN";
        expires +1y;

        if (!-f $request_filename) {
            rewrite ^/static/?(.*)$ /static.php?resource=$1 last;
        }
    }
    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
        add_header Cache-Control "no-store";
        add_header X-Frame-Options "SAMEORIGIN";
        expires    off;

        if (!-f $request_filename) {
           rewrite ^/static/?(.*)$ /static.php?resource=$1 last;
        }
    }
    if (!-f $request_filename) {
        rewrite ^/static/?(.*)$ /static.php?resource=$1 last;
    }
    add_header X-Frame-Options "SAMEORIGIN";
}


# кеширование графики ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
location /media/ {
    try_files $uri $uri/ /get.php$is_args$args;

    location ~ ^/media/theme_customization/.*\.xml {
        deny all;
    }

    location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
        add_header Cache-Control "public";
        add_header X-Frame-Options "SAMEORIGIN";
        expires +1y;
        try_files $uri $uri/ /get.php$is_args$args;
    }
    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
        add_header Cache-Control "no-store";
        add_header X-Frame-Options "SAMEORIGIN";
        expires    off;
        try_files $uri $uri/ /get.php$is_args$args;
    }
    add_header X-Frame-Options "SAMEORIGIN";
}


# прочие разделы ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
location /media/customer/ {
    deny all;
}

location /media/downloadable/ {
    deny all;
}

location /media/import/ {
    deny all;
}


# корневые скрипты +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
location ~ (index|get|static|report|404|503|health_check)\.php$ {

    # лимиты соединений с 1 IP / частоты запросов
    limit_conn perip 32;
    limit_req zone=dynamic burst=64 nodelay;

    try_files $uri =404;
    fastcgi_pass   upstream_magento;

    fastcgi_param  PHP_FLAG  "session.auto_start=off \n suhosin.session.cryptua=off";
    fastcgi_param  PHP_VALUE "memory_limit=768M \n max_execution_time=18000";

    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}


# запрет остальных php-скриптов
location ~* (\.php$|\.htaccess$|\.git) {
    deny all;
}
 
Последнее редактирование:
Продолжение ...

/etc/varnish/varnish.params

Код:
# эти порты закрыты
VARNISH_LISTEN_PORT=6081

VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082

VARNISH_SECRET_FILE=/etc/varnish/secret

VARNISH_STORAGE="malloc,2g" # убедиться, что RAM + swap покрывает этот объем с запасом

VARNISH_USER=varnish
VARNISH_GROUP=varnish

DAEMON_OPTS=\
  -p thread_pool_min=200 \
  -p thread_pool_max=8000 \
  -p thread_pool_timeout=300 \
  -p http_resp_hdr_len="64k" \
  -p http_resp_size="96k"

/etc/varnish/default.vcl

Код:
vcl 4.0;
import std;

# один общий бекенд
# если помимо magento хостятся другие движки - вывести их на отдельный бекенд
backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .connect_timeout = 3s; # Wait for backend connection (Apache, Nginx, etc...)
    .first_byte_timeout = 600s; # Wait for the first byte to come from your backend
    .between_bytes_timeout = 4s; # Wait between each bytes sent

    # health_check из оригинального конфига - выпилен
}

acl purge {
    "localhost";
}

sub vcl_recv {

    # реальный ip 
    unset req.http.X-Forwarded-For;
    set req.http.X-Forwarded-For = req.http.X-Real-IP;

   
    if (req.method == "PURGE") {
        if (client.ip !~ purge) {
            return (synth(405, "Method not allowed"));
        }
        # To use the X-Pool header for purging varnish during automated deployments, make sure the X-Pool header
        # has been added to the response in your backend server config. This is used, for example, by the
        # capistrano-magento2 gem for purging old content from varnish during it's deploy routine.
        if (!req.http.X-Magento-Tags-Pattern && !req.http.X-Pool) {
            return (synth(400, "X-Magento-Tags-Pattern or X-Pool header required"));
        }
        if (req.http.X-Magento-Tags-Pattern) {
        ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern);
        }
        if (req.http.X-Pool) {
          ban("obj.http.X-Pool ~ " + req.http.X-Pool);
        }
        return (synth(200, "Purged"));
    }

    if (req.method != "GET" &&
        req.method != "HEAD" &&
        req.method != "PUT" &&
        req.method != "POST" &&
        req.method != "TRACE" &&
        req.method != "OPTIONS" &&
        req.method != "DELETE") {
          /* Non-RFC2616 or CONNECT which is weird. */
          return (pipe);
    }

    # We only deal with GET and HEAD by default
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

    # Bypass shopping cart, checkout and search requests
    if (req.url ~ "/checkout" || req.url ~ "/catalogsearch") {
        return (pass);
    }

    # Bypass health check requests
    if (req.url ~ "/health_check.php") {
        return (pass);
    }

    # Set initial grace period usage status
    set req.http.grace = "none";

    # normalize url in case of leading HTTP scheme and domain
    set req.url = regsub(req.url, "^http[s]?://", "");

    # collect all cookies
    std.collect(req.http.Cookie);

    # Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$") {
            # No point in compressing these
            unset req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            # unkown algorithm
            unset req.http.Accept-Encoding;
        }
    }

    # Remove Google gclid parameters to minimize the cache objects
    set req.url = regsuball(req.url,"\?gclid=[^&]+$",""); # strips when QS = "?gclid=AAA"
    set req.url = regsuball(req.url,"\?gclid=[^&]+&","?"); # strips when QS = "?gclid=AAA&foo=bar"
    set req.url = regsuball(req.url,"&gclid=[^&]+",""); # strips when QS = "?foo=bar&gclid=AAA" or QS = "?foo=bar&gclid=AAA&bar=baz"

    # Статика отдается напрямую
    # аналогичным образом прописать любые папки/файлы для роботов (сайтмеп, yml для яндекс-бота и т.п.)
    if (req.url ~ "^/(pub/)?(media|static|)/") {
        return (pass);
    }

    return (hash);
}

sub vcl_hash {
    if (req.http.cookie ~ "X-Magento-Vary=") {
        hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
    }

    # For multi site configurations to not cache each other's content
    if (req.http.host) {
        hash_data(req.http.host);
    } else {
        hash_data(server.ip);
    }

    # To make sure http users don't see ssl warning
    if (req.http.X-Forwarded-Proto) {
        hash_data(req.http.X-Forwarded-Proto);
    }
   
}

sub vcl_pipe {
    # реальный ip при передаче через pipe
    set bereq.http.connection = "close";
    if (req.http.X-Forwarded-For) {
    set bereq.http.X-Forwarded-For = req.http.X-Forwarded-For;
    } else {
    set bereq.http.X-Forwarded-For = regsub(client.ip, ":.*", "");
    }
   
    return (pipe);
}

sub vcl_backend_response { 
    set beresp.grace = 3d;

    if (beresp.http.content-type ~ "text") {
        #set beresp.do_esi = true;
    }

    if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") {
        set beresp.do_gzip = true;
    }

    # cache only successfully responses and 404s
    if (beresp.status != 200 && beresp.status != 404) {
        set beresp.ttl = 0s;
        set beresp.uncacheable = true;
        return (deliver);
    } elsif (beresp.http.Cache-Control ~ "private") {
        set beresp.uncacheable = true;
        set beresp.ttl = 86400s;
        return (deliver);
    }

    if (beresp.http.X-Magento-Debug) {
        set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control;
    }

    # validate if we need to cache it and prevent from setting cookie
    if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {
        unset beresp.http.set-cookie;
    }

   # If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass
   if (beresp.ttl <= 0s ||
        beresp.http.Surrogate-control ~ "no-store" ||
        (!beresp.http.Surrogate-Control && beresp.http.Vary == "*")) {
        # Mark as Hit-For-Pass for the next 2 minutes
        set beresp.ttl = 120s;
        set beresp.uncacheable = true;
    }
    return (deliver);
}

sub vcl_deliver {   
    if (resp.http.X-Magento-Debug) {
        if (resp.http.x-varnish ~ " ") {
            set resp.http.X-Magento-Cache-Debug = "HIT";
            set resp.http.Grace = req.http.grace;
        } else {
            set resp.http.X-Magento-Cache-Debug = "MISS";
        }
    } else {
        unset resp.http.Age;
    }

    unset resp.http.X-Magento-Debug;
    unset resp.http.X-Magento-Tags;
    unset resp.http.X-Powered-By;
    unset resp.http.Server;
    unset resp.http.X-Varnish;
    unset resp.http.Via;
    unset resp.http.Link;
}
   
sub vcl_hit {
    if (obj.ttl >= 0s) {
        # Hit within TTL period
        return (deliver);
    }
    if (std.healthy(req.backend_hint)) {
        if (obj.ttl + 300s > 0s) {
            # Hit after TTL expiration, but within grace period
            set req.http.grace = "normal (healthy server)";
            return (deliver);
        } else {
            # Hit after TTL and grace expiration
            return (fetch);
        }
    } else {
        # server is not healthy, retrieve from cache
        set req.http.grace = "unlimited (unhealthy server)";
        return (deliver);
    }
}

+++++++

Пользуйтесь varnishstat и varnishlog, чтобы отслеживать битые заголовки, ошибки
и чтобы настроить ttl и размера кеша
Для просмотра ссылки Войди или Зарегистрируйся
 
Which Linux system is better for Magento 2? Centos or Ubuntu?
 
Назад
Сверху