78 lines
3.4 KiB
Plaintext
78 lines
3.4 KiB
Plaintext
# Бинго «Баланс 2.0» на своём поддомене (рекомендуемый вариант).
|
|||
|
|
# Положить в /etc/nginx/conf.d/bingo.conf (или sites-available + симлинк в sites-enabled),
|
||
|
|
# заменить bingo.example.com и пути к сертификату, затем: nginx -t && systemctl reload nginx
|
||
|
|
#
|
||
|
|
# Контейнер слушает 127.0.0.1:8080 на этом же хосте (HOST_BIND / HOST_PORT в .env).
|
||
|
|
|
||
|
|
# Ограничение частоты запросов к API. Адреса держатся только в памяти nginx и никуда не пишутся.
|
||
|
|
# Вся команда может выходить через один корпоративный NAT, поэтому запас большой:
|
||
|
|
# 25 человек дают около 1–2 запросов в секунду.
|
||
|
|
limit_req_zone $binary_remote_addr zone=bingo_api:1m rate=10r/s;
|
||
|
|
|
||
|
|
upstream bingo_app {
|
||
|
|
server 127.0.0.1:8080;
|
||
|
|
keepalive 8;
|
||
|
|
}
|
||
|
|
|
||
|
|
server {
|
||
|
|
listen 80;
|
||
|
|
listen [::]:80;
|
||
|
|
server_name bingo.example.com;
|
||
|
|
access_log off;
|
||
|
|
return 301 https://$host$request_uri;
|
||
|
|
}
|
||
|
|
|
||
|
|
server {
|
||
|
|
# nginx 1.25.1 и новее: можно писать «listen 443 ssl;» и отдельной строкой «http2 on;».
|
||
|
|
listen 443 ssl http2;
|
||
|
|
listen [::]:443 ssl http2;
|
||
|
|
server_name bingo.example.com;
|
||
|
|
|
||
|
|
ssl_certificate /etc/nginx/ssl/bingo.example.com/fullchain.pem;
|
||
|
|
ssl_certificate_key /etc/nginx/ssl/bingo.example.com/privkey.pem;
|
||
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||
|
|
ssl_session_cache shared:bingo_ssl:1m;
|
||
|
|
ssl_session_timeout 1d;
|
||
|
|
|
||
|
|
# Анонимность: не писать журнал доступа. В журнал ошибок nginx пишет адрес клиента,
|
||
|
|
# поэтому уровень crit — туда попадают только поломки самого nginx. Для отладки временно поставьте error.
|
||
|
|
access_log off;
|
||
|
|
error_log /var/log/nginx/bingo.error.log crit;
|
||
|
|
|
||
|
|
# Страница сама отдаёт CSP, nosniff, Referrer-Policy и т. д. Здесь добавляется только HSTS.
|
||
|
|
# ВАЖНО: не добавляйте X-Frame-Options — он запретит вкладку «Веб-сайт» в Teams.
|
||
|
|
# Встраивание уже ограничено заголовком CSP frame-ancestors от приложения.
|
||
|
|
add_header Strict-Transport-Security "max-age=31536000" always;
|
||
|
|
|
||
|
|
client_max_body_size 8k; # приложению хватает 2 КБ
|
||
|
|
gzip on;
|
||
|
|
gzip_types application/json text/css text/javascript;
|
||
|
|
|
||
|
|
location / {
|
||
|
|
proxy_pass http://bingo_app;
|
||
|
|
proxy_http_version 1.1;
|
||
|
|
proxy_set_header Host $host;
|
||
|
|
proxy_set_header Connection "";
|
||
|
|
# X-Forwarded-For намеренно не передаётся: приложению IP не нужен.
|
||
|
|
proxy_connect_timeout 5s;
|
||
|
|
proxy_read_timeout 15s;
|
||
|
|
}
|
||
|
|
|
||
|
|
location /api/ {
|
||
|
|
limit_req zone=bingo_api burst=40 nodelay;
|
||
|
|
limit_req_status 429;
|
||
|
|
limit_req_log_level warn;
|
||
|
|
|
||
|
|
proxy_pass http://bingo_app;
|
||
|
|
proxy_http_version 1.1;
|
||
|
|
proxy_set_header Host $host;
|
||
|
|
proxy_set_header Connection "";
|
||
|
|
proxy_connect_timeout 5s;
|
||
|
|
proxy_read_timeout 15s;
|
||
|
|
}
|
||
|
|
|
||
|
|
# Служебная проверка контейнера — снаружи не нужна.
|
||
|
|
location = /healthz {
|
||
|
|
return 404;
|
||
|
|
}
|
||
|
|
}
|