70 lines
3.8 KiB
Plaintext
70 lines
3.8 KiB
Plaintext
# Прод-конфиг веба: статика + прокси API на контейнер api внутри сети
|
||
# compose (строка api резолвится docker- DNS). Порт наружу — 80, TLS
|
||
# терминалирует перед этим nginx (балансировщик / Caddy / Traefik).
|
||
#
|
||
# Отличия от dev nginx.conf:
|
||
# - proxy_pass http://api:8080 вместо host.docker.internal:8080;
|
||
# - security-заголовки (nosniff / frame / referrer) поверх HSTS.
|
||
#
|
||
# Хост, который не относится к нашему origin (Host-заголовок чужой),
|
||
# nginx отдаёт сюда же — server_name _; выделенного виртуального хоста
|
||
# под чужой домен нет, это осознанно.
|
||
|
||
# Зоны лимитов: 10 запросов/сек на IP и до 20 одновременных соединений.
|
||
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 — на пачку файлов при первой загрузке страницы, сверх
|
||
# лимита — сразу 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 в
|
||
# логах — дописанный клиентом мусор останется левым элементом.
|
||
location ~ ^/(auth|users|projects|objects|tickets|invitations|recurring|ping|db-ping|swagger)(/|$) {
|
||
proxy_pass http://api: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 в location перекрывает серверный.
|
||
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;
|
||
}
|
||
}
|