Ответы пользователя по тегу PHP-FPM
  • Почему медленно работает сайт?

    listen = 127.0.0.1:9001


    1. Используйте unix socket, это увеличит скорость работы связки nginx + php-fpm

    Пример пула php-fpm:

    [site.ru]
    listen = /var/lib/php5-fpm/siteru.sock
    listen.owner = site
    listen.group = site
    listen.mode = 0660
    ...


    Пример настройки nginx:
    location ~ \.php$ {
      ...
      fastcgi_pass unix:/var/lib/php5-fpm/siteru.sock;
      ...
    }


    pm = ondemand


    2. Используйте модель dynamic, при ondemand скорее всего вы упираетесь в pm.max_children

    Пример для dynamic:

    pm = dynamic
    pm.max_children = 10
    pm.start_servers = 2
    pm.min_spare_servers = 1
    pm.max_spare_servers = 5
    pm.max_requests = 500


    3. Включите лог медленных запросов на mysql, включите дебаг в yii2, включите отладочные логи на php-fpm

    Пример включения отладочных логов для php-fpm:
    ; Перенаправлять вывод процесса в лог
    catch_workers_output = yes
    ; Если скрипт выполняется больше указанного времени, писать отладочную информацию в slowlog
    request_slowlog_timeout = 3
    ; Лог-файл для медленных запросов
    slowlog = /var/log/fpm-php/siteru.slow.log
    Ответ написан
  • Какие прорехи в безопасности могут быть в конфигурации nginx?

    1. Постоянный редирект с / на index.php

    location = / {
            rewrite ^ $scheme://$host/index.php permanent;
        }
    
        location / {
            deny all;
            return 404;
        }
        location ~* ^/index\.php$ {
            try_files $uri $uri/ =404;
            fastcgi_index index.php;
            fastcgi_pass php5-fpm-sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include /etc/nginx/fastcgi_params;
        }



    Очень странная логика, особенно использование $host и некорректное использование try_files. Про try_files почитайте тут.

    $host
    в порядке приоритета: имя хоста из строки запроса, или имя хоста из поля “Host” заголовка запроса, или имя сервера, соответствующего запросу


    Если у вас не определен default_server и server_name site.ru; стоит первым в списке, то к вам будут прилетать все запросы с любым полем Host, в том числе пустым, что является очень опасной практикой.
    Лучше использовать переменную $server_name, но все равно, если вам нужно обращения по любым url обрабатывать только через index.php, то правильно это делается так:

    /NONEXISTENTFILE меняете на заранее фейковый файл который не может существовать, например /d7sdhsdhsdf8sfhgsfd8fh438dfjh

    ...
            error_page 404 = @cms;
    
            location / {
                try_files /NONEXISTENTFILE @cms;
            }
    
            location @cms {
                    fastcgi_pass      unix:/var/lib/php5-fpm/xxxxx.sock;
                    fastcgi_index    index.php;
                    fastcgi_param   SCRIPT_FILENAME $document_root/index.php;
                    fastcgi_param   SCRIPT_NAME /index.php;
                    include             /etc/nginx/fastcgi_params;
            }
    ...


    2. Запрещаем любую статику кроме gif|jpg|png|js|css|ttf|woff|ico
    location ~* \.(gif|jpg|png|js|css|ttf|woff|ico)$ {
            try_files $uri =404;
            expires 30d;
        }



    Логичнее и правильнее будет сделать так:

    try_files $uri =404; нам не понадобится, т.к. у нас есть error_page 404 = @cms; который в случае отсутствия картинки перенаправит запрос в @cms

    ...
            error_page 404 = @cms;
    
            location ~* ^.+\.(gif|jpg|png|js|css|ttf|woff|ico)$ {
                    expires 30d;
                    access_log off;
                    log_not_found off;
            }
    
            location / {
                try_files /NONEXISTENTFILE @cms;
            }
    ...


    По поводу json.php и в принципе ограничения доступа, правильнее делать это через map или geo, например так:

    http {
    ....
            geo $my_client_ip $denied {
                    default 1;
                    127.0.0.1 0;
                    XX.XX.XX.XX 0; # <- IP1 с которого можно заходить
                    YY.YY.YY.YY 0;    # <- IP2 с которого можно заходить
            }
    
    server {
            listen       443 ssl;
            server_name  site.ru;
            root         /var/www/html/;
    ...
            set $my_client_ip $remote_addr;
            if ($http_x_forwarded_client_ip ~ "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") {
                    set $my_client_ip $http_x_forwarded_client_ip;
            }
    
            error_page 403 = @deny;
    
            location @deny {
                    root /var/www/deny;
                    rewrite ^(.*)$ /index.html break;
            }
    
            location ~* ^/json\.php$ {
                    if ($denied) {
                            return 403;
                    }
                    try_files /NONEXISTENTFILE @json;
            }
    
            location @json {
                    try_files       $uri = 404;
                    fastcgi_pass    unix:/var/lib/php5-fpm/xxxxx.sock;
                    fastcgi_index   index.php;
                    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    include         /etc/nginx/fastcgi_params;
            }
    
    }
    }


    4. Разрешаем доступ к /admin только с 1-го IP, для /admin/phpmyadmin


    Не делайте так! Организуйте для phpMyAdmin отдельный поддомен с отдельным виртуальным сервером и отдельной обработкой php5-fpm через отдельный сокет.
    Никогда не храните "левые" (вспомогательные) утилиты в общем каталоге web-приложения, это плохая практика. К примеру: Если в phpMyAdmin будет найдена критическая уязвимость, то даже в случае ограничения доступа к нему с определенного IP существует вероятность, что она может быть проэксплуатирована и тогда через неё поломают ваше web-приложение - оно вам нужно?

    По поводу location ~* /admin/ аналогично как для json.php.

    Ну и все рекомендации выше от Кирилл Несмеянов относительно hsts, ssl, ciphers, dh, ocsp stapling поддерживаю.
    Ответ написан
  • Как правильно организовать балансировку нагрузки?

    Если Вы уверены, что Web-приложение справляется с нагрузкой, то возможно на балансировщике стоит увеличить таймауты, добавьте в location /

    proxy_connect_timeout 120s;
    proxy_send_timeout 120s;
    proxy_read_timeout 120s;


    На 3-х вебсерверах если Вы используете php-fpm то лучше работать через unix-сокеты, а не через tcp, через сокеты будет быстрее.

    Возможно стоит посмотреть в сторону параметра least_conn в upstream, то есть запросы сначала будут отправляются бэкенду с наименьшим количеством активных подключений (но с учетом весов). Подробнее тут.
    Если какой-то бэкенд мощнее других, то используйте определение веса через weight
    Так же настройте директивы max_fails и fail_timeout в блоке upstream (в моем примере ниже параметры проставлены для примера).

    Так же включите логи на балансировщике, это сильно упростит отладку:

    http {
        ...
        log_format upstream_log '[$time_local] $remote_addr - $remote_user - $server_name to: $upstream_addr: $request upstream_response_time $upstream_response_time msec $msec request_time $request_time';
    
    upstream servers {
                    least_conn;
                    server ip1;
                    server ip2 max_fails=3 fail_timeout=30s;
                    server ip3 max_fails=5 fail_timeout=30s;
                    keepalive 16;
            }
    
    server {
                    listen 80;
                    access_log /var/log/nginx/servers-access.log upstream_log;
                    error_log /var/log/nginx/servers-error.log debug;
    
                    location / {
                            proxy_pass http://servers;
                            proxy_http_version 1.1;
                            proxy_set_header Connection "";
                            proxy_connect_timeout 120s;
                            proxy_send_timeout 120s;
                            proxy_read_timeout 120s;
            }
    }
    Ответ написан