<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Исчерпывающее руководство по конфигурации Nginx]]></title><description><![CDATA[<p dir="auto">Nginx — это высокопроизводительный веб-сервер, обратный прокси-сервер и балансировщик нагрузки. Архитектура Nginx основана на модели master-процесса и worker-процессов. Master-процесс читает и обрабатывает конфигурацию, а также управляет worker-процессами, которые выполняют фактическую обработку запросов.</p>
<h2>Структура конфигурационного файла</h2>
<p dir="auto">Конфигурация Nginx имеет иерархическую блочную структуру, где директивы организованы в контексты. Основной конфигурационный файл обычно находится по адресу <code>/etc/nginx/nginx.conf</code>.</p>
<h3>Основные контексты конфигурации</h3>
<p dir="auto"><strong>Main (главный) контекст</strong> — глобальная область, содержащая директивы, которые влияют на весь экземпляр Nginx.</p>
<p dir="auto"><strong>Events контекст</strong> — управляет настройками обработки соединений.</p>
<p dir="auto"><strong>HTTP контекст</strong> — содержит всю HTTP-связанную конфигурацию.</p>
<p dir="auto"><strong>Server контекст</strong> — определяет виртуальные хосты и специфичные для сервера настройки.</p>
<p dir="auto"><strong>Location контекст</strong> — специфичная для URL конфигурация внутри server-блока.</p>
<p dir="auto"><strong>Upstream контекст</strong> — определяет группы серверов для балансировки нагрузки.</p>
<h3>Пример базовой структуры конфигурации</h3>
<pre><code class="language-nginx"># Main контекст - глобальные директивы
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

# Events контекст
events {
    worker_connections 1024;
    use epoll;
}

# HTTP контекст
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # Server контекст
    server {
        listen 80;
        server_name example.com;
        root /var/www/html;
        
        # Location контекст
        location / {
            try_files $uri $uri/ =404;
        }
    }
}
</code></pre>
<h2>Процессы и соединения</h2>
<h3>Worker Processes</h3>
<p dir="auto">Директива <code>worker_processes</code> определяет количество рабочих процессов для обработки запросов. Каждый worker-процесс является однопоточным.</p>
<pre><code class="language-nginx">worker_processes auto;  # автоматически определяет количество CPU ядер
</code></pre>
<p dir="auto"><strong>Как это работает</strong>: Если Nginx выполняет CPU-интенсивные операции (например, SSL или gzip), и у вас 2 или более CPU/ядер, то вы можете установить <code>worker_processes</code> равным количеству CPU или ядер. Значение <code>auto</code> автоматически определяет оптимальное количество на основе доступных ядер.</p>
<h3>Worker Connections</h3>
<p dir="auto">Директива <code>worker_connections</code> определяет максимальное количество одновременных соединений, которые может открыть один worker-процесс.</p>
<pre><code class="language-nginx">events {
    worker_connections 1024;
}
</code></pre>
<p dir="auto"><strong>Расчет максимального количества клиентов</strong>:</p>
<p dir="auto"><code>max_clients = worker_processes × worker_connections</code></p>
<p dir="auto">Например, если у вас 4 worker-процесса и 1024 соединения на процесс, вы можете обслуживать до 4096 клиентов одновременно.</p>
<p dir="auto"><strong>Важное замечание</strong>: При использовании Nginx в качестве reverse proxy, это число нужно делить на 2, поскольку каждое клиентское соединение требует соединения с backend-сервером.</p>
<h3>Оптимизация worker_connections</h3>
<p dir="auto">По умолчанию значение составляет 512 или 768. Вы можете увеличить это значение до лимита системы, определяемого командой <code>ulimit -n</code>.</p>
<pre><code class="language-nginx">events {
    worker_connections 1024;
    use epoll;  # для Linux
    multi_accept on;  # принимать несколько соединений за один цикл событий
}
</code></pre>
<h2>Директива Server</h2>
<p dir="auto">Server-блок определяет виртуальный хост — конфигурацию для конкретного домена или IP-адреса.</p>
<h3>Listen директива</h3>
<p dir="auto">Определяет, на каком порту и адресе сервер будет слушать входящие соединения.</p>
<pre><code class="language-nginx">server {
    listen 80;                    # IPv4 на порту 80
    listen [::]:80;               # IPv6 на порту 80
    listen 443 ssl http2;         # HTTPS с HTTP/2
    listen 192.168.1.10:8080;     # конкретный IP и порт
}
</code></pre>
<h3>Server_name директива</h3>
<p dir="auto">Определяет доменное имя (или имена), которые будут обрабатываться этим server-блоком.</p>
<pre><code class="language-nginx">server {
    server_name example.com www.example.com;  # несколько доменов
}

server {
    server_name *.example.com;  # wildcard
}

server {
    server_name ~^(?&lt;subdomain&gt;.+)\.example\.com$;  # regex
}
</code></pre>
<p dir="auto"><strong>Как Nginx выбирает server-блок</strong>:</p>
<ol>
<li>Точное совпадение имени</li>
<li>Самое длинное совпадение, начинающееся с *</li>
<li>Самое длинное совпадение, заканчивающееся на *</li>
<li>Первое совпадение по регулярному выражению</li>
<li>Default server (указанный с <code>default_server</code> в <code>listen</code>)</li>
</ol>
<h2>Директива Location</h2>
<p dir="auto">Location-блоки определяют, как обрабатывать запросы в зависимости от URI.</p>
<h3>Синтаксис и модификаторы</h3>
<pre><code class="language-nginx">location [modifier] path {
    # конфигурация
}
</code></pre>
<p dir="auto"><strong>Модификаторы</strong>:</p>
<ul>
<li><code>=</code> — точное совпадение (наивысший приоритет)</li>
<li><code>^~</code> — преимущественное префиксное совпадение (останавливает поиск regex)</li>
<li><code>~</code> — regex с учетом регистра</li>
<li><code>~*</code> — regex без учета регистра</li>
<li>(без модификатора) — префиксное совпадение</li>
</ul>
<h3>Порядок приоритета location</h3>
<ol>
<li>Точные совпадения <code>=</code></li>
<li>Преимущественные префиксы <code>^~</code></li>
<li>Регулярные выражения <code>~</code> и <code>~*</code> (в порядке появления в файле)</li>
<li>Префиксные совпадения (самый длинный префикс имеет приоритет)</li>
</ol>
<h3>Примеры location</h3>
<pre><code class="language-nginx"># Точное совпадение - наивысший приоритет
location = /exact {
    return 200 "Exact match";
}

# Преимущественный префикс - останавливает regex
location ^~ /images/ {
    root /var/www;
}

# Regex с учетом регистра
location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
}

