Files
zuevav f4bca8449e main
2026-05-20 19:33:02 +03:00

190 lines
6.1 KiB
Plaintext
Raw Permalink 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.
# ZBrain Nginx Configuration
# ===========================
# Два server-блока:
# 1. Внутренний (brain.zetit.local) - полный доступ к UI и API
# 2. Публичный (brain.zetit.ru) - только /mcp/* и /oauth/*
#
# Положить в /etc/nginx/sites-available/zbrain
# и сделать symlink в /etc/nginx/sites-enabled/
# ============================================================
# Upstream'ы
# ============================================================
upstream brainhub_api {
server 127.0.0.1:3000;
keepalive 32;
}
upstream brainhub_api_public {
server 127.0.0.1:3010;
keepalive 32;
}
upstream brainhub_web {
server 127.0.0.1:8080;
keepalive 32;
}
# Rate limiting для публичного MCP
limit_req_zone $binary_remote_addr zone=mcp_public:10m rate=30r/s;
limit_req_zone $http_authorization zone=mcp_token:10m rate=100r/s;
# ============================================================
# Внутренний контур: brain.zetit.local
# ============================================================
server {
listen 80;
listen [::]:80;
server_name brain.zetit.local;
# Внутри сети можно без HTTPS, либо self-signed cert
# Если нужен HTTPS - раскомментировать listen 443 ниже и убрать listen 80
access_log /var/log/nginx/zbrain-internal.access.log;
error_log /var/log/nginx/zbrain-internal.error.log;
client_max_body_size 50M;
# Web UI (статика)
location / {
proxy_pass http://brainhub_web;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# API
location /api/ {
proxy_pass http://brainhub_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
# Таймауты для долгих операций (sync, import)
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
# SSE events
location /api/events {
proxy_pass http://brainhub_api;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 24h;
# SSE headers
chunked_transfer_encoding off;
}
# MCP - внутренний доступ (тоже с токенами, но без rate limit)
location /mcp/ {
proxy_pass http://brainhub_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization $http_authorization;
proxy_read_timeout 120s;
proxy_buffering off;
}
}
# ============================================================
# Публичный контур: brain.zetit.ru
# ============================================================
server {
listen 80;
listen [::]:80;
server_name brain.zetit.ru;
# HTTP -> HTTPS redirect (кроме ACME challenge)
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name brain.zetit.ru;
# TLS
ssl_certificate /etc/letsencrypt/live/brain.zetit.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/brain.zetit.ru/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
access_log /var/log/nginx/zbrain-public.access.log;
error_log /var/log/nginx/zbrain-public.error.log;
client_max_body_size 10M;
# ВАЖНО: на публичном контуре доступны только /mcp/* и /oauth/*
# Никакого UI, API админки и т.д.
# MCP proxy с rate limiting
location /mcp/ {
# Лимит по IP - защита от подбора токенов
limit_req zone=mcp_public burst=60 nodelay;
# Лимит по токену - защита от взбесившегося скрипта
limit_req zone=mcp_token burst=200 nodelay;
limit_req_status 429;
proxy_pass http://brainhub_api_public;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization $http_authorization;
proxy_read_timeout 120s;
proxy_buffering off;
}
# OAuth flow для удалённой авторизации
location /oauth/ {
limit_req zone=mcp_public burst=20 nodelay;
proxy_pass http://brainhub_api_public;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Health check (без rate limit, для мониторинга)
location /health {
proxy_pass http://brainhub_api_public/health;
access_log off;
}
# Всё остальное - 404, чтобы публично ничего лишнего не светить
location / {
return 404;
}
}