Базовые фичи Nginx - SUPERCOMPTEAM/NeuroModule GitHub Wiki
Это конспект лекций отсюда: https://www.youtube.com/watch?v=dHsv8EnhSgQ&list=PLhgRAQ8BwWFa7ulOkX0qi5UfVizGD_-Rc
Nginx - в первую очередь обратный прокси-сервер (не совсем web-сервер)
vs Apache:
Apache - по умолчанию prefork: каждый процесс обрабатывает 1 запрос за одну единицу времени Nginx - асинхронная архитектура. Может обрабатывать несколько запросов однвременно. Все запросы к динамическому контенту передается через другие процессы (нельзя встраивать серверные ЯП в свои процессы)
Nginx меньше веcит чем Apache. Nginx работает со статическими ресурсами. Хорошо настроенный сервер nginx будет более эффективным и менее требовательным к ресурсам чем Apache.
Установка
sudo apt-get install nginx
/etc/nginx/ - файлы конфигурации nginx
service nginx status - просмотр текущего состояния nginx
Сборка из исходного кода
wiki/install/mainline
sudo apt-get install libpcre3 libpcre3-dev libssl-dev zlib1g-dev - либы
./configure --sbin-path=/usr/bin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-debug --with-pcre --with-http_ssl_module
https://www.nginx.com/resources/wiki/start/topics/tutorials/installoptions/ - флаги компиляции
Термины
Контекст (context) - разделы в файлах конфигурации, в котором используются директивы (http, server итд). самый верхний - файл конфигурации. в нем настраиваются опции мастер-процесса
Директивы (directives) - конкретные опции конфигурации. состоят из имени опции и значения опции (listen 80 - директива)
файл конфигурации /etc/nginx/nginx.conf
блок server - vhost, внутри контекста http, связан с одним хостом - доменом (поддоменом, ip-адресом). Порт, который будет прослушивать этот хост - по умолчанию порт 80. отсюда listen 80; server_name - домен, поддомен или ip, для которого существует этот хост. root /path - корневая папка с сайтом, статику которого раздаем на сервере.
service nginx reload - перезагрузить конфигурацию nginx. Команда не приведет к остановки nginx. restart - перезапускает.
curl -I позволяет посмотреть mime.type (text/plain - тип контента)
Контекст types. Например используя text/html html можно указать, что ко всем файлам с расширением html применим тип контента text/html. По умолчанию nginx уже подставляет тип контента к определенным расширениям файлов: include mime.types. этот файл лежит в /etc/nginx и в нем есть контекст types.
все это в контексте http.
самый тупой nginx.conf:
events {
}
http {
include mime.types;
server {
listen 80;
root /sites;
}
}
блоки location - самые часто используемые
location - ссылки после домена. внутри server. В нем например можно написать return 200 'ok'. 200 - код возврата. здесь используется совпадение префикса - странички /site и /sitefwe и /site/1 отрисуют одно и то же. чтобы это выключить, напишем равно после слова location.
Регулярные выражения: ~ после location Чтобы убрать чувствительность к регистру: *~ после location location ^~ - более высокий приоритет чем регулярные выражению. но у location = самый высокий приоритет
try_files $uri =404; - ищем файл в папке root:
events {
}
http {
include mime.types;
server {
listen 80;
root /sites;
location /obama {
root /sites;
try_files $uri =404;
}
}
}
Логирование
директория /var/log/nginx. там есть access.log и error.log Контекст наследуется от родительского контекста. Поэтому в контекст location можем добавить чтобы например ошибки контекста логировались в другой файл: error-log /path. Флаг debug позволит получать больше информации об ошибке.
Существует несколько уровней логирования. Подробнее: http://wiki.nginx.org/CoreModule#error_log
Отключить логирование в location:
access_log off;
error_log off;
обычно логирование access_log не нужно вести к статическим файлам типа css
Наследование и типы директив
типы директив:
- стандартный (standart)
- массивы (array)
- действия (action)
- try_files
Стандартная директива например gzip on. В контексте и в его подконекстах gzip будет включен.
Директива массив (например access_log) - работает так же, как стандартная, но можно переопределять в одном контексте несколько раз с разными значениями.
При наследовании стандартных директив и директив массивов в дочернем контексте они полностью перезаписывают логику директив в родительском контексте (одной строкой).
Директива действие (например rewrite). Активируется при вызове. Также примером может служить директива return. В директивах действиях наследование не работает, т.к. поток прирывается действием.
переменные в nginx: http://nginx.org/ru/docs/varindex.html
try_files. Не наследуется. Пример:
try_files x y z; - сперва пробует x, потом y, потом z
Настройка воркеров
Директива worker_processes отвечает за то, сколько workers. Надо указывать число, равное количеству ядер на сервере. Если установить worker_processes auto, то кол-во процессов установится равным кол-ву ядер. По умолчанию стоит 1 (одно ядро)
nproc - кол-во ядер lscpu - информация по процессору
В контексте events есть директива worker_connections. Это то, сколько подключений обрабатывает 1 worker процесс. стоит указать число, которое выдаст команда ulimit -n. В контексте events директива multi_accept on позволит одновременно принимать все новые подключения. Иначе он будет принимать только одно подключение за единицу времени.
В контесксте http:
charset utf-8 - кодировка по умолчанию utf-8
open_file_cache max=1000 inactive=20s'; - настройки кеширования файлов open_file_cache_valid 30s; open_file_cache_errors on;
Настройки буферов client_body_buffer_size 16k; - размер буфера POST-запроса, получаемого от клиента client_header_buffer_size 1k; - размер буфера заголов client_max_body_size 8m; - максимльный размер тела запроса клиента client_header_buffers 2 1k; - размер и максимально большой размер заголовов
Сколько секунд ждать после получения client_body и client_header: client_body_timeout 12; client_header_timeout 12;
keepalive_timeout 300; - время сколько держим подключения открытыми (в мс)
send_timeout 10; - макс. кол-во времени (с), через которое соединение будет закрыто
Контекст types указывается после include mimetypes для указания отдельных типов контента.
Директива add_header:
- Директива-массив
- Добавляет кастомный заголовок в ответ
Динамические модули nginx v.1.9.11
./configure --help - просмотреть все модули. Если в конце флага =dynamic, то модуль поддерживает динамику
Expires (заголовки)
Используются для оптимизации скорости загрузки.
expires 1M; - (1M - 1 месяц; d - days итд.) уменьшение времени загрузки странички в браузере. Говорит браузеру кешировать определенные ресурсы определенное кол-во времени. При след загрузке страницы браузеру не нужно запрашивать кешированный файл - берет его из кеша.
кешировать со стороны клиента можно: статические css или js файлы.
можно указать expires max; - но это плохо
директивы add_header Pragma public; и add_header Cashe-control public; - сообщают браузеру что файлы можно кешировать любым способом. add_header Vary Accept-Encoding; -
Сжатие данных Gzip
Accept-Encoding: gzip,deflate; - флаг для curl -I для скачивания сжатого файла
gzip on; - директива для подключения gzip gzip_min_length 100; - минимальная длина файла, с которой начинать сжатие. в байтах. gzip_comp_level 3; - чем больше число, тем больше степень сжати; оптимально 2-4. gzip_types text/plaun; - выбор типа файлов к которым применять сжатие. gzip_disable "msi6"; - отключение gzip для определенных браузеров
FastCgi Cache
бенчмарк apache: ab -n 100 -c 10 http://ip - для оценки скорости сервера
директивы для активации кеша fastCgi:
В контексе http:
-
указывем где будут храниться файлы кеша (/tmp очищается при перезагрузке сервера. 1:2 - это уровень подпапок. key_zone - то как мы будем обращаться к микро кешу): fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=microcache:10m max_size=500m; - max_size равняется кол-ву оперативной памяти по умолчанию
-
указываем в каком формате будем хранить кеш fastcgi_cache_key "$scheme$request_method$host$request_uri" (http/https, get/post)
В блоке location:
fastcgi_cache microcache; - имя (параметр) keyzone, который указали при создании fastcgi_cache_valid 200 60m - код ответа и максимальное время хранения кеша
Ограничение кол-ва запросов на сервер
2 способа:
- Ограничить число параллельных соединений
В контексте http:
limit_conn_zone $server_name zone=per_vhost:5m; - ограничение числа параллельных соединений в блоке сервера per_vhost=размер памяти зоны limit_conn_zone $binary_remote_addr zone=per_ip:5m; - ограничиваем относительно ip-адреса.
это мы просто выделили память. Для реализации спускаемся в location:
location ... {
limit_conn per_ip 1; # только 1 соединение за раз
}
При этом то что только одно соединение за раз не означает, что сервер при множестве параллельных соединений выберет одно из них. Вместо этого будет сбой работы сервера и запросы вернутся с кодом отличным от 200. Таким образом можно защитить свой сервер от атаки параллельными соединениями.
- Ограничить число одновременных подключений
В контексте http:
limit_req_zone $binary_remote_addr zone=one_per_sec:5m rate=1r/s; - 1 запрос в секунду
location ... {
limit_req zone=one_per_sec burst=5; # размер буфера
}
Стриминг видео
Модуль mp4 - не устанаавливается по умолчанию. Нужно указать --with_http_mp4_module. Можно контролировать скорость передачи ответа клиенту и размер буффера.
location ~ \.mp4$ {
root /root/;
mp4; # определение модуля
mp4_buffer_size 4M;
mp4_max_buffer_size; # размер буфера не больше этого (иначе 500)
}
Http2
- Бинарный протокол
- Сжатие заголовков
- Постоянные соединение
- Мультиплексные потоки
- Server PUSH
В HTTP1 несколько скриптов в 1 файл. Для установки соединения между клиентом и сервером требуется каждый раз отправлять заголовки в обе стороны.Также существует ограничение на максимальное кол-во соединений между клиентом и сервером. В http1 за 1 соединение передаем только 1 файл. В http2 - нет. Если поддерживаются серверные PUSH, сервер выдаст сразу всю необходимую информацию.
--with-http_v2_module --with-http_ssl_module (http 2 только с ssl)
http {
# HTTPS server
server {
listen 443 ssl http2; # просто добавляем сюда http2 чтобы работать с ним
server_name localhost;
ssl_certificate /path/to/cert.pem; # сертификат
ssl_certificate_key /path/to/cert.key; # ключ
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers off; # Стандартная директива шифрования
location / {
root html;
index index.html index.htm;
}
}
}
SSL
генерация ключей
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /path/to/nginx.key -out /path/to/nginx.crt
файл выше отражает использование ssl в nginx. ток http2 можно убрать
Auth
sudo apt-get install apache2-utils
sudo htpasswd -c /etc/nginx/.htpassw name # Пароль
location ... {
auth_basic "Restricted Content"; # ограниченный контент
auth_basic_user_file /path/to/.htpassw;
}
Повышение безопасности сервера
- Удалить ненужный функционал. Для этого не будем компилировать неиспользуемые стандартные модули:
./configure --help | grep without # Список стандартных модулей, которые можем исключить
./cotfigure --without=http_autoindex_module # Компилируем без авто-index.html модуля
- Отключение серверных токенов.
С помощью этого можем удалить всю информацию о том, какая версия nginx используется на сервере.
В контексте http:
server_tokens off;
- Задание размера буфферов. Против атаки "переполнение буффера"
В контексте http:
client_body_buffer_size 16k;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
- Блокировка User-Agent-ов
В контексте http:
if ($http_user_agent ~* badbot) { # или $http_referer
return 403;
}
- Настройка X-Frame-Options
add_header X-Frame-Options SAMEORIGIN; # только с одного домена
SSL сертификаты Let's Encrypt
Let's Encrypt - бесплатные автоматически созданные SSL-сертификаты. Cert bot. Выдает сертификаты только на домены.
генерация сертификатов:
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
инструменты certbot:
certbot --nginx # сам добавит https в nginx.conf
certbot certonly -d domain.com # если хотите пропустить установку
certbot renew --dry-run # обновить вручную
crontab -e # открыть файл cron
# in cron
@daily certbot renew
crontab -l # просмотр cron файла
events {}
http {
server {
listen 80;
server_name domain.com;
location / {
return 200 "Hello world";
}
}
}
Обратный прокси и балансировщик
прямое назначение nginx не web-сервер, а обратный прокси-сервер и балансировщик.
nginx -c /path/to/nginx.conf # Запустить сервер nginx из конкретной конфиги
Прокси
Обратный прокси-сервер выступает посредником между клиентом и вышестоящим (upstream) сервером. чаще всего это backend-сервисы.
events {}
http {
server {
listen 8000;
location /service {
proxy_pass 'http://localhost:8001/'; # тут обязателен слеш в конце
}
}
}
Если не укажем путь до прокси, nginx будет использовать оригинальный путь, указанный в location. Поэтому в конце лучше добавить /.
При проксировании можно добавлять кастомные заголовки, идущие либо к серверу, либо к клиенту с прокси-сервера.
events {}
http {
server {
listen 8000;
location /service {
add_header Header: header; # Кастомный заголовок клиенту
proxy_set_header Header: header; # Кастомный заголовок проксируемому серверу
proxy_pass 'http://localhost:8001/'; # тут обязателен слеш в конце
}
}
}
Балансировщик
Балансировщик нагрузки должен распределять запросы по нескольким серверам, снижая нагрузку на конкретные серверы. Также он обеспечивает избыточность: если 1 из серверов отвалится, балансировщик переправит запросы на остальные доступные серверы. Распределение = перенаправление = проксирование.
upstream - контекст, в котором сгруппированы несколько серверов. Чаще всего они обрабатывают одни и те же запросы и выдают одинаковый результат.
events {}
http {
upstream servers {
ip_hash; # Поведение балансировщика, м.б. ip_hash, least_conn и т.д.
server localhost:8001;
server localhost:8002;
server localhost:8003;
}
server {
listen 8000;
location / {
proxy_pass 'http://servers';
}
}
}
-
Round-robin - поведение при распределении запросов, при использовании которой nginx по-очереди отправляет запросы каждому серверу (иногда порядок нарушается). Если убить один из серверов, round-robin перестанет на него посылать запросы. При запуске, сервер снова включается в round-robin.
-
ip hash или Sticky Sessions - запросы привязываются к ip-адресам пользователей и по возможности для одного пользователя проксируются на один сервер. В случае падения сервера запросы от этого пользователя будут проксироваться на другой. При восстановлении они снова начнут передаваться на восстановленный сервер.
-
least_conn - nginx не отправляет запросы на серверы, у которых активное соединение.