# Regex без учета регистра
location ~* \.(jpg|png|gif)$ {
    expires 1y;
}

# Префиксное совпадение
location /api/ {
    proxy_pass http://backend;
}

# Дефолтный обработчик
location / {
    root /var/www/html;
    index index.html;
}
</code></pre>
<h2>Root и Alias директивы</h2>
<h3>Root директива</h3>
<p dir="auto">Директива <code>root</code> устанавливает корневую директорию для запросов. Полный путь формируется путем добавления URI запроса к значению root, <strong>включая часть location</strong>.</p>
<pre><code class="language-nginx">location /images/ {
    root /var/www;
}
</code></pre>
<p dir="auto">Для запроса <code>/images/logo.png</code> файл будет искаться по пути: <code>/var/www/images/logo.png</code>.</p>
<h3>Alias директива</h3>
<p dir="auto">Директива <code>alias</code> заменяет часть URI, указанную в location, на путь из alias. <strong>Часть location НЕ добавляется</strong> к пути.</p>
<pre><code class="language-nginx">location /images/ {
    alias /var/www/static/;
}
</code></pre>
<p dir="auto">Для запроса <code>/images/logo.png</code> файл будет искаться по пути: <code>/var/www/static/logo.png</code>.</p>
<p dir="auto"><strong>Важное различие</strong>: С <code>root</code> путь location добавляется к корневому пути, с <code>alias</code> — заменяется.</p>
<h2>Try_files директива</h2>
<p dir="auto">Директива <code>try_files</code> проверяет существование файлов в указанном порядке и обслуживает первый найденный.</p>
<h3>Синтаксис</h3>
<pre><code class="language-nginx">try_files file1 file2 ... uri;
try_files file1 file2 ... =code;
</code></pre>
<h3>Примеры использования</h3>
<pre><code class="language-nginx"># Базовое использование для SPA приложений
location / {
    try_files $uri $uri/ /index.html;
}
</code></pre>
<p dir="auto"><strong>Как это работает</strong>:</p>
<ol>
<li>Сначала проверяет, существует ли файл <code>$uri</code></li>
<li>Если нет, проверяет, является ли <code>$uri/</code> директорией</li>
<li>Если нет, отдает <code>/index.html</code></li>
</ol>
<pre><code class="language-nginx"># С named location для проксирования
location / {
    try_files $uri $uri/ @backend;
}

location @backend {
    proxy_pass http://backend-server;
}
</code></pre>
<pre><code class="language-nginx"># С кодом ошибки
location / {
    try_files $uri $uri/ =404;
}
</code></pre>
<p dir="auto"><strong>Важно</strong>: При использовании <code>try_files</code> внутри location, если последний параметр — URI, Nginx выполнит внутренний редирект.</p>
<h2>Reverse Proxy конфигурация</h2>
<h3>Proxy_pass директива</h3>
<p dir="auto">Директива <code>proxy_pass</code> перенаправляет запросы на proxied-сервер.</p>
<pre><code class="language-nginx">location /api/ {
    proxy_pass http://127.0.0.1:8000;
}
</code></pre>
<h3>Важные proxy заголовки</h3>
<pre><code class="language-nginx">location / {
    proxy_pass http://backend;
    
    # Передает оригинальный Host header
    proxy_set_header Host $host;
    
    # IP адрес клиента
    proxy_set_header X-Real-IP $remote_addr;
    
    # Цепочка proxy серверов
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
    # Протокол (http или https)
    proxy_set_header X-Forwarded-Proto $scheme;
}
</code></pre>
<p dir="auto"><strong>Почему это важно</strong>: По умолчанию Nginx перезаписывает Host header на адрес proxied-сервера. Приложению на backend нужен оригинальный Host header, чтобы правильно обрабатывать запросы.</p>
<h3>Proxy_redirect</h3>
<pre><code class="language-nginx"># Перезаписывает Location и Refresh заголовки в ответах от proxied-сервера
proxy_redirect http://localhost:8000/ http://example.com/;

