70 lines
4.1 KiB
Nginx Configuration File
70 lines
4.1 KiB
Nginx Configuration File
# Отдача статики тестового веба.
|
||
# Роутинг у нас hash-based (#/tickets), но на всякий случай любой
|
||
# несуществующий путь ведём на index.html — случайный 404 мешает отладке.
|
||
|
||
# Зоны лимитов лежат здесь (файл подключается в http-контексте через
|
||
# conf.d): 10 запросов/сек на IP и до 20 одновременных соединений.
|
||
# Браузеру с запасом хватает, а зациклившийся retry фронта упрётся
|
||
# в потолок, а не будет долбить статику бесконечно.
|
||
limit_req_zone $binary_remote_addr zone=perip:1m rate=10r/s;
|
||
limit_conn_zone $binary_remote_addr zone=addr:1m;
|
||
|
||
server {
|
||
listen 80;
|
||
server_name _;
|
||
root /usr/share/nginx/html;
|
||
index index.html;
|
||
|
||
gzip on;
|
||
gzip_types text/css application/javascript application/json;
|
||
gzip_min_length 1024;
|
||
|
||
# HSTS: по HTTP браузер заголовок игнорирует, поэтому локально он
|
||
# безвреден, а с TLS (домен и сертификат — при деплое) заставит
|
||
# браузер держать сайт только по https. includeSubDomains — потому
|
||
# что на одном домене будут и API, и фото-прокси.
|
||
# ВНИМАНИЕ: add_header на уровне server перекрывается ЛЮБЫМ
|
||
# add_header внутри location — поэтому в location / заголовки
|
||
# продублированы явно.
|
||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||
add_header X-Content-Type-Options "nosniff" always;
|
||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||
|
||
# burst — на пачку файлов при первой загрузке страницы (~5 запросов),
|
||
# сверх лимита — сразу 429, а не неопределённое ожидание.
|
||
limit_req zone=perip burst=30 nodelay;
|
||
limit_req_status 429;
|
||
limit_conn addr 20;
|
||
limit_conn_status 429;
|
||
|
||
# API на том же origin (BASE='' в js/api.js): проксируем API-пути
|
||
# бэкенда, остальное — статика. Regex-локация важнее prefix /.
|
||
# X-Forwarded-For ПЕРЕЗАПИСЫВАЕМ ($remote_addr), а не дополняем:
|
||
# gin берёт левый элемент и по нему считает лимиты и client_ip в
|
||
# логах — дописанный клиентом мусор останется левым элементом.
|
||
# local dev: бэкенд на хосту (host.docker.internal:8080);
|
||
# в проде адрес подставит app-nginx.prod.
|
||
location ~ ^/(auth|users|projects|objects|tickets|invitations|recurring|ping|db-ping|swagger)(/|$) {
|
||
proxy_pass http://host.docker.internal:8080;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $remote_addr;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
# Фотоотчёт: до 10 МБ + запас на multipart-обвязку.
|
||
client_max_body_size 12m;
|
||
}
|
||
|
||
location / {
|
||
try_files $uri $uri/ /index.html;
|
||
# Кэш мешает отладке: отдаём всегда свежее.
|
||
# add_header в этой локации перекрывает серверный (nginx не
|
||
# смешивает уровни) — заголовки дублируем здесь явно.
|
||
add_header Cache-Control "no-cache";
|
||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||
add_header X-Content-Type-Options "nosniff" always;
|
||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||
}
|
||
}
|