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

alex_me

Постоялец
Регистрация
25 Янв 2017
Сообщения
172
Реакции
130
Вот пример, подробно, с комментами

Все настройки, касающиеся таймаутов и буферов желательно сбросить до дефолтных по оригинальному конфигу 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;
}
 
Последнее редактирование:

alex_me

Постоялец
Регистрация
25 Янв 2017
Сообщения
172
Реакции
130
Продолжение ...

/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 и размера кеша
Для просмотра ссылки Войди или Зарегистрируйся
 

David Zhou

Постоялец
Регистрация
13 Мар 2018
Сообщения
76
Реакции
103
Which Linux system is better for Magento 2? Centos or Ubuntu?
 
Сверху