Nginx
Тестирование конфигурации:
sudo nginx -t
Перезапустить nginx с проверкой новой конфигурацией:
sudo nginx -s reload
Твики
Балансировка
Для активной проверки требуется модуль (не доступен в стандартном nginx): https://github.com/nginx-modules/nginx_upstream_check_module
FROM nginx:1.18.0-alpine
LABEL link1="https://github.com/nginx-modules/nginx_upstream_check_module"
RUN set -x \
&& tempDir="$(mktemp -d)" \
&& chown nobody:nobody $tempDir \
&& cd $tempDir \
&& wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" \
&& tar xzf nginx-${NGINX_VERSION}.tar.gz \
&& apk add --no-cache --virtual .build-deps gcc libc-dev make openssl-dev pcre-dev zlib-dev linux-headers curl gnupg libxslt-dev gd-dev geoip-dev git \
&& git clone --depth 1 https://github.com/nginx-modules/nginx_upstream_check_module nginx-${NGINX_VERSION}/nginx_upstream_check_module \
&& CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') \
&& CONFARGS=${CONFARGS/-Os -fomit-frame-pointer/-Os} \
&& cd nginx-$NGINX_VERSION \
&& patch -p1 < nginx_upstream_check_module/check_1.16.1+.patch \
&& ./configure --with-compat $CONFARGS --add-module=nginx_upstream_check_module \
&& make \
&& make install \
&& cd / \
&& rm -rf $tempDir \
&& apk del .build-deps \
&& rm -rf /var/cache/apk/* \
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]
Пример конфигурации с активной проверкой:
server_tokens off;
upstream docs {
least_conn;
server docs1.domain.com weight=10;
server docs2.domain.com;
check interval=5000 rise=1 fall=3 timeout=4000 type=http;
check_http_send "HEAD / HTTP/1.1\r\nHost: docs.domain.com\r\nUser-Agent: nginx\r\n\r\n";
}
server {
listen 80 default;
return 307 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name docs.domain.com;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location / {
proxy_pass http://docs;
}
ssl_protocols SSLv3 TLSv1.2 TLSv1.3;
ssl_certificate /ssl/domain.com.crt;
ssl_certificate_key /ssl/domain.com.key;
ssl_dhparam /ssl/dhparam.pem;
}
SSL
http://nginx.org/ru/docs/http/ngx_http_log_module.html#log_format
На уровне http (/etc/nginx/nginx.conf) в «# Logging Settings»:
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $request_length $request_time '
'$upstream_response_length $upstream_response_time '
'$upstream_status';
где:
$request_length – полный размер запроса, включая заголовки и тело, в байтах
$request_time – время обработки запроса, в миллисекундах
$upstream_response_length – длинна ответа полученного от отладочного сервера, в байтах
$upstream_response_time– время затраченное на получение ответа от отладочного сервера, в миллисекундах
$upstream_status – код статуса ответа от отладочного сервера
В необходимом месте добавляем:
access_log /var/log/nginx/application_access.log detailed;
https://habrahabr.ru/post/308880/ - NGINX: Перехват ошибок 5хх с помощью отладочного сервера
Модули
Модуль ngx_http_autoindex_module
Модуль ngx_http_autoindex_module обслуживает запросы, оканчивающиеся слэшом (‘/’), и выдаёт листинг каталога. Обычно запрос попадает к модулю ngx_http_autoindex_module, когда модуль ngx_http_index_module не нашёл индексный файл.
Пример конфигурации
location / {
autoindex on;
}
Директивы
синтаксис: autoindex on | off;
умолчание: autoindex off;
контекст: http, server, location
- разрешает или запрещает вывод листинга каталога.
синтаксис: autoindex_exact_size on | off;
умолчание: autoindex_exact_size on;
контекст: http, server, location
- определяет, как выводить размеры файлов в листинге каталога: точно или округляя до килобайт, мегабайт и гигабайт.
синтаксис: autoindex_localtime on | off;
умолчание: autoindex_localtime off;
контекст: http, server, location
- определяет, в какой временной зоне выводить время в листинге каталога: в локальной или в UTC.
http://nginx.org/ru/docs/http/ngx_http_autoindex_module.html
Модуль ngx_http_core_module
Директивы
синтаксис: connection_pool_size размер;
умолчание: connection_pool_size 1m;
контекст: http, server
- задаёт максимально допустимый размер тела запроса клиента, указываемый в поле “Content-Length” заголовка запроса. Если размер больше заданного, то клиенту возвращается ошибка 413 (Request Entity Too Large). Следует иметь в виду, что браузеры не умеют корректно показывать эту ошибку. Установка параметра размер в 0 отключает проверку размера тела запроса клиента.
http://nginx.org/ru/docs/http/ngx_http_core_module.html
Модуль ngx_http_access_module
Директивы
синтаксис: allow адрес | CIDR | unix | all;
умолчание: -
контекст: http, server, location, limit_except
Разрешает доступ для указанной сети или адреса. Если указано специальное значение unix: (1.5.1), разрешает доступ для всех UNIX-сокетов.
синтаксис: deny адрес | CIDR | unix | all;
умолчание: -
контекст: http, server, location, limit_except
Запрещает доступ для указанной сети или адреса. Если указано специальное значение unix: (1.5.1), запрещает доступ для всех UNIX-сокетов.
http://nginx.org/ru/docs/http/ngx_http_access_module.html
Docker
Пример запуска Nginx, в /data/docker/nginx/etc_nginx_conf.d должен существовать default.conf, приложение должно быть в /data/docker/nginx/var_www:
docker run -d -p80:80 --mount type=bind,src=/data/docker/nginx/etc_nginx_conf.d,dst=/etc/nginx/conf.d --mount type=bind,src=/data/docker/nginx/var_www,dst=/var/www/ --name nginx nginx:alpine
Пример для PHP:
server {
listen 80;
root /var/www;
index index.html index.php;
location ~ \.php$ {
fastcgi_pass mngt.domain.com:9000;
fastcgi_index index.php;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location = /favicon.ico {
log_not_found off;
}
}
https://hub.docker.com/_/nginx
nginx-spnego
FROM nginx:1.16.1-alpine
LABEL maintainer="domain" \
release-date="2020–02–09" \
link1="https://github.com/stnoonan/spnego-http-auth-nginx-module" \
link2="https://gist.github.com/hermanbanken/96f0ff298c162a522ddbba44cad31081" \
link3="https://github.com/fclmman/alpine-nginx-spnego/blob/master/Dockerfile"
RUN set -x \
&& tempDir="$(mktemp -d)" \
&& chown nobody:nobody $tempDir \
&& cd $tempDir \
&& wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" \
&& tar xzf nginx-${NGINX_VERSION}.tar.gz \
&& apk add --no-cache krb5 \
&& apk add --no-cache --virtual .build-deps gcc libc-dev make openssl-dev pcre-dev zlib-dev linux-headers curl gnupg libxslt-dev gd-dev geoip-dev git krb5-dev \
&& git config --global http.proxy $http_proxy \
&& git clone https://github.com/stnoonan/spnego-http-auth-nginx-module.git nginx-${NGINX_VERSION}/spnego-http-auth-nginx-module \
&& CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') \
&& CONFARGS=${CONFARGS/-Os -fomit-frame-pointer/-Os} \
&& cd nginx-$NGINX_VERSION \
&& ./configure --with-compat $CONFARGS --add-dynamic-module=spnego-http-auth-nginx-module \
&& make modules \
&& cp objs/ngx_http_auth_spnego_module.so /etc/nginx/modules/ \
&& sed -i -e '1 s/^/load_module \/etc\/nginx\/modules\/ngx_http_auth_spnego_module.so;\n/;' /etc/nginx/nginx.conf \
&& cd / \
&& rm -rf $tempDir \
&& apk del .build-deps \
&& rm -rf /var/cache/apk/* \
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]
ingress
Запустить:
Нажмите, чтобы отобразить
#docker
docker run -d -p443:443 -p80:80 \
-v /data/docker/nginx/conf:/etc/nginx/conf.d:ro \
-v /data/docker/nginx/ssl:/ssl:ro \
--name nginx nginx:stable-alpine
#docker-compose
docker-compose up -d
#swarm
docker service create -p 443:443 -p80:80 \
--mount type=bind,source=/data/docker/nginx/conf,destination=/etc/nginx/conf.d,readonly \
--mount type=bind,source=/data/docker/nginx/ssl,destination=/ssl,readonly \
--name nginx nginx:stable-alpine
docker stack deploy --compose-file docker-compose.yaml nginx
version: '3.7'
volumes:
conf:
driver_opts:
type: none
device: ${VOLPATH-/data/docker/nginx}/conf
o: bind
ssl:
driver_opts:
type: none
device: ${VOLPATH-/data/docker/nginx}/ssl
o: bind
services:
nginx:
image: nginx:stable-alpine
container_name: nginx
ports:
- mode: host
protocol: tcp
published: 80
target: 80
- mode: host
protocol: tcp
published: 443
target: 443
volumes:
- conf:/etc/nginx/conf.d:ro
- ssl:/ssl:ro
restart: always
k8s
default-ssl-certificate
limit_req
Ограничить кол-во запросов
Ограничить кол-во запросов
По 2r/s на 1 IP, с всплесками до 1 и общим по 4r/s с всплесками до 3 на определённый путь.
Обновить configmap в nginx, для helm:
--set controller.allowSnippetAnnotations=true \
--set controller.config.http-snippet='limit_req_zone $binary_remote_addr_map zone=ip_v3request:10m rate=2r/s;
map $request_uri $binary_remote_addr_map {
~*^/api/v3/Request $binary_remote_addr;
}
limit_req_zone $v3request_map zone=v3request:10m rate=4r/s;
map $request_uri $v3request_map {
~*^/api/v3/Request 1;
}'
и добавить в ingress сервиса:
ingress:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
limit_req zone=ip_v3request burst=1 nodelay;
limit_req zone=v3request burst=3 nodelay;
limit_req_status 429;
Ошибки
client intended to send too large body
В nginx/error.log. Необходимо увеличить размер connection_pool_size.
open() ".../favicon.ico" failed (2: No such file or directory)
В nginx/error.log. Добавляем в конфигурацию сайта:
location = /favicon.ico {
log_not_found off;
}
В nginx/error.log. Добавляем в конфигурацию сайта в блок с опцией fastcgi_pass:
fastcgi_buffers 16 32k;
fastcgi_buffer_size 32k;
либо в блок с опциями proxy_
proxy_buffer_size 64k;
proxy_buffers 4 128k;
proxy_busy_buffers_size 128k;
http://eddnet.org/?p=2121