Nginx для Angular SSR в FastPanel
Для чего нужен раздел
Эта страница нужна технической команде, когда iEXExchanger установлен со связкой:
frontend-домен example.com -> Angular SSR
backend/admin-домен app.example.com -> Laravel backend
browser API -> example.com/backend-api/*Обычная Laravel-настройка Nginx через public/index.php подходит для backend/admin-домена. Для основного клиентского frontend-домена нужна отдельная схема: Nginx проксирует Angular SSR на локальный Node-процесс и отдельно проксирует API в backend.
Базовая схема
Frontend-домен
https://example.com
Клиентский сайт обменника
Backend/admin-домен
https://app.example.com
Laravel, админка, API, платежные callback
Angular SSR
127.0.0.1:4000
Серверный рендер клиента
Browser API
/backend-api/*
Same-origin путь из браузера в backend
Backend upstream
https://app.example.com или origin IP с Host: app.example.com
Куда Nginx передает API
Socket/Reverb
обычно 127.0.0.1:8080 или backend-домен
Realtime-соединения
Почему /backend-api, а не прямой backend-домен
/backend-api, а не прямой backend-доменБраузер должен обращаться к API через основной домен:
https://example.com/backend-api/client-api/v1/...А Nginx уже внутри сервера передает запрос в backend:
Так frontend работает same-origin и не упирается в CORS. Backend при этом остается на своем домене, со своим PHP-FPM, cookies, middleware, callback и логикой Laravel.
Старый подход через /apis, alias на backend public и fastcgi_pass внутри frontend-домена лучше не использовать как основную схему. Он смешивает frontend и backend в одном server block и повышает риск ошибок с SCRIPT_FILENAME, fallback routes, cookies, hidden files и FastPanel include-ами. /apis можно оставить только временно как compatibility alias для старой frontend-сборки.
Что должно быть в Angular SSR .env
.envДля production FastPanel/PM2 схемы root .env frontend-проекта должен быть заполнен примерно так:
Важно:
PORT
Должен совпадать с Nginx upstream, обычно 4000
HOST
Для production на том же сервере обычно 127.0.0.1
ALLOWED_HOSTS
Только реальные frontend-домены клиента, не *
API_URL
Backend-origin для SSR, например https://app.example.com
CLIENT_CUSTOM_DIR
Внешняя папка /ng-custom/, которую Nginx отдает через alias
Не ставьте API_URL=/backend-api в root .env для PM2/FastPanel SSR. /backend-api - это путь браузера через Nginx, а SSR-серверу нужен backend-origin.
Что добавить вне server
serverВверху Nginx-конфига, до server { ... }, обычно нужны:
map $http_accept_language $accept_language
Выбор языка по браузеру
map $cookie_lang $selected_lang
Выбор языка по cookie
map $http_upgrade $connection_upgrade
WebSocket upgrade
upstream frontend_ssr
Локальный Angular SSR, обычно 127.0.0.1:4000
upstream backend_https
Backend-домен или origin IP backend-домена
Если у клиента включены только ru,en, языки в map и regex должны совпадать с реальными языками проекта.
Что должно быть внутри server frontend-домена
server frontend-доменаВнутри server block FastPanel оставьте SSL, root, index, set $root_path, disable_symlinks и другие служебные строки панели. После этого добавляются рабочие правила frontend-схемы.
add_header Vary "Accept-Language, Cookie" always
Корректное кеширование языковых страниц
client_max_body_size 64m
Чтобы загрузки документов/файлов не падали с 413
set $backend_domain app.example.com
Backend Host/SNI для proxy
location = /
Редирект на язык по умолчанию или выбранный язык
static location для JS/CSS/assets
Должен стоять выше locale SSR location
locale SSR location
Проксирует /ru/..., /en/... и другие языки в Angular SSR
location ^~ /ng-custom/
Отдает клиентские вставки без долгого кеша
location ^~ /backend-api/
Проксирует browser API в backend
aliases /images, /storage, /static, /dist, /exports
Отдают публичные backend-файлы с frontend-домена
location ^~ /app/ и /apps/
Нужны, если socket/Reverb идет через основной домен
Главное правило по static location
Static location должен стоять выше языкового SSR location.
Иначе файлы вроде /ru/main-*.js и /ru/styles-*.css могут получить языковые cookies/headers и плохо кешироваться через Cloudflare или браузер.
Ожидаемо для hashed JS/CSS:
/ng-custom/
/ng-custom/Для production не используйте:
Это только Angular dev server.
Production-папка должна быть внешней, например:
Nginx должен отдавать ее через alias, а SSR должен читать ее через CLIENT_CUSTOM_DIR. Для /ng-custom/ нужен Cache-Control: no-store, чтобы клиентские вставки, verification meta, пиксели или сторонние скрипты обновлялись без пересборки Angular.
/backend-api/
/backend-api/Canonical API location:
В proxy важно сохранить:
proxy_ssl_server_name on
Корректный SNI для HTTPS backend
proxy_ssl_name $backend_domain
Backend получает правильное имя
proxy_set_header Host $backend_domain
Laravel видит backend-домен
X-Forwarded-Host $host
Backend знает публичный frontend host
X-Forwarded-Proto $scheme
Корректные HTTPS-ссылки
proxy_cookie_domain
Cookie backend корректно работают на frontend-домене
Если /backend-api/client-api/v1/ping возвращает HTML от Angular, значит API location не сработал и запрос ушел в SSR fallback.
Если backend отвечает редиректом на /ru/client-api/..., часто причина в неправильном Host для backend proxy.
Публичный API /api/v3
/api/v3Если новый публичный Exchanger API должен быть доступен same-origin с frontend-домена, его тоже можно проксировать через Nginx:
Он должен уходить в backend upstream с корректным backend Host/SNI, как и /backend-api.
Socket/Reverb
Если backend /start отдает socket host основного домена и порт 443, на frontend-домене нужны proxy-блоки:
Они должны передавать Upgrade и Connection headers и иметь длинные proxy_read_timeout / proxy_send_timeout, обычно до 3600s.
Если socket остается на backend-домене или отдельном порту, эти блоки на frontend-домене могут быть не нужны, но backend-домен и firewall должны быть настроены корректно.
Проверка после настройки
Минимальные проверки:
Что должно быть:
nginx -t
Конфиг валиден
/backend-api/...
Backend JSON или backend-статус, не Angular HTML
/dist/assets/...
Файл открывается с frontend-домена
/ru/
Страница SSR открывается
127.0.0.1:4000/ru/ с Host
SSR отвечает локально
Browser DevTools
Нет запросов на https://app.example.com/client-api/...
Частые ошибки
API_URL=/backend-api в SSR .env
SSR не знает backend-origin
Указать https://app.example.com
ALLOWED_HOSTS=*
Angular предупреждает о риске host validation
Указать реальные frontend-домены
/ng-custom/ проксируется на localhost:4200
Production зависит от dev server
Использовать alias на runtime-папку
Старый /apis остался основным API
Смешиваются frontend и backend правила
Перейти на /backend-api, /apis оставить временно
/backend-api отдает Angular HTML
Nginx location не совпал или стоит ниже fallback
Поднять API location выше fallback и проверить proxy_pass
Backend редиректит на /ru/client-api/...
Backend получил неверный Host
Проверить proxy_set_header Host и proxy_ssl_name
Static JS/CSS получает cookie
Static location ниже языкового SSR location
Переставить static location выше
413 при загрузке
Малый client_max_body_size
Увеличить, обычно до 64m или по требованиям проекта
Что отвечать в AI-чате
"Как настроить Nginx для frontend?"
"Frontend-домен проксирует Angular SSR на 127.0.0.1:4000, а API должен идти через /backend-api в backend-домен. Backend Laravel остается на отдельном домене с PHP-FPM 8.4."
"Почему API дает CORS?"
"Браузер должен ходить на https://frontend-domain/backend-api/..., а не напрямую на backend-домен. Проверьте API_URL, frontend build и Nginx proxy."
"Почему /backend-api открывает сайт, а не API?"
"Nginx не попал в API location. Проверьте порядок location: /backend-api/ должен быть выше SSR fallback."
"Что писать в API_URL?"
"Для SSR .env пишите backend-origin, например https://app.example.com. /backend-api нужен браузеру через Nginx, а не SSR-серверу."
"Можно оставить /apis?"
"Только временно для старой frontend-сборки. Новая каноническая схема - /backend-api."
Связанные разделы
Последнее обновление
Это было полезно?