axe-web/nginx.conf
edadmin ca3392157a
Some checks are pending
web / check (push) Waiting to run
web / build-web (push) Waiting to run
web / deploy (push) Blocked by required conditions
feat: prod web image + Gitea Actions, demo chips removed
2026-10-18 22:44:06 +03:00

70 lines
4.1 KiB
Nginx Configuration File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Отдача статики тестового веба.
# Роутинг у нас 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;
}
}