Stylesheet conf/userstyle.css not found, please contact the developer of "dokuwiki_2024" template.
linux:nginx:nginx_tnt
Различия
Показаны различия между двумя версиями страницы.
Предыдущая версия справа и слеваПредыдущая версияСледующая версия | Предыдущая версия | ||
linux:nginx:nginx_tnt [2021/11/24 00:04] – dx | linux:nginx:nginx_tnt [2022/08/04 14:12] (текущий) – dx | ||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ====== nginx: tips & howto ====== | ||
+ | ===== Генератор конфига ===== | ||
+ | |||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | |||
+ | Отдельно хочу отметить утилиту [[https:// | ||
+ | |||
+ | ===== Конфиги сниппеты ===== | ||
+ | |||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | |||
+ | ===== Редиректы ===== | ||
+ | |||
+ | ==== Редирект всех запросов на определенный файл ==== | ||
+ | |||
+ | < | ||
+ | root / | ||
+ | index index.php; | ||
+ | |||
+ | location / { | ||
+ | try_files $uri $uri/ @redirect; | ||
+ | } | ||
+ | location ~ \.php$ { | ||
+ | try_files $uri @redirect; | ||
+ | ... | ||
+ | } | ||
+ | location @redirect { | ||
+ | return 301 /index.php; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Works like a charm, как говорится. | ||
+ | |||
+ | ==== Перенаправление на SSL-адрес (HTTPS) с нестандартным портом ==== | ||
+ | |||
+ | via http:// | ||
+ | |||
+ | < | ||
+ | |||
+ | ==== Редирект на https:// | ||
+ | |||
+ | < | ||
+ | server { | ||
+ | listen 80; | ||
+ | server_name foobar.com www.foobar.com | ||
+ | return 301 https:// | ||
+ | } | ||
+ | server { | ||
+ | listen 443 ssl; | ||
+ | server_name foobar.com; | ||
+ | |||
+ | ssl_certificate | ||
+ | ssl_certificate_key / | ||
+ | |||
+ | return 301 https:// | ||
+ | } | ||
+ | |||
+ | server { | ||
+ | listen 443 ssl; | ||
+ | server_name www.foobar.com; | ||
+ | root / | ||
+ | |||
+ | ssl_certificate | ||
+ | ssl_certificate_key / | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Еще примеры ==== | ||
+ | |||
+ | * https:// | ||
+ | * | ||
+ | |||
+ | ===== Банхаммер3000 ===== | ||
+ | |||
+ | ==== Блокируем через geoip ==== | ||
+ | |||
+ | http:// | ||
+ | |||
+ | Начиная с версии [[https:// | ||
+ | |||
+ | Примеры использования модуля - http:// | ||
+ | |||
+ | < | ||
+ | yum install nginx-module-geoip | ||
+ | apt-get install nginx-module-geoip | ||
+ | </ | ||
+ | |||
+ | Добавляем в самое начало файла ''/ | ||
+ | |||
+ | < | ||
+ | load_module " | ||
+ | </ | ||
+ | |||
+ | Коды названий стран | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | В блок **http {}** перед **include** добавить | ||
+ | |||
+ | < | ||
+ | geoip_country / | ||
+ | map $geoip_country_code $allowed_country { | ||
+ | default yes; | ||
+ | RU no; | ||
+ | UA no; | ||
+ | BY no; | ||
+ | CN no; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Для блокировки нужно добавить в **server {}** | ||
+ | |||
+ | < | ||
+ | if ($allowed_country = no) { | ||
+ | return 444; | ||
+ | </ | ||
+ | |||
+ | 444 - закрыть соединение без отправки ответа клиенту. | ||
+ | |||
+ | FIXME почитать про GeoIP2 | ||
+ | * https:// | ||
+ | * 1 | ||
+ | |||
+ | ==== Блокируем поисковых ботов ==== | ||
+ | |||
+ | * https:// | ||
+ | * https:// | ||
+ | |||
+ | < | ||
+ | map $http_user_agent $bad_bot { | ||
+ | default 0; | ||
+ | ~(? | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | В **server {}** добавить в нужное место | ||
+ | |||
+ | < | ||
+ | |||
+ | Для проверки представимся ahrefsom | ||
+ | |||
+ | < | ||
+ | |||
+ | ==== Блокируем реферальный спам ==== | ||
+ | 1 | ||
+ | Добавляес в '' | ||
+ | |||
+ | < | ||
+ | map $http_referer $bad_referer { | ||
+ | hostnames; | ||
+ | default | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Добавляес в '' | ||
+ | |||
+ | < | ||
+ | server { | ||
+ | if ($bad_referer) { | ||
+ | return 444; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Можно использовать [[https:// | ||
+ | |||
+ | < | ||
+ | http { | ||
+ | include referral-spam.conf; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | В этом нам поможет [[http:// | ||
+ | |||
+ | ===== PHP-FPM ===== | ||
+ | |||
+ | ==== ondemand или dynamic ==== | ||
+ | |||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | // | ||
+ | При политике ondemand воркеры создаётся только тогда когда приходит запрос. Через несколько секунд (задаётся в настройках) после завершения обработки запроса (если не поступит нового запроса который можно передать воркеру) воркер убивается.\\ | ||
+ | При dynamic демон всегда поддерживает некоторое заданное количество воркеров в пуле, и распределяет запросы между ними. Если для обработки запросов не хватает воркеров то демон создаёт дополнительных (вплоть до некоторого конфигурируемого значения). Когда потребность в дополнительных воркерах отпадает демон убивает лишние, | ||
+ | Профит от повторного использования воркеров в том что не тратится время на повторное создание процесса. Но если у тебя тормозной код то на его фоне ты этого времени всё-равно не заметишь.\\ | ||
+ | На сколько я понимаю это происходит как-то так. | ||
+ | |||
+ | Попаболь в том что воркеры не особо спешат освобождать память использованную для обработки запроса (кстати я не в курсе баг это или какая-то непонятная фича). По этому если твоё приложение на обработку каждого запроса тратит (например) 100 мб памяти и у тебя есть 3 воркера, | ||
+ | |||
+ | У меня используется dynamic для пулов которые без запросов не остаются, | ||
+ | |||
+ | ==== Калькулятор max_children ==== | ||
+ | |||
+ | cli | ||
+ | * [[https:// | ||
+ | * https:// | ||
+ | |||
+ | ui calc | ||
+ | * https:// | ||
+ | * [[https:// | ||
+ | |||
+ | ==== Разное FPM ==== | ||
+ | |||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[http:// | ||
+ | * [[http:// | ||
+ | * https:// | ||
+ | * [[https:// | ||
+ | |||
+ | |||
+ | ==== Дебаг PHP-FPM с помощью strace ==== | ||
+ | |||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | ===== Разное ===== | ||
+ | |||
+ | ==== Ограничение доступа для групп адресов ==== | ||
+ | |||
+ | ''/ | ||
+ | |||
+ | < | ||
+ | allow 1.2.3.4/32; | ||
+ | allow 1.2.3.8/32; | ||
+ | </ | ||
+ | |||
+ | ''/ | ||
+ | |||
+ | < | ||
+ | allow 10.0.0.0/8; | ||
+ | allow 172.16.0.0/ | ||
+ | allow 192.168.0.0/ | ||
+ | </ | ||
+ | |||
+ | ''/ | ||
+ | |||
+ | < | ||
+ | allow 4.5.6.7; | ||
+ | allow 8.9.10.11; | ||
+ | </ | ||
+ | |||
+ | ''/ | ||
+ | |||
+ | < | ||
+ | location ^~ /admin/ { | ||
+ | include includes/ | ||
+ | deny all; | ||
+ | } | ||
+ | |||
+ | location ^~ /beer/ { | ||
+ | include includes/ | ||
+ | include includes/ | ||
+ | include includes/ | ||
+ | deny all; | ||
+ | } | ||
+ | |||
+ | location ^~ /vodka/ { | ||
+ | include includes/ | ||
+ | include includes/ | ||
+ | deny all; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Как работает SNI ==== | ||
+ | |||
+ | * https:// | ||
+ | |||
+ | ==== Что такое CORS ==== | ||
+ | |||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | ==== Отключить кэширование для директории ==== | ||
+ | |||
+ | Например есть такое | ||
+ | |||
+ | < | ||
+ | location /static { | ||
+ | alias / | ||
+ | add_header Pragma " | ||
+ | add_header Cache-Control " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | И есть апишечка где кэш очень вреден | ||
+ | |||
+ | |||
+ | < | ||
+ | location / | ||
+ | add_header Pragma " | ||
+ | add_header Cache-Control " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== X509_check_private_key: | ||
+ | |||
+ | Нарушен порядок в crt/pem файле. | ||
+ | |||
+ | < | ||
+ | -----BEGIN CERTIFICATE----- | ||
+ | Сертификат_сервера | ||
+ | -----END CERTIFICATE----- | ||
+ | -----BEGIN CERTIFICATE----- | ||
+ | Сертификат корневого центра сертификации (CA) | ||
+ | -----END CERTIFICATE----- | ||
+ | -----BEGIN CERTIFICATE----- | ||
+ | СЕРТИФИКАТ ПРОМЕЖУТОЧНОГО ЦЕНТРА СЕРТИФИКАЦИИ | ||
+ | Сертификат промежуточного центра сертификации (Intermediate) | ||
+ | -----END CERTIFICATE----- | ||
+ | </ | ||
+ | |||
+ | ==== HTTPOnly и Secure Cookie ==== | ||
+ | |||
+ | * https:// | ||
+ | * https:// | ||
+ | |||
+ | ==== favicon.ico ==== | ||
+ | |||
+ | По стандарту, | ||
+ | Можно для nginx создать секцию | ||
+ | < | ||
+ | location / | ||
+ | root ... | ||
+ | log_not_found off; | ||
+ | access_log off; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Есть опция **empty_gif** | ||
+ | < | ||
+ | location / | ||
+ | empty_gif; | ||
+ | access_log off; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Таким образом будет отдаваться прозрачный гиф 1х1px на все запросы иконки. | ||
+ | |||
+ | А теперь объединим. | ||
+ | |||
+ | < | ||
+ | | ||
+ | access_log off; | ||
+ | try_files $uri @emptygif; | ||
+ | } | ||
+ | location @emptygif { | ||
+ | internal; | ||
+ | empty_gif; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | via | ||
+ | * http:// | ||
+ | * http:// | ||
+ | |||
+ | ==== Закрываем сайт на обслуживание ==== | ||
+ | |||
+ | **Варианты** | ||
+ | |||
+ | **1) в location /** | ||
+ | |||
+ | < | ||
+ | ## System Maintenance (Service Unavailable) | ||
+ | if (-f $document_root/ | ||
+ | error_page 503 / | ||
+ | return 503; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | (if нежелателен - там куча ограничений, | ||
+ | |||
+ | **2) try_files closed.html @apache =503;**\\ | ||
+ | (проблема в том, что в таком варианте код ответа при обслуживании будет 200). Хотя можно сделать отдельный location closed.html и в нем выставить код ответа 503, по желанию оттуда же отдать и саму страницу. | ||
+ | Можно написать как | ||
+ | < | ||
+ | но если индекса нет и апач перекидывает на какую-то внутреннюю страницу с рядом опций - могут быть проблемы, | ||
+ | |||
+ | С другой стороны, | ||
+ | |||
+ | **3) через переменную и if** | ||
+ | < | ||
+ | set $Maintenance = off; | ||
+ | if ($Maintenance = ' | ||
+ | но см выше про if. | ||
+ | </ | ||
+ | |||
+ | **4) выделить блок, закрывающий сайт на обслуживание в отдельный файл maint.conf**, | ||
+ | |||
+ | via http:// | ||
+ | |||
+ | ==== Как убедиться, | ||
+ | |||
+ | Нашёл здесь - https:// | ||
+ | |||
+ | Находим PID | ||
+ | |||
+ | < | ||
+ | # ps ax | grep nginx | ||
+ | 1071 ? Ss 0:01 nginx: master process / | ||
+ | 17947 pts/0 S+ 0:00 grep --color=auto nginx | ||
+ | 18315 ? S 0:25 nginx: worker process | ||
+ | </ | ||
+ | |||
+ | Запускаем trace | ||
+ | |||
+ | < | ||
+ | # strace -p 18315 2>&1 | grep gz | ||
+ | open("/ | ||
+ | open("/ | ||
+ | open("/ | ||
+ | </ | ||
+ | |||
+ | ==== monit ==== | ||
+ | |||
+ | https:// | ||
+ | |||
+ | < | ||
+ | server { | ||
+ | listen 80; | ||
+ | server_name monit.domain.com; | ||
+ | location / { | ||
+ | proxy_pass 127.0.0.1: | ||
+ | proxy_set_header Host $host; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Много соединений в TIME_WAIT ==== | ||
+ | |||
+ | Apache (backend) nginx (frontend). В netstat сотни/ | ||
+ | |||
+ | Скорее всего это нормально если включён keepalive. Если устанавливается много новых подключений и быстро разрываются, | ||
+ | |||
+ | Решением было установить для параметров ядра **TCP_TW_RECYCLE** и **TCP_TW_REUSE** значение **1**, по-умолчанию **0** | ||
+ | |||
+ | Применять с осторожностью | ||
+ | |||
+ | < | ||
+ | echo 1 > / | ||
+ | echo 1 > / | ||
+ | </ | ||
+ | |||
+ | Или добавить в ''/ | ||
+ | |||
+ | < | ||
+ | net.ipv4.tcp_tw_reuse=1 | ||
+ | net.ipv4.tcp_tw_recycle=1 | ||
+ | net.ipv4.tcp_fin_timeout=15 | ||
+ | net.ipv4.ip_local_port_range = 10240 65000 | ||
+ | </ | ||
+ | |||
+ | * TCP_TW_RECYCLE Description: | ||
+ | * TCP_TW_REUSE Description: | ||
+ | |||
+ | **Обновлено** | ||
+ | |||
+ | Ошибка **sysctl: cannot stat / | ||
+ | |||
+ | net.ipv4.tcp_tw_recycle [[https:// | ||
+ | |||
+ | < | ||
+ | The tcp_tw_recycle was already broken for connections | ||
+ | behind NAT, since the per-destination timestamp is not | ||
+ | monotonically increasing for multiple machines behind | ||
+ | a single destination address. | ||
+ | |||
+ | After the randomization of TCP timestamp offsets | ||
+ | in commit 8a5bd45f6616 (tcp: randomize tcp timestamp offsets | ||
+ | for each connection), | ||
+ | types of connections for the same reason: the timestamps | ||
+ | received from a single machine is not monotonically increasing, | ||
+ | anymore. | ||
+ | |||
+ | Remove tcp_tw_recycle, | ||
+ | the PAWSPassive SNMP counter since it is only used for | ||
+ | tcp_tw_recycle, | ||
+ | since the strict argument is only set when tcp_tw_recycle is | ||
+ | enabled. | ||
+ | </ | ||
+ | |||
+ | Почитать | ||
+ | * https:// | ||
+ | * http:// | ||
+ | |||
+ | ==== TCP_CORK/ | ||
+ | |||
+ | Игорь Сысоев / http:// | ||
+ | |||
+ | Да, в Линкусе TCP_CORK (tcp_nopush) и TCP_NODELAY взаимоисключающие, | ||
+ | nginx проявляет недюженный интеллект, | ||
+ | обеих опций. | ||
+ | |||
+ | " | ||
+ | полными пакетами. После того, как весь запрос обработан, | ||
+ | выключается, | ||
+ | |||
+ | " | ||
+ | по окончании запроса, | ||
+ | keep-alive. До этого nginx выводит данные вызовами writev() достаточно | ||
+ | большими порциями для заполнения пакета (" | ||
+ | данные должны уходить без задержек и TCP_NODELAY не нужен. А вот с последним | ||
+ | неполным пакетом может случится небольшая задержка, | ||
+ | закрывается. Для этого и нужно включить TCP_NODELAY. | ||
+ | |||
+ | В Линуксе обработка этих двух опций | ||
+ | |||
+ | < | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | такова: | ||
+ | |||
+ | 1) если данные будут выводить комбинацией writev(заголовок)/ | ||
+ | то проверяется, | ||
+ | TCP_NODELAY выключается и включается TCP_CORK. По окончании передачи TCP_CORK | ||
+ | выключается. Включать TCP_NODELAY не нужно, так как выключание TCP_CORK | ||
+ | сбрасывает данные. | ||
+ | |||
+ | 2) если при переходе в keep-alive TCP_CORK не была включена, | ||
+ | TCP_NODELAY, | ||
+ | |||
+ | Кстати, | ||
+ | до отдачи ответа. | ||
+ | |||
+ | ==== Как определить количество рабочих процессов, | ||
+ | |||
+ | via http:// | ||
+ | |||
+ | Ответ автора nginx Игоря Сысоева: | ||
+ | |||
+ | //Если весь сайт помещается в память сервера, | ||
+ | // | ||
+ | |||
+ | Кроме этого необходимо понаблюдать за состоянием процессов nginx в работе в часы пик. Командой ps посмотреть состояние рабочих процессов (worker process): | ||
+ | |||
+ | < | ||
+ | # ps ax -o %cpu, | ||
+ | |||
+ | %CPU VSZ WCHAN COMMAND | ||
+ | 0,0 1428 pause nginx: master process / | ||
+ | 0,0 2284 - nginx: worker process (nginx) | ||
+ | 0,0 2128 kqread nginx: worker process (nginx) | ||
+ | </ | ||
+ | |||
+ | Если один из рабочих процессов находится в состоянии ожидания " | ||
+ | |||
+ | И не забывайте контролировать логи ошибок nginx, если количество соединений превысит значение, | ||
+ | |||
+ | ==== Правильная отдача заголовков при технических работах на сайте ==== | ||
+ | |||
+ | (via http:// | ||
+ | |||
+ | Есть ситуация: | ||
+ | |||
+ | < | ||
+ | server { | ||
+ | listen 80 default; | ||
+ | server_name _; | ||
+ | root / | ||
+ | charset utf-8; | ||
+ | error_page 404 403 =503 /503.html; | ||
+ | location = /503.html { | ||
+ | add_header Retry-After "Sun, 27 Feb 2011 23: | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Строка error_page **404 403 =503 /503.html** означает, | ||
+ | |||
+ | ==== Схема frontend-backend ==== | ||
+ | |||
+ | * http:// | ||
+ | |||
+ | ===== Кэширование ===== | ||
+ | |||
+ | * [[http:// | ||
+ | * [[http:// | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | ===== Разное ===== | ||
+ | |||
+ | * http:// | ||
+ | * http:// | ||
+ | * http:// | ||
+ | * http:// | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// |