# Или для всех URL
proxy_redirect http://localhost:8000/ /;
</code></pre>
<h3>Отключение буферизации</h3>
<pre><code class="language-nginx">location /stream/ {
    proxy_pass http://backend;
    proxy_buffering off;  # для приложений с низкой задержкой
}
</code></pre>
<h2>Upstream и балансировка нагрузки</h2>
<p dir="auto">Директива <code>upstream</code> определяет группу серверов для балансировки нагрузки.</p>
<h3>Базовая конфигурация</h3>
<pre><code class="language-nginx">upstream backend {
    server backend1.example.com:8080;
    server backend2.example.com:8080;
    server backend3.example.com:8080;
}

server {
    location / {
        proxy_pass http://backend;
    }
}
</code></pre>
<h3>Методы балансировки</h3>
<p dir="auto"><strong>Round Robin</strong> (по умолчанию) — запросы распределяются последовательно.</p>
<pre><code class="language-nginx">upstream backend {
    server backend1.example.com;
    server backend2.example.com;
}
</code></pre>
<p dir="auto"><strong>Least Connections</strong> — запросы направляются на сервер с наименьшим количеством активных соединений.</p>
<pre><code class="language-nginx">upstream backend {
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
}
</code></pre>
<p dir="auto"><strong>IP Hash</strong> — клиент всегда направляется на один и тот же сервер на основе IP.</p>
<pre><code class="language-nginx">upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
}
</code></pre>
<p dir="auto"><strong>Weight</strong> — распределение нагрузки с учетом весов.</p>
<pre><code class="language-nginx">upstream backend {
    server backend1.example.com weight=3;
    server backend2.example.com weight=2;
    server backend3.example.com weight=1;
}
</code></pre>
<h3>Параметры серверов в upstream</h3>
<pre><code class="language-nginx">upstream backend {
    server backend1.example.com:8080 weight=5;
    server backend2.example.com:8080 max_fails=3 fail_timeout=30s;
    server backend3.example.com:8080 max_conns=100;
    server backend4.example.com:8080 backup;  # используется только если основные недоступны
    server backend5.example.com:8080 down;    # временно исключен
}
</code></pre>
<h2>SSL/TLS конфигурация</h2>
<h3>Базовая HTTPS конфигурация</h3>
<pre><code class="language-nginx">server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    
    # Пути к сертификатам
    ssl_certificate /etc/nginx/certs/ssl_certificate.crt;
    ssl_certificate_key /etc/nginx/certs/ssl_certificate.key;
    
    # Протоколы SSL
    ssl_protocols TLSv1.2 TLSv1.3;
    
    # Шифры
    ssl_ciphers HIGH:!aNULL:!MD5;
    
    location / {
        root /var/www/html;
    }
}
</code></pre>
<h3>Редирект HTTP на HTTPS</h3>
<pre><code class="language-nginx"># Редирект всех HTTP запросов на HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# HTTPS сервер
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    
    ssl_certificate /path/to/cert.crt;
    ssl_certificate_key /path/to/cert.key;
    
    location / {
        root /var/www/html;
    }
}
</code></pre>
<h3>Каноническая форма URL</h3>
<pre><code class="language-nginx"># Редирект с example.com на www.example.com
server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /path/to/cert.crt;
    ssl_certificate_key /path/to/cert.key;
    
    return 301 https://www.example.com$request_uri;
}

