Files
AndreyandClaude Opus 5 a321109a8f 🐛 fix(gateway): установка на нестандартном порту принимает формы
Шлюз передавал дальше Host без порта ({host} в Caddy, $host в nginx). Браузер
при этом шлёт Origin с портом, и CSRF-проверка Django отвергала любой POST на
установке, опубликованной как ip:8081: «Origin checking failed».

Теперь Host уходит с портом. X-Forwarded-Proto и X-Forwarded-For Caddy
принимает от прокси из частных сетей — установку часто ставят за прокси
панели, который снимает TLS и ходит к шлюзу по http; без этого CSRF падал бы
снова, как только перед установкой появлялся https.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 11:32:25 +03:00

102 lines
4.0 KiB
Plaintext

# Имена сервисов разрешаются на каждом запросе через DNS Docker, а не один
# раз при старте nginx: после пересоздания контейнера (compose up, обновление
# образа) адрес меняется, и закэшированный IP уводил бы трафик на другой
# сервис. Для этого upstream задан переменной — с ней nginx резолвит заново
# по истечении valid.
# Vite HMR ходит по websocket на тот же origin, что и приложение, поэтому
# location / должен уметь апгрейдить соединение. Обычные запросы при этом
# закрывают connection как раньше.
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
server {
listen 80;
server_name app.localhost localhost *.localhost;
resolver 127.0.0.11 valid=10s ipv6=off;
set $backend_app backend-app:8000;
set $web_chat web-chat:5175;
set $frontend frontend:5173;
location = /admin {
return 404;
}
location /admin/ {
return 404;
}
location /api/ {
proxy_pass http://$backend_app;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /ws/ {
proxy_pass http://$backend_app;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
location = /chat-widget.js {
proxy_pass http://$backend_app;
proxy_set_header Host $http_host;
}
location /chat/ {
# Vite React Refresh injects an inline preamble in local development.
add_header Content-Security-Policy "default-src 'self'; connect-src 'self' ws: wss:; img-src 'self' data:; media-src 'self' blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none'; base-uri 'self'; frame-ancestors *" always;
proxy_pass http://$web_chat;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /calls/ {
# Vite injects the React Refresh preamble inline in development. Production
# uses the strict policy from frontend.production.conf.
add_header Content-Security-Policy "default-src 'self'; connect-src 'self' ws: wss:; img-src 'self' data:; media-src 'self' blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
add_header Permissions-Policy "camera=(self), microphone=(self)" always;
rewrite ^ /chat/call.html break;
proxy_pass http://$web_chat;
proxy_set_header Host $http_host;
}
location / {
# Vite React Refresh injects its development preamble inline. This policy is
# local-only; production keeps the strict CSP from the canonical gateway.
add_header Content-Security-Policy "default-src 'self'; connect-src 'self' ws: wss:; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always;
add_header X-Frame-Options SAMEORIGIN always;
proxy_pass http://$frontend;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name platform.localhost;
resolver 127.0.0.11 valid=10s ipv6=off;
set $backend_platform backend-platform:8000;
location /api/ {
proxy_pass http://$backend_platform;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
return 404;
}
}