SafeKit - СейфКит
Комплекс безопасности для вашего бизнеса
Услуги
Битрикс24
1С-Битрикс: Управление сайтом
Mikrotik
Windows Server
Блог
Компания
О компании
Партнеры
Реквизиты
Оферта
Политика
Контакты
Акции
+79696000089
+79696000089 Мобильный
Заказать звонок
Задать вопрос
sale@safekit.tech
г. Нижний Новгород, сп Новинки, ул. 2-ая Дорожная, д. 13, кв. 19
  • Вконтакте
  • Telegram
  • WhatsApp
+79696000089
+79696000089 Мобильный
SafeKit - СейфКит
Компания
  • О компании
  • Партнеры
  • Реквизиты
  • Оферта
  • Политика
Сертификаты
Услуги
  • Битрикс24
  • 1С-Битрикс: Управление сайтом
  • Mikrotik
  • Windows Server
Блог
Лицензии
  • amoCRM
  • Битрикс
  • Подписки
Инструменты
SafeKit Pro
Развлечения для сетевиков
Контакты
+  ЕЩЕ
    SafeKit - СейфКит
    Компания
    • О компании
    • Партнеры
    • Реквизиты
    • Оферта
    • Политика
    Сертификаты
    Услуги
    • Битрикс24
    • 1С-Битрикс: Управление сайтом
    • Mikrotik
    • Windows Server
    Блог
    Лицензии
    • amoCRM
    • Битрикс
    • Подписки
    Инструменты
    SafeKit Pro
    Развлечения для сетевиков
    Контакты
    +  ЕЩЕ
      nginx: шпаргалка с разбором — от listen до балансировки - SafeKit - СейфКит
      Телефоны
      +79696000089 Мобильный
      • Услуги
        • Назад
        • Услуги
        • Битрикс24
        • 1С-Битрикс: Управление сайтом
        • Mikrotik
        • Windows Server
      • Блог
      • Компания
        • Назад
        • Компания
        • О компании
        • Партнеры
        • Реквизиты
        • Оферта
        • Политика
      • Контакты
      • Акции
      • +79696000089Мобильный
      Контактная информация
      г. Нижний Новгород, сп Новинки, ул. 2-ая Дорожная, д. 13, кв. 19
      sale@safekit.tech
      • Вконтакте
      • Telegram
      • WhatsApp

      nginx: шпаргалка с разбором — от listen до балансировки

      Главная
      —
      Блог
      —nginx: шпаргалка с разбором — от listen до балансировки
      25 февраля 2026 10:00

      Полный разбор типовых конфигов nginx: порты, домены, статика, редиректы, reverse proxy, балансировка, SSL и security headers. Каждый блок — с объяснением, зачем это нужно.

      nginx — один из самых распространённых веб-серверов. Его ставят как фронтенд перед приложениями, раздают статику, терминируют SSL, балансируют нагрузку. Конфиги внешне похожи, но один неверный параметр — и сервис ведёт себя непредсказуемо.

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

      Структура конфига

      Главный файл: /etc/nginx/nginx.conf. Конфиги сайтов лежат в /etc/nginx/sites-available/, подключаются симлинком в /etc/nginx/sites-enabled/.

      # Проверить синтаксис конфига
      nginx -t
      # Перечитать конфиг без рестарта (graceful reload)
      nginx -s reload
      # или через systemd:
      systemctl reload nginx
      # Полный рестарт (обрывает соединения)
      systemctl restart nginx
      # Статус и последние ошибки
      systemctl status nginx
      journalctl -u nginx -n 50 --no-pager

      1. listen — порты и протоколы

      server {
          listen 80;              # IPv4, порт 80 (HTTP)
          listen [::]:80;         # IPv6, порт 80
          listen 443 ssl;         # IPv4, порт 443 (HTTPS)
          listen [::]:443 ssl;    # IPv6, порт 443
          # Если нужен только IPv6:
          listen [::]:80 ipv6only=on;
      }

      Как читать: каждый listen — это отдельный сокет, который nginx открывает. Можно слушать несколько портов в одном server {}-блоке. Параметр ssl после порта говорит: все соединения на этот порт обрабатывать как HTTPS.

      Типичная ошибка: listen 443 без ssl — nginx примет соединение, но не сможет его расшифровать и вернёт ошибку клиенту.

      # Проверить, какие порты реально слушает nginx
      ss -tlnp | grep nginx
      # или
      netstat -tlnp | grep nginx

      2. server_name — домены и поддомены

      server {
          # Один домен
          server_name example.com;
          # Домен и www
          server_name example.com www.example.com;
          # Все поддомены (wildcard)
          server_name *.example.com;
          # Любой хост (default server)
          server_name _;
      }

      Как читать: nginx смотрит на заголовок Host входящего запроса и ищет server {}-блок с совпадающим server_name. Если совпадений нет — отдаёт запрос default_server (первый блок или тот, у кого явно прописан этот флаг).

      Wildcard *.example.com покрывает sub.example.com, но не сам example.com — для него нужна отдельная строка.

      server_name _ — условный «мусорный» сервер, который ловит всё, на что не нашлось явного блока. Полезно для заглушки или редиректа неизвестных хостов.

      # Посмотреть все server_name в конфиге
      nginx -T 2>/dev/null | grep server_name

      3. access_log — логирование запросов

      http {
          # Формат лога (определяется один раз в http {})
          log_format main  '$remote_addr [$time_local] '
                           '"$request" $status $body_bytes_sent '
                           '"$http_referer" "$http_user_agent"';
          # JSON-формат для ELK / Loki
          log_format json escape=json
              '{"time":"$time_iso8601",'
              '"ip":"$remote_addr",'
              '"method":"$request_method",'
              '"uri":"$request_uri",'
              '"status":$status,'
              '"bytes":$body_bytes_sent}';
      }
      server {
          # Логировать в файл с форматом main
          access_log /var/log/nginx/example.access.log main;
          # Буферизация: пишем на диск пачками, не каждую строку
          access_log /var/log/nginx/example.access.log main buffer=16k flush=10s;
          # Отключить логирование для healthcheck
          location /health {
              access_log off;
              return 200 "ok";
          }
      }

      Как читать: без явного log_format nginx пишет в формате combined (Apache-совместимый). JSON-формат удобен, если логи собирает Filebeat или Promtail.

      buffer + flush — копит строки в памяти и сбрасывает пачкой. Снижает нагрузку на диск при высоком трафике.

      # Следить за логом в реальном времени
      tail -f /var/log/nginx/example.access.log
      # Топ URL по количеству запросов
      awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
      # Топ IP по количеству запросов
      awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
      # Все ошибки 5xx за последние 100 строк
      tail -100 /var/log/nginx/access.log | awk '$9 >= 500'

      4. Раздача статики

      server {
          listen 80;
          server_name example.com;
          root /var/www/example;
          index index.html index.htm;
          location / {
              # Ищем файл → директорию → 404
              try_files $uri $uri/ =404;
              # Для SPA (React/Vue) вместо =404:
              # try_files $uri $uri/ /index.html;
          }
          # Кэширование картинок на 30 дней
          location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
              expires 30d;
              add_header Cache-Control "public, immutable";
          }
          # CSS и JS — 7 дней
          location ~* \.(css|js)$ {
              expires 7d;
              add_header Cache-Control "public";
          }
      }
      # Сжатие gzip (добавить в http {})
      http {
          gzip on;
          gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
          gzip_min_length 256;
          gzip_comp_level 6;
          gzip_vary on;
      }

      try_files — ключевая директива. Проверяет файл по $uri, потом директорию $uri/, затем возвращает 404. Для SPA-приложений вместо 404 подставляют /index.html — клиентский роутер сам разберётся с URL.

      gzip_comp_level 6 — баланс между степенью сжатия и нагрузкой на CPU. Уровень 9 даёт незначительно лучшее сжатие, но заметно дороже. Уровень 1 почти не сжимает. 6 — оптимум для большинства случаев.

      # Проверить, что gzip работает
      curl -H "Accept-Encoding: gzip" -I https://example.com | grep -i encoding

      5. Редиректы

      # Редирект с www на без www (301 — постоянный)
      server {
          listen 80;
          server_name www.example.com;
          return 301 http://example.com$request_uri;
      }
      # Редирект с HTTP на HTTPS
      server {
          listen 80;
          server_name example.com www.example.com;
          return 301 https://example.com$request_uri;
      }
      # Редирект конкретного URL
      location /old-page {
          return 301 /new-page;
      }
      # Временный редирект (поисковик не обновляет индекс)
      location /promo {
          return 302 /promo-2026;
      }
      # Редирект по регулярному выражению
      rewrite ^/blog/([0-9]+)$ /articles/$1 permanent;  # 301
      rewrite ^/blog/([0-9]+)$ /articles/$1 redirect;   # 302

      301 vs 302: 301 — постоянный, поисковик переносит вес страницы на новый URL. 302 — временный, старый адрес остаётся в индексе. Ошибка здесь стоит дорого: неверный 301 кэшируется браузером и поисковиком надолго.

      return vs rewrite: return быстрее — nginx сразу отвечает клиенту, не продолжая обработку. rewrite меняет URI внутри nginx и передаёт дальше по цепочке location-ов. Используйте return везде, где не нужна внутренняя переработка URI.

      6. Reverse proxy — обратный прокси

      server {
          listen 80;
          server_name example.com;
          location / {
              proxy_pass http://127.0.0.1:3000;
              # Передать реальный IP клиента в приложение
              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_set_header Host              $host;
              # Таймауты
              proxy_connect_timeout 10s;
              proxy_send_timeout    60s;
              proxy_read_timeout    60s;
              # Буферизация ответа бэкенда
              proxy_buffering    on;
              proxy_buffer_size  8k;
              proxy_buffers      16 8k;
          }
      }
      # Для WebSocket — дополнительные заголовки
      location /ws {
          proxy_pass http://127.0.0.1:3000;
          proxy_http_version 1.1;
          proxy_set_header Upgrade    $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_set_header Host       $host;
      }
      # Через Unix-сокет (быстрее TCP loopback)
      location /api {
          proxy_pass http://unix:/run/myapp/app.sock;
          proxy_set_header Host $host;
      }

      proxy_set_header X-Real-IP — без этого заголовка приложение видит IP самого nginx (127.0.0.1), а не реального клиента. Это ломает логи, геолокацию и rate-limiting на уровне приложения.

      X-Forwarded-Proto — приложение знает, по какому протоколу пришёл клиент. Нужно для корректного формирования ссылок: без него приложение за HTTPS-nginx будет генерировать http:// ссылки.

      proxy_buffering off нужен для Server-Sent Events и длинных потоков — иначе nginx будет буферизовать данные и клиент не получит их в реальном времени.

      # Проверить, что заголовки доходят до приложения
      curl -H "Host: example.com" http://127.0.0.1:3000/debug-headers

      7. Балансировка нагрузки

      upstream app_servers {
          # Round-robin (по умолчанию) — запросы по очереди
          server 10.0.0.1:3000;
          server 10.0.0.2:3000;
          # weight: сервер с weight=3 получает втрое больше запросов
          server 10.0.0.1:3000 weight=3;
          server 10.0.0.2:3000 weight=1;
          # backup: используется только если основные недоступны
          server 10.0.0.3:3000 backup;
          # down: временно вывести из ротации (без удаления строки)
          server 10.0.0.4:3000 down;
          # Пул постоянных соединений к бэкенду
          keepalive 32;
      }
      # ip_hash: один клиент всегда попадает на один бэкенд
      upstream app_sticky {
          ip_hash;
          server 10.0.0.1:3000;
          server 10.0.0.2:3000;
      }
      # least_conn: запрос идёт к серверу с наименьшим числом активных соединений
      upstream app_smart {
          least_conn;
          server 10.0.0.1:3000;
          server 10.0.0.2:3000;
      }
      server {
          listen 80;
          server_name example.com;
          location / {
              proxy_pass       http://app_servers;
              proxy_set_header Host       $host;
              proxy_set_header X-Real-IP  $remote_addr;
              # Для keepalive обязательно:
              proxy_http_version 1.1;
              proxy_set_header Connection "";
          }
      }

      Round-robin подходит, когда все запросы примерно одинаковой длительности и серверы равнозначны. least_conn умнее: если один запрос занимает 5 секунд, а другой — 50 мс, round-robin всё равно распределит следующий запрос «по очереди». least_conn учитывает реальную загрузку.

      ip_hash нужен, когда приложение хранит сессию в памяти процесса (не в Redis). Минус: при падении сервера его клиенты «переедут» и потеряют сессию. Лучше вынести сессии во внешнее хранилище.

      keepalive + proxy_http_version 1.1 — без этих двух директив keepalive не работает. HTTP/1.0 закрывает соединение после каждого запроса.

      8. SSL/TLS

      server {
          listen 443 ssl;
          server_name example.com;
          ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
          # Только TLS 1.2 и 1.3 (1.0 и 1.1 уязвимы и отключены в браузерах)
          ssl_protocols TLSv1.2 TLSv1.3;
          # Безопасные шифры
          ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
          ssl_prefer_server_ciphers off;
          # Кэш сессий: повторное TLS-рукопожатие не нужно
          ssl_session_cache   shared:SSL:10m;
          ssl_session_timeout 1d;
          ssl_session_tickets off;
          # OCSP Stapling: сервер сам проверяет отзыв сертификата
          ssl_stapling        on;
          ssl_stapling_verify on;
          ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
          resolver 8.8.8.8 1.1.1.1 valid=300s;
          # HSTS: браузер запоминает HTTPS на год, не делает HTTP-запрос вообще
          add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
      }
      # HTTP → HTTPS редирект
      server {
          listen 80;
          server_name example.com www.example.com;
          return 301 https://example.com$request_uri;
      }

      ssl_prefer_server_ciphers off — в TLS 1.3 клиент выбирает шифр, сервер это не контролирует. Оставить off — правильно для TLS 1.3. Для совместимости со старыми клиентами иногда ставят on.

      OCSP Stapling — без него браузер при каждом соединении обращается к серверу сертификационного центра, чтобы проверить, не отозван ли сертификат. Это добавляет задержку. Со stapling nginx сам периодически получает OCSP-ответ и прикладывает его к TLS-рукопожатию.

      # Получить сертификат Let's Encrypt
      certbot --nginx -d example.com -d www.example.com
      # Проверить срок действия сертификата
      echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
      # Автообновление сертификатов
      systemctl status certbot.timer

      9. Security headers — заголовки безопасности

      server {
          # Скрыть версию nginx из заголовков и страниц ошибок
          server_tokens off;
          # Запрет показа сайта во фрейме на чужих сайтах (clickjacking)
          add_header X-Frame-Options "SAMEORIGIN" always;
          # Браузер не пытается угадать тип файла по содержимому
          add_header X-Content-Type-Options "nosniff" always;
          # Не передавать полный URL при переходе на другой домен
          add_header Referrer-Policy "strict-origin-when-cross-origin" always;
          # Политика загрузки ресурсов (CSP)
          add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" always;
          # Запрет определения местоположения, камеры и микрофона
          add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
      }

      server_tokens off — по умолчанию nginx отдаёт версию в заголовке Server: nginx/1.26.0. Зная версию, атакующий ищет соответствующие CVE. Отключаем, заодно убирается версия и со страниц ошибок.

      X-Frame-Options SAMEORIGIN — сайт можно открыть во <iframe> только с того же домена. Защита от clickjacking: когда злоумышленник встраивает невидимый фрейм с вашим сайтом поверх своего и заставляет пользователя кликать «вслепую».

      CSP — самый мощный заголовок. Запрещает браузеру загружать скрипты, стили, изображения с доменов, которых нет в политике. Эффективная защита от XSS. Но требует тщательной настройки под конкретный сайт.

      # Проверить все заголовки ответа
      curl -sI https://example.com
      # Проверить оценку конфига SSL
      # https://www.ssllabs.com/ssltest/
      # Проверить security headers
      # https://securityheaders.com/

      10. Rate limiting — ограничение запросов

      http {
          # Зона памяти: 10 МБ, до 10 запросов/сек на один IP
          limit_req_zone $binary_remote_addr zone=api:10m    rate=10r/s;
          # Отдельная зона для формы входа: не более 5 попыток/мин
          limit_req_zone $binary_remote_addr zone=login:10m  rate=5r/m;
      }
      server {
          # API: разрешаем всплески до 20, остальное — 429
          location /api/ {
              limit_req zone=api burst=20 nodelay;
              limit_req_status 429;
              proxy_pass http://127.0.0.1:3000;
          }
          # Форма входа: строгое ограничение
          location /login {
              limit_req zone=login burst=3;
              limit_req_status 429;
              proxy_pass http://127.0.0.1:3000;
          }
      }

      $binary_remote_addr — IP в бинарном виде (4 байта для IPv4). Занимает меньше памяти, чем строковый адрес. 10 МБ хватает примерно для 160 000 уникальных IP.

      burst — допустимый всплеск сверх лимита. Запросы из burst ставятся в очередь. nodelay — очередь обрабатывается немедленно, без искусственных задержек. Без nodelay запросы из burst «размазываются» по времени, что создаёт неожиданные задержки для клиента.

      Rate limiting защищает от брутфорса, credential stuffing и агрессивных ботов даже до того, как запрос дойдёт до приложения.

      Итог: быстрая диагностика

      # Проверить синтаксис конфига (всегда перед reload)
      nginx -t
      # Посмотреть итоговый конфиг со всеми include
      nginx -T
      # Текущие соединения к nginx
      ss -s
      # Ошибки в реальном времени
      tail -f /var/log/nginx/error.log
      # Найти блок, обрабатывающий домен
      nginx -T 2>/dev/null | grep -B5 "server_name.*example.com"
      # Сколько воркеров запущено
      ps aux | grep nginx
      Теги
      nginx конфиг reverse proxy ssl балансировка linux
      Назад к списку
      Теги
      AWS Security Blog BleepingComputer Check Point Research Cisco Talos Intelligence Cloudflare Blog (Security) Dark Reading Fortinet Blog Krebs on Security Microsoft Security Blog Positive Technologies Blog SecurityWeek The Hacker News информационная безопасность кибербезопасность новости ИБ Хабр — Информационная безопасность Хабр — Системное администрирование
      Компания
      Сертификаты
      Услуги
      Блог
      Лицензии
      Инструменты
      SafeKit Pro
      Развлечения для сетевиков
      Контакты
      • Вконтакте
      • Telegram
      • WhatsApp
      +79696000089
      +79696000089 Мобильный
      sale@safekit.tech
      г. Нижний Новгород, сп Новинки, ул. 2-ая Дорожная, д. 13, кв. 19
      Политика конфиденциальности
      2026 © Всё для защиты и стабильности
      Нашли ошибку на сайте? Выделите текст и нажмите Ctrl+Shift+Enter (или Cmd+Shift+Enter на Mac) — сообщение уйдёт в поддержку. Если горячие клавиши недоступны, пишите на support@safekit.tech.