# Основной сервер
server {
    listen 443 ssl http2;
    server_name www.example.com;
    
    ssl_certificate /path/to/cert.crt;
    ssl_certificate_key /path/to/cert.key;
    
    location / {
        root /var/www/html;
    }
}
</code></pre>
<h2>Gzip сжатие</h2>
<p dir="auto">Gzip сжатие уменьшает размер передаваемых файлов, ускоряя загрузку сайта.</p>
<h3>Основная конфигурация</h3>
<pre><code class="language-nginx">http {
    # Включить gzip
    gzip on;
    
    # Уровень сжатия (1-9)
    # 5 - оптимальный баланс между размером и CPU
    gzip_comp_level 5;
    
    # Минимальная длина ответа для сжатия
    gzip_min_length 256;
    
    # Включить сжатие для proxied запросов
    gzip_proxied any;
    
    # MIME типы для сжатия
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml
        application/xml+rss
        application/xhtml+xml
        image/svg+xml;
    
    # Добавить Vary: Accept-Encoding header
    gzip_vary on;
}
</code></pre>
<p dir="auto"><strong>Как это работает</strong>: Когда браузер делает запрос, сервер сжимает файл с помощью gzip перед отправкой. Браузер распаковывает его перед отображением пользователю. Уровень сжатия 5 обеспечивает около 75% уменьшения размера для большинства текстовых файлов.</p>
<p dir="auto"><strong>Примечание</strong>: <code>text/html</code> всегда включен в gzip по умолчанию, его не нужно указывать явно.</p>
<h2>Security Headers</h2>
<p dir="auto">Security headers защищают от различных атак (XSS, clickjacking, MIME-sniffing).</p>
<h3>Основные заголовки безопасности</h3>
<pre><code class="language-nginx"># В http или server контексте
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" 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 Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none';" always;
</code></pre>
<p dir="auto"><strong>Описание заголовков</strong>:</p>
<ul>
<li><strong>Strict-Transport-Security (HSTS)</strong> — принудительное использование HTTPS</li>
<li><strong>X-Frame-Options</strong> — защита от clickjacking, запрещает встраивание в iframe</li>
<li><strong>X-Content-Type-Options</strong> — запрещает MIME-sniffing браузерами</li>
<li><strong>X-XSS-Protection</strong> — включает встроенный XSS фильтр браузера</li>
<li><strong>Content-Security-Policy</strong> — контролирует, какие ресурсы можно загружать</li>
<li><strong>Referrer-Policy</strong> — контролирует передачу Referer header</li>
</ul>
<p dir="auto"><strong>Параметр <code>always</code></strong>: Гарантирует, что Nginx добавит заголовки даже для ответов с кодами 4xx и 5xx.</p>
<h3>Создание переиспользуемого snippet</h3>
<pre><code class="language-nginx"># /etc/nginx/snippets/security-headers.conf
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" 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;
</code></pre>
<p dir="auto">Использование в server-блоке:</p>
<pre><code class="language-nginx">server {
    listen 443 ssl http2;
    server_name example.com;
    
    include snippets/security-headers.conf;
    
    location / {
        root /var/www/html;
    }
}
</code></pre>
<h2>Таймауты</h2>
<p dir="auto">Таймауты контролируют, как долго Nginx ждет различных событий.</p>
<h3>Основные директивы таймаутов</h3>
<pre><code class="language-nginx">http {
    # Таймаут для чтения заголовков запроса от клиента
    client_header_timeout 60s;
    
    # Таймаут для чтения тела запроса от клиента
    client_body_timeout 60s;
    
    # Время, в течение которого keepalive соединение остается открытым
    keepalive_timeout 75s;
    
    # Таймаут для отправки ответа клиенту
    send_timeout 60s;
}
</code></pre>
<h3>Client_body_timeout</h3>
<p dir="auto">Определяет, сколько времени Nginx будет ждать отправки тела запроса клиентом. Важно для загрузки больших файлов.</p>
<pre><code class="language-nginx"># Для сайтов с загрузкой больших файлов
client_body_timeout 300s;
</code></pre>
<h3>Keepalive_timeout</h3>
<p dir="auto">Определяет, как долго keepalive соединение остается открытым после отправки ответа.</p>
<pre><code class="language-nginx">keepalive_timeout 65s;
</code></pre>
<p dir="auto"><strong>Как это работает</strong>: После отправки ответа клиенту соединение не закрывается сразу, а остается открытым указанное время. Это позволяет повторно использовать соединение для последующих запросов, избегая накладных расходов на установку нового TCP соединения.</p>
<p dir="auto"><strong>Оптимизация</strong>: Высокое значение позволяет повторно использовать соединения, но потребляет больше ресурсов сервера. Для сайтов с высокой нагрузкой можно уменьшить до 30s.</p>
<h3>Пример для API с большими загрузками</h3>
<pre><code class="language-nginx">location /api/upload {
    client_header_timeout 120s;
    client_body_timeout 300s;
    client_max_body_size 100m;
    
    proxy_pass http://backend;
    proxy_read_timeout 300s;
    proxy_connect_timeout 60s;
}
</code></pre>
<h2>Размеры буферов</h2>
<h3>Client_body_buffer_size</h3>
<p dir="auto">Определяет размер буфера для чтения тела запроса клиента.</p>
<pre><code class="language-nginx"># По умолчанию 8k или 16k
client_body_buffer_size 16k;
</code></pre>
<p dir="auto"><strong>Как это работает</strong>: Если размер тела запроса превышает размер буфера, Nginx записывает его во временный файл на диске. Это замедляет обработку из-за дополнительных операций I/O.</p>
<p dir="auto"><strong>Оптимизация</strong>: Для API с большими загрузками можно увеличить размер буфера, но не устанавливайте его слишком большим, чтобы избежать уязвимостей к DoS атакам.</p>
<h3>Client_max_body_size</h3>
<p dir="auto">Ограничивает максимальный размер тела запроса клиента.</p>
<pre><code class="language-nginx">http {
    client_max_body_size 10M;
}

# Или для конкретного location
location /upload {
    client_max_body_size 100M;
}
</code></pre>
<p dir="auto"><strong>По умолчанию</strong>: 1M. Если клиент отправляет файл больше этого размера, Nginx возвращает ошибку 413 (Request Entity Too Large).</p>
<h2>PHP-FPM конфигурация</h2>
<h3>Базовая настройка для PHP</h3>
<pre><code class="language-nginx">server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    index index.php index.html;
    
    location / {
        try_files $uri $uri/ =404;
    }
    
    # Обработка PHP файлов
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        
        # Для UNIX сокета
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        
        # Или для TCP/IP
        # fastcgi_pass 127.0.0.1:9000;
        
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    
    # Запрет доступа к .htaccess файлам
    location ~ /\.ht {
        deny all;
    }
}
</code></pre>
<p dir="auto"><strong>Как это работает</strong>: Когда запрашивается файл <code>.php</code>, Nginx передает запрос PHP-FPM через FastCGI протокол. PHP-FPM выполняет скрипт и возвращает результат обратно Nginx.</p>
<h3>Разные версии PHP для разных сайтов</h3>
<pre><code class="language-nginx">server {
    server_name site1.com;
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        include fastcgi_params;
    }
}

server {
    server_name site2.com;
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        include fastcgi_params;
    }
}
</code></pre>
<h2>Rewrite и редиректы</h2>
<h3>Return директива</h3>
<p dir="auto">Директива <code>return</code> — самый эффективный способ создания редиректов.</p>
<pre><code class="language-nginx"># Постоянный редирект (301)
location /old-page {
    return 301 /new-page;
}

# Временный редирект (302)
location /temp {
    return 302 /temporary-location;
}

# Редирект на другой домен
server {
    server_name old-domain.com;
    return 301 https://new-domain.com$request_uri;
}
</code></pre>
<p dir="auto"><strong>Почему <code>return</code> лучше <code>rewrite</code></strong>: <code>return</code> немедленно останавливает обработку и отправляет редирект, без дополнительных проверок. Это быстрее и проще в понимании.</p>
<h3>Rewrite директива</h3>
<p dir="auto">Директива <code>rewrite</code> использует регулярные выражения для изменения URI.</p>
<p dir="auto"><strong>Синтаксис</strong>:</p>
<pre><code class="language-nginx">rewrite regex replacement [flag];
</code></pre>
<p dir="auto"><strong>Флаги</strong>:</p>
<ul>
<li><code>last</code> — останавливает обработку rewrite и начинает новый поиск location</li>
<li><code>break</code> — останавливает обработку rewrite в текущем контексте</li>
<li><code>redirect</code> — временный редирект (302)</li>
<li><code>permanent</code> — постоянный редирект (301)</li>
</ul>
<h3>Примеры rewrite</h3>
<pre><code class="language-nginx"># Простой rewrite с захватом групп
location /data/ {
    rewrite ^(/data/.*)/geek/(\w+)\.?.*$ $1/linux/$2.html last;
}
# /data/distro/geek/test.php -&gt; /data/distro/linux/test.html
</code></pre>
<p dir="auto"><strong>Как это работает</strong>: <code>$1</code> и <code>$2</code> захватывают части URI, заключенные в скобки <code>()</code> в регулярном выражении.</p>
<pre><code class="language-nginx"># Rewrite для контроллера
location /linux/ {
    rewrite ^/linux/(.*)$ /linux.php?distro=$1 last;
}
# /linux/ubuntu -&gt; /linux.php?distro=ubuntu
</code></pre>
<pre><code class="language-nginx"># Условный rewrite
if ($scheme = "http") {
    rewrite ^ https://example.com$uri permanent;
}
</code></pre>
<h3>Редирект с сохранением параметров</h3>
<pre><code class="language-nginx">location /old-path/ {
    return 301 /new-path$request_uri;
}
</code></pre>
<h2>Переменные Nginx</h2>
<p dir="auto">Nginx предоставляет множество встроенных переменных для использования в конфигурации.</p>
<h3>Основные переменные запроса</h3>
<pre><code class="language-nginx"># IP адрес клиента
$remote_addr

# Порт клиента
$remote_port

# Полный URI запроса с параметрами
$request_uri

# Нормализованный URI (после rewrite)
$uri

# HTTP метод (GET, POST, etc.)
$request_method

# Протокол запроса (http или https)
$scheme

# Host header из запроса
$host

# Доменное имя сервера
$server_name

# Порт сервера
$server_port

# Query string (параметры после ?)
$args или $query_string
</code></pre>
<h3>Пример использования переменных</h3>
<pre><code class="language-nginx"># Логирование с переменными
log_format custom '$remote_addr - $remote_user [$time_local] '
                  '"$request" $status $body_bytes_sent '
                  '"$http_referer" "$http_user_agent"';

# Установка заголовков
location / {
    proxy_pass http://backend;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

# Условная логика
if ($request_method = POST) {
    return 405;
}
</code></pre>
<h3>Переменные для доступа к параметрам</h3>
<pre><code class="language-nginx"># Доступ к конкретному query параметру
$arg_name  # для параметра ?name=value

# Пример
if ($arg_debug = "true") {
    return 200 "Debug mode";
}
</code></pre>
<h2>Map директива</h2>
<p dir="auto">Директива <code>map</code> создает новые переменные на основе значений других переменных.</p>
<p dir="auto"><strong>Синтаксис</strong>:</p>
<pre><code class="language-nginx">map $source_variable $destination_variable {
    default default_value;
    value1 result1;
    value2 result2;
    ~regex result3;
}
</code></pre>
<h3>Примеры использования map</h3>
<pre><code class="language-nginx"># Редирект поддоменов
map $host $redirect_host {
    default "example.org";
    ~^(?&lt;subdomain&gt;\S+)\.example\.com$ $subdomain.example.org;
}

server {
    server_name .example.com;
    return 301 https://$redirect_host$request_uri;
}
</code></pre>
<pre><code class="language-nginx"># Определение backend на основе User-Agent
map $http_user_agent $backend {
    default backend_default;
    ~*bot backend_bots;
    ~*mobile backend_mobile;
}

server {
    location / {
        proxy_pass http://$backend;
    }
}
</code></pre>
<pre><code class="language-nginx"># Установка переменной для блокировки IP
map $remote_addr $blocked {
    default 0;
    192.168.1.10 1;
    10.0.0.5 1;
}

server {
    if ($blocked) {
        return 403;
    }
}
</code></pre>
<p dir="auto"><strong>Важно</strong>: <code>map</code> директива может использоваться только в <code>http</code> контексте, а не внутри <code>server</code> или <code>location</code>.</p>
<h2>Rate Limiting (ограничение частоты запросов)</h2>
<p dir="auto">Rate limiting защищает сервер от перегрузки и DoS атак.</p>
<h3>Limit_req (ограничение запросов)</h3>
<pre><code class="language-nginx">http {
    # Определяем зону для отслеживания
    limit_req_zone $binary_remote_addr zone=limitbyip:10m rate=10r/s;
    
    # Статус для отклоненных запросов
    limit_req_status 429;
    
    server {
        location /api/ {
            # Применяем ограничение
            limit_req zone=limitbyip burst=20 nodelay;
            
            proxy_pass http://backend;
        }
    }
}
</code></pre>
<p dir="auto"><strong>Параметры</strong>:</p>
<ul>
<li><code>$binary_remote_addr</code> — ключ для идентификации клиентов (IP адрес)</li>
<li><code>zone=limitbyip:10m</code> — имя зоны и размер памяти (10 МБ)</li>
<li><code>rate=10r/s</code> — максимальная частота (10 запросов в секунду)</li>
<li><code>burst=20</code> — разрешает временные всплески до 20 запросов</li>
<li><code>nodelay</code> — обрабатывает burst запросы немедленно, без задержки</li>
</ul>
<p dir="auto"><strong>Как это работает</strong>: Nginx отслеживает количество запросов от каждого IP адреса. Если частота превышает указанный лимит, запросы задерживаются (помещаются в очередь) или отклоняются с ошибкой 429.</p>
<h3>Limit_conn (ограничение соединений)</h3>
<pre><code class="language-nginx">http {
    # Определяем зону
    limit_conn_zone $binary_remote_addr zone=connlimit:10m;
    
    server {
        location /downloads/ {
            # Максимум 5 одновременных соединений от одного IP
            limit_conn connlimit 5;
            
            root /var/www/files;
        }
    }
}
</code></pre>
<h3>Множественные ограничения</h3>
<pre><code class="language-nginx">http {
    limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;
    limit_req_zone $server_name zone=perserver:10m rate=10r/s;
    
    server {
        location / {
            limit_req zone=perip burst=5 nodelay;
            limit_req zone=perserver burst=10;
            
            proxy_pass http://backend;
        }
    }
}
</code></pre>
<h2>MIME типы</h2>
<h3>Default_type и mime.types</h3>
<p dir="auto">Nginx использует MIME типы для определения типа содержимого файлов.</p>
<pre><code class="language-nginx">http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
}
</code></pre>
<p dir="auto"><strong>Как это работает</strong>: Файл <code>mime.types</code> содержит сопоставление расширений файлов и MIME типов. Если расширение файла не найдено в <code>mime.types</code>, используется <code>default_type</code>.</p>
<p dir="auto"><code>application/octet-stream</code> означает, что браузер будет скачивать файл как бинарный, вместо попытки отобразить его.</p>
<h3>Добавление пользовательских MIME типов</h3>
<pre><code class="language-nginx">http {
    include mime.types;
    
    types {
        application/javascript mjs;
        application/wasm wasm;
    }
}
</code></pre>
<h2>Логирование</h2>
<h3>Access log</h3>
<pre><code class="language-nginx">http {
    # Определение формата лога
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    # Использование формата
    access_log /var/log/nginx/access.log main;
}
</code></pre>
<h3>Пользовательский формат лога</h3>
<pre><code class="language-nginx">http {
    log_format custom '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_referer" "$http_user_agent" '
                      '$request_time $upstream_response_time';
    
    access_log /var/log/nginx/custom.log custom;
}
</code></pre>
<p dir="auto"><strong>Полезные переменные для логов</strong>:</p>
<ul>
<li><code>$request_time</code> — полное время обработки запроса</li>
<li><code>$upstream_response_time</code> — время ответа backend сервера</li>
<li><code>$status</code> — код HTTP ответа</li>
<li><code>$body_bytes_sent</code> — количество отправленных байт</li>
</ul>
<h3>Error log</h3>
<pre><code class="language-nginx"># Уровни: debug, info, notice, warn, error, crit, alert, emerg
error_log /var/log/nginx/error.log warn;
</code></pre>
<h3>Отключение логов для статики</h3>
<pre><code class="language-nginx">location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    access_log off;
    expires 1y;
}
</code></pre>
<h2>Include директива</h2>
<p dir="auto">Директива <code>include</code> позволяет подключать внешние конфигурационные файлы.</p>
<pre><code class="language-nginx">http {
    include /etc/nginx/mime.types;
    include /etc/nginx/conf.d/*.conf;
    
    server {
        include /etc/nginx/snippets/ssl-params.conf;
        include /etc/nginx/snippets/security-headers.conf;
    }
}
</code></pre>
<p dir="auto"><strong>Преимущества использования include</strong>:</p>
<ul>
<li>Модульность конфигурации</li>
<li>Переиспользование общих настроек</li>
<li>Упрощение управления большими конфигурациями</li>
</ul>
<h3>Структура директорий</h3>
<pre><code>/etc/nginx/
├── nginx.conf                    # Главный файл
├── conf.d/                       # Дополнительные конфигурации
│   └── default.conf
├── sites-available/              # Доступные сайты
│   ├── example.com.conf
│   └── test.com.conf
├── sites-enabled/                # Активные сайты (симлинки)
│   └── example.com.conf -&gt; ../sites-available/example.com.conf
└── snippets/                     # Переиспользуемые фрагменты
    ├── ssl-params.conf
    └── security-headers.conf
</code></pre>
<h2>If директива и её подводные камни</h2>
<p dir="auto">Директива <code>if</code> в Nginx работает не так, как ожидается в большинстве языков программирования.</p>
<h3>Когда безопасно использовать if</h3>
<p dir="auto"><strong>Безопасно</strong> только с директивами <code>return</code> и <code>rewrite</code>:</p>
<pre><code class="language-nginx">if ($scheme = "http") {
    return 301 https://$host$request_uri;
}

if ($request_method = POST) {
    return 405;
}
</code></pre>
<h3>Проблемы с if</h3>
<pre><code class="language-nginx"># НЕПРАВИЛЬНО - может вызвать segmentation fault
location / {
    if ($request_uri ~* "admin") {
        proxy_pass http://admin_backend;
    }
    root /var/www/html;
}
</code></pre>
<p dir="auto"><strong>Почему это проблема</strong>: <code>if</code> в Nginx оценивается на этапе конфигурации, а не на каждом запросе. Это может приводить к неожиданному поведению и ошибкам.</p>
<h3>Альтернативы if</h3>
<p dir="auto"><strong>Используйте <code>map</code> вместо <code>if</code></strong>:</p>
<pre><code class="language-nginx">map $request_uri $backend {
    default http://default_backend;
    ~*admin http://admin_backend;
}

server {
    location / {
        proxy_pass $backend;
    }
}
</code></pre>
<p dir="auto"><strong>Используйте разные <code>location</code> блоки</strong>:</p>
<pre><code class="language-nginx">location ~* /admin {
    proxy_pass http://admin_backend;
}

location / {
    proxy_pass http://default_backend;
}
</code></pre>
<h2>Events контекст и оптимизация производительности</h2>
<h3>Основные директивы events</h3>
<pre><code class="language-nginx">events {
    # Количество одновременных соединений на worker
    worker_connections 1024;
    
    # Метод обработки событий (зависит от ОС)
    use epoll;  # Linux
    # use kqueue;  # FreeBSD, macOS
    
    # Принимать несколько соединений за раз
    multi_accept on;
}
</code></pre>
<h3>Методы обработки событий</h3>
<p dir="auto"><strong>Linux: epoll</strong> — наиболее эффективный метод для Linux систем.</p>
<p dir="auto"><strong>FreeBSD/macOS: kqueue</strong> — оптимизированный для BSD систем.</p>
<p dir="auto"><strong>Почему это важно</strong>: Эти методы используют механизмы ядра операционной системы для эффективной обработки тысяч соединений одновременно без блокировки.</p>
<h3>Полная оптимизация производительности</h3>
<pre><code class="language-nginx">user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    # Основные настройки
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    
    # Таймауты
    keepalive_timeout 65;
    client_header_timeout 60;
    client_body_timeout 60;
    send_timeout 60;
    
    # Буферы
    client_body_buffer_size 16k;
    client_max_body_size 10m;
    
    # Gzip
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_types text/plain text/css text/xml text/javascript 
               application/json application/javascript application/xml;
    
    # Кэширование открытых файлов
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid 60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
}
</code></pre>
<h2>Проверка и перезагрузка конфигурации</h2>
<h3>Проверка синтаксиса</h3>
<pre><code class="language-bash"># Проверка конфигурации
sudo nginx -t

# Вывод:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
</code></pre>
<h3>Управление Nginx</h3>
<pre><code class="language-bash"># Запуск
sudo systemctl start nginx

# Остановка
sudo systemctl stop nginx

# Перезапуск
sudo systemctl restart nginx

# Перезагрузка конфигурации без разрыва соединений
sudo systemctl reload nginx

# Или напрямую
sudo nginx -s reload

# Проверка статуса
sudo systemctl status nginx
</code></pre>
<h3>Сигналы Nginx</h3>
<pre><code class="language-bash"># Изящная остановка (ждет завершения запросов)
sudo nginx -s quit

# Быстрая остановка
sudo nginx -s stop

# Перезагрузка конфигурации
sudo nginx -s reload

# Переоткрыть лог-файлы
sudo nginx -s reopen
</code></pre>
<h2>Полный пример конфигурации production-сервера</h2>
<pre><code class="language-nginx">user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    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" '
                    '$request_time $upstream_response_time';
    
    access_log /var/log/nginx/access.log main;
    
    # Основные настройки
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    
    # Таймауты
    keepalive_timeout 65;
    client_header_timeout 60;
    client_body_timeout 60;
    send_timeout 60;
    
    # Буферы
    client_body_buffer_size 16k;
    client_max_body_size 10m;
    
    # Gzip сжатие
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_proxied any;
    gzip_vary on;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml
        application/xml+rss;
    
    # Rate limiting
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_status 429;
    
    # Upstream для балансировки
    upstream backend {
        least_conn;
        server backend1.example.com:8080 weight=3;
        server backend2.example.com:8080 weight=2;
        server backend3.example.com:8080 backup;
    }
    
    # Редирект HTTP на HTTPS
    server {
        listen 80;
        listen [::]:80;
        server_name example.com www.example.com;
        return 301 https://www.example.com$request_uri;
    }
    
    # Редирект с example.com на www.example.com
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name example.com;
        
        ssl_certificate /etc/nginx/ssl/certificate.crt;
        ssl_certificate_key /etc/nginx/ssl/private.key;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        
        return 301 https://www.example.com$request_uri;
    }
    
    # Основной сервер
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name www.example.com;
        
        root /var/www/html;
        index index.php index.html;
        
        # SSL
        ssl_certificate /etc/nginx/ssl/certificate.crt;
        ssl_certificate_key /etc/nginx/ssl/private.key;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        
        # Security headers
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header X-Frame-Options "DENY" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none';" always;
        
        # Логирование
        access_log /var/log/nginx/example.com.access.log main;
        error_log /var/log/nginx/example.com.error.log warn;
        
        # Основной location
        location / {
            try_files $uri $uri/ /index.php?$args;
        }
        
        # API с rate limiting
        location /api/ {
            limit_req zone=general burst=20 nodelay;
            
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            
            proxy_read_timeout 300s;
            proxy_connect_timeout 60s;
        }
        
        # PHP обработка
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
        
        # Статические файлы
        location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
            access_log off;
        }
        
        # Запрет доступа к скрытым файлам
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }
        
        # Health check endpoint
        location = /health {
            access_log off;
            return 200 "OK\n";
            add_header Content-Type text/plain;
        }
    }
}
</code></pre>
<h2>Заключение</h2>
<p dir="auto">Эта статья охватывает основные и продвинутые аспекты конфигурации Nginx:</p>
<ul>
<li><strong>Архитектура</strong> — master и worker процессы, обработка соединений</li>
<li><strong>Структура конфигурации</strong> — иерархия контекстов и директив</li>
<li><strong>Location блоки</strong> — модификаторы и приоритеты обработки</li>
<li><strong>Reverse proxy</strong> — проксирование запросов на backend серверы</li>
<li><strong>Балансировка нагрузки</strong> — upstream блоки и методы распределения</li>
<li><strong>SSL/TLS</strong> — настройка HTTPS и редиректы</li>
<li><strong>Оптимизация</strong> — gzip, кэширование, буферы и таймауты</li>
<li><strong>Безопасность</strong> — security headers и rate limiting</li>
<li><strong>PHP-FPM</strong> — интеграция с PHP приложениями</li>
<li><strong>Логирование</strong> — форматы логов и пользовательские настройки</li>
</ul>
<p dir="auto">Понимание того, как работает каждая директива и почему она настроена определенным образом, поможет вам создавать эффективные, безопасные и высокопроизводительные конфигурации Nginx для любых задач.</p>
]]></description><link>https://forum.exlends.ru/topic/333/ischerpyvayushee-rukovodstvo-po-konfiguracii-nginx</link><generator>RSS for Node</generator><lastBuildDate>Wed, 20 May 2026 06:36:25 GMT</lastBuildDate><atom:link href="https://forum.exlends.ru/topic/333.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 10 Dec 2025 10:58:41 GMT</pubDate><ttl>60</ttl></channel></rss>