Главная/Статьи/Оптимизация nginx для PHP и Битрикс

Оптимизация nginx для PHP и Битрикс

Тюним nginx для максимальной производительности: gzip, кэширование, fastcgi_cache, worker_processes, буферы. Production-ready конфигурация.

ДМ
Дмитрий Мещеряков
📅 17 июля 2026 г.📖 7 мин чтения

С оптимизацией nginx есть одна закономерность: конфиги копируют целиком, вместе с чужими значениями и чужими компромиссами. В результате на сервере с двумя гигабайтами памяти оказываются настройки для машины с шестьюдесятью четырьмя, а fastcgi_cache включается на сайте, где половина страниц персональная.

Разберём параметры по смыслу — что каждый из них меняет и от чего зависит правильное значение.

Базовая структура конфига

nginx
# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}
http {
    # Базовые настройки
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    types_hash_max_size 2048;
    server_tokens off;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    # Логи
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'uht="$upstream_header_time" urt="$upstream_response_time"';
    access_log /var/log/nginx/access.log main buffer=16k;
    error_log /var/log/nginx/error.log warn;
    # Gzip
    include /etc/nginx/conf.d/gzip.conf;
    # FastCGI Cache
    include /etc/nginx/conf.d/fastcgi-cache.conf;
    # Сайты
    include /etc/nginx/sites-enabled/*;
}

Gzip сжатие

nginx
# /etc/nginx/conf.d/gzip.conf
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 1000;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/json
    application/javascript
    application/x-javascript
    application/xml
    application/xml+rss
    application/vnd.ms-fontobject
    application/x-font-ttf
    font/opentype
    image/svg+xml;
💡 Совет

gzip_comp_level: Значение от 1 до 9. Уровень 6 — оптимальный баланс между сжатием и нагрузкой на CPU. Уровень 9 даёт всего на 1-2% лучше сжатие, но в 2-3 раза медленнее.

FastCGI Cache для PHP

⚠️ Важно

Это самая эффективная и самая опасная настройка в списке. fastcgi_cache кэширует готовый ответ PHP целиком — включая ответ, сформированный для авторизованного пользователя. Без корректного исключения по кукам сессии один посетитель увидит корзину и личные данные другого.

Обязательный минимум: не кэшировать при наличии куки сессии, не кэшировать POST, не кэшировать зону личного кабинета и оформления заказа. И проверить это до выкладки — тем же способом, что и композит: запросить страницу с куками авторизованного пользователя и без них, сравнить ответы.

Приём с обнулением переменной, которую проверяет fastcgi_cache_bypass, здесь работает надёжнее набора отдельных флагов: легко завести флаг, аккуратно его выставлять и нигде не проверять.

nginx
# /etc/nginx/conf.d/fastcgi-cache.conf
# Зона кэша
fastcgi_cache_path /var/cache/nginx/fastcgi 
    levels=1:2 
    keys_zone=FASTCGI_CACHE:100m 
    inactive=60m 
    max_size=1g
    use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
fastcgi_cache_background_update on;
fastcgi_cache_lock on;
fastcgi_cache_lock_timeout 5s;
# Не кэшировать для авторизованных
map $http_cookie $no_cache {
    default 0;
    "~*PHPSESSID" 1;
    "~*BITRIX_SM_LOGIN" 1;
    "~*BITRIX_SM_UIDH" 1;
}

Конфиг сайта с кэшированием

nginx
# /etc/nginx/sites-enabled/bitrix.conf
upstream php-fpm {
    server unix:/run/php/php8.2-fpm.sock;
    keepalive 32;
}
server {
    listen 80;
    listen 443 ssl http2;
    server_name example.com www.example.com;
    root /var/www/html;
    index index.php index.html;
    # SSL
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
    # HSTS
    add_header Strict-Transport-Security "max-age=31536000" always;
    # Лимиты
    client_max_body_size 100M;
    client_body_buffer_size 128k;
    client_body_timeout 60s;
    client_header_timeout 60s;
    # Статика с долгим кэшем
    location ~* \.(jpg|jpeg|gif|png|svg|webp|ico|css|js|woff|woff2|ttf|eot|pdf)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
        # Открываем CORS для шрифтов
        location ~* \.(woff|woff2|ttf|eot)$ {
            add_header Access-Control-Allow-Origin "*";
        }
    }
    # Запрет служебных файлов
    location ~ /(\.ht|\.git|\.env|\.svn) {
        deny all;
        return 404;
    }
    location ~ ^/(bitrix/\.settings|bitrix/php_interface/dbconn) {
        deny all;
        return 404;
    }
    # Битрикс urlrewrite
    location / {
        try_files $uri $uri/ @bitrix;
    }
    location @bitrix {
        fastcgi_pass php-fpm;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/bitrix/urlrewrite.php;
        # Кэширование для анонимных
        fastcgi_cache FASTCGI_CACHE;
        fastcgi_cache_valid 200 301 302 10m;
        fastcgi_cache_bypass $no_cache;
        fastcgi_no_cache $no_cache;
        add_header X-Cache-Status $upstream_cache_status;
    }
    # PHP
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass php-fpm;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $document_root;
        # Таймауты
        fastcgi_read_timeout 300s;
        fastcgi_send_timeout 300s;
        fastcgi_connect_timeout 60s;
        # Буферы
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        # Keepalive
        fastcgi_keep_conn on;
        # Не кэшируем админку
        location ~ ^/bitrix/(admin|tools)/ {
            fastcgi_pass php-fpm;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_cache off;
        }
    }
}

Оптимизация буферов

nginx
# Для больших ответов PHP
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
# Proxy буферы (если есть reverse proxy)
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
⚠️ Важно

Размер буферов: Если видите в логах an upstream response is buffered to a temporary file, увеличьте fastcgi_buffers. Но не ставьте слишком большие значения — это съест память.

Кэширование композитного сайта Битрикс

nginx
# /etc/nginx/sites-enabled/bitrix-composite.conf
# Проверка наличия композитного кэша
map $uri $composite_cache_file {
    default "/bitrix/html_pages${uri}index@.html";
}
server {
    # ... базовые настройки ...
    location / {
        # Сначала проверяем композитный кэш
        if (-f "$document_root$composite_cache_file") {
            rewrite ^ $composite_cache_file last;
        }
        try_files $uri $uri/ @bitrix;
    }
    # Композитные страницы
    location ~ ^/bitrix/html_pages/ {
        internal;
        # Заголовки
        add_header X-Bitrix-Composite "nginx";
        add_header Cache-Control "no-store, no-cache, must-revalidate";
        # Типы контента
        types {
            text/html html;
        }
    }
}

Rate limiting

nginx
# /etc/nginx/conf.d/rate-limit.conf
# Зоны лимитов
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=conn:10m;
server {
    # ... 
    # Лимит на API
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        limit_conn conn 10;
        # ... fastcgi ...
    }
    # Строгий лимит на логин
    location = /bitrix/admin/ {
        limit_req zone=login burst=3;
        # ... fastcgi ...
    }
}

Security headers

nginx
# /etc/nginx/conf.d/security.conf
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# CSP (настройте под свой сайт)
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;

Проверка конфигурации

bash
# Проверить синтаксис
nginx -t
# Перезагрузить без даунтайма
nginx -s reload
# Посмотреть текущие соединения
nginx -V 2>&1 | grep -o with-http_stub_status_module
# Если модуль есть, добавить:
location = /nginx_status {
    stub_status;
    allow 127.0.0.1;
    deny all;
}

Мониторинг производительности

bash
# Топ медленных запросов из лога
awk '{print $NF}' /var/log/nginx/access.log | sort -rn | head -20
# Статистика кодов ответа
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# Запросы в секунду
tail -f /var/log/nginx/access.log | pv -l -i10 -r > /dev/null

Итоги

ПараметрРекомендация
worker_processesauto (= CPU cores)
worker_connections2048-4096
keepalive_timeout65
gzip_comp_level6
fastcgi_buffers256 16k
fastcgi_cache100m-1g

Приведённые значения — отправная точка, а не универсальные константы. На что смотреть при подборе:

worker_processes — по числу ядер (auto делает это сам), worker_connections — по доступной памяти и характеру нагрузки. Увеличивать второе бесполезно, если упирается PHP-FPM: очередь просто переедет на уровень выше.

gzip_comp_level 6 — разумный компромисс. Девятый уровень даёт единицы процентов выигрыша в размере при заметно большей нагрузке на процессор. Если нужен реальный прирост — включайте brotli, а не поднимайте уровень gzip.

Кэширование статики на 30 дней требует версионирования файлов. Без изменения адреса при изменении содержимого вернувшийся пользователь получит старую вёрстку и не поймёт, почему у него всё сломано.

fastcgi_cache — только с проверенным исключением персональных страниц. Это единственный пункт списка, ошибка в котором приводит к утечке данных, а не к замедлению.

Ограничение частоты запросов настраивайте с burst. Жёсткий лимит без всплеска отсекает нормальных пользователей: обычная страница подтягивает десятки ресурсов почти одновременно.

Заголовки безопасности проверяйте после включения. Content-Security-Policy, добавленный по образцу из статьи, с высокой вероятностью сломает сторонние скрипты — счётчики, чаты, платёжные виджеты. Начинайте с режима отчётов, а не сразу с блокировки.

💡 Совет

И порядок работы, который экономит больше всего времени. Меняйте по одному параметру и измеряйте. Конфиг, собранный из десяти изменений сразу, невозможно откатить осмысленно: когда что-то ломается, вы не знаете, какая именно строка виновата. nginx -t перед каждой перезагрузкой и curl -I после — минимальный цикл проверки.

🚀

Хотите такое же решение?

Настрою окружение под ваш проект, учту специфику инфраструктуры и обучу команду.

Обсудить проект →
Бесплатная консультация · Ответ в течение дня

Комментарии

Система комментариев скоро будет подключена. А пока вы можете написать мне в Telegram или на email.