> For the complete documentation index, see [llms.txt](https://docs.iexexchanger.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.iexexchanger.com/get-started/ustanovka/nastroika-fastpanel/nastroika-nginx.md).

# Настройка Nginx

На данном этапе необходимо настроить Nginx для корректной работы Frontend и Backend частей iEXExchanger.

Nginx отвечает за обработку входящих запросов, работу Angular SSR, передачу API-запросов в Backend, отдачу статических файлов, языковые маршруты и WebSocket-соединения.

В рамках данного раздела будут настроены:

* Nginx для основного домена Frontend;
* Nginx для технического поддомена Backend;
* проксирование Angular SSR на порт `4000`;
* передача API-запросов через `/backend-api`;
* доступ к статическим файлам Backend;
* поддержка WebSocket/Reverb.

## Перед началом

Перед выполнением данного этапа убедитесь, что:

* основной домен `ваш_домен` создан в FastPanel;
* технический поддомен `app.ваш_домен` создан в FastPanel;
* SSL-сертификаты настроены для обоих доменов;
* Frontend загружен и настроен;
* Backend загружен и настроен;
* Backend работает через PHP-FPM;
* рабочая директория Backend указана как `public`;
* у вас есть доступ к FastPanel.

***

## Что необходимо заменить в конфигурации

Перед добавлением конфигурации замените шаблонные значения на реальные данные вашего проекта.

| Значение                    | Что указать                                   |
| --------------------------- | --------------------------------------------- |
| `ваш_домен`                 | основной домен обменника                      |
| `app.ваш_домен`             | технический поддомен Backend                  |
| `имя_пользователя_frontend` | пользователь основного домена в FastPanel     |
| `имя_пользователя_backend`  | пользователь поддомена Backend в FastPanel    |
| `BACKEND_ORIGIN_IP`         | IP-адрес сервера, на котором работает Backend |

Пример:

```
ваш_домен: example.com
app.ваш_домен: app.example.com
имя_пользователя_frontend: example_com_usr
имя_пользователя_backend: app_example_com_usr
BACKEND_ORIGIN_IP: 123.123.123.123
```

{% content-ref url="/spaces/YuqSN6CIJoIeh8EPb0uE/pages/1l6h1Oe73cxdYfGUwqH8" %}
[Как найти путь к проекту и имя пользователя в FastPanel?](/pomosh-i-spravka/infrastruktura/kak-naiti-put-k-proektu-i-imya-polzovatelya-v-fastpanel.md)
{% endcontent-ref %}

***

## Настройка Nginx для Backend

Backend работает на техническом поддомене: `app.ваш_домен`

На стороне Backend необходимо оставить стандартную Laravel-конфигурацию FastPanel и добавить только настройку WebSocket/Reverb.

{% stepper %}
{% step %}

### Открытие ручной настройки Backend

В панели управления FastPanel перейдите в раздел: **«Сайты» — «app.ваш\_домен»**

Откройте раздел **«Ручная настройка».**

Перейдите во вкладку **«Frontend».**
{% endstep %}

{% step %}

### Поиск стандартного PHP-блока

В конфигурации Backend найдите блок:

```nginx
location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass unix:/var/run/app.ваш_домен.sock;
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    fastcgi_param DOCUMENT_ROOT $realpath_root;
}
```

В реальной конфигурации FastPanel домен в сокете будет вашим, например:

```nginx
fastcgi_pass unix:/var/run/app.example.com.sock;
```

{% endstep %}

{% step %}

### Добавление WebSocket/Reverb

Сразу после PHP-блока добавьте:

```nginx
location ^~ /app/ {
    proxy_http_version 1.1;
    proxy_set_header Host $http_host;
    proxy_set_header Scheme $scheme;
    proxy_set_header SERVER_PORT $server_port;
    proxy_set_header REMOTE_ADDR $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";

    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;

    proxy_pass http://0.0.0.0:8080;
}
```

После добавления блока нажмите кнопку **«Сохранить».**
{% endstep %}

{% step %}

### Что делает настройка Backend

Данная настройка проксирует WebSocket-соединения к Laravel Reverb.

Она нужна для работы:

* realtime-уведомлений;
* онлайн-статусов;
* динамических событий;
* обновлений в административной панели;
* функций, использующих WebSocket.
  {% endstep %}
  {% endstepper %}

## Настройка Nginx для Frontend

Frontend работает на основном домене: `ваш_домен`

На стороне Frontend необходимо заменить стандартную FastPanel-конфигурацию, которая по умолчанию проксирует сайт на `127.0.0.1:81`, на конфигурацию для Angular SSR.

{% stepper %}
{% step %}

### Открытие ручной настройки Frontend

В панели управления FastPanel перейдите в раздел: **«Сайты» — «ваш\_домен»**

Откройте раздел **«Ручная настройка».**

Перейдите во вкладку **«Frontend».**
{% endstep %}

{% step %}

### Блоки вне server

В самый верх конфигурации, до блока `server`, добавьте:

```nginx
map $http_accept_language $accept_language {
    "~*ru" ru;
    "~*en" en;
    default ru;
}

map $cookie_lang $selected_lang {
    "~^(ru|en)$" $cookie_lang;
    default $accept_language;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' '';
}

upstream iex_frontend_ssr {
    server 127.0.0.1:4000;
    keepalive 32;
}

upstream iex_backend_https {
    server BACKEND_ORIGIN_IP:443;
    keepalive 32;
}
```

Если в вашем проекте используются дополнительные языки, добавьте их в оба блока `map` и во все языковые `location`.

Например, для языков `ru`, `en`, `uk`, `ka`:

```nginx
map $http_accept_language $accept_language {
    "~*ru" ru;
    "~*en" en;
    "~*uk" uk;
    "~*ka" ka;
    default ru;
}

map $cookie_lang $selected_lang {
    "~^(ru|en|uk|ka)$" $cookie_lang;
    default $accept_language;
}
```

Также ниже в конфигурации нужно заменить: `(ru|en)` на `(ru|en|uk|ka)`
{% endstep %}

{% step %}

### Настройка Gzip

Внутри стандартной конфигурации найдите строку:

```nginx
gzip_comp_level 1;
```

Замените её на:

```nginx
gzip_comp_level 5;
```

Это улучшит сжатие статических файлов и уменьшит объём передаваемых данных.
{% endstep %}

{% step %}

### Настройки внутри server

Внутри блока `server` найдите строку:

```nginx
disable_symlinks if_not_owner from=$root_path;
```

Сразу после неё добавьте:

```nginx
add_header Vary "Accept-Language, Cookie" always;
client_max_body_size 64m;

set $backend_domain app.ваш_домен;
set $backend_cookie_domain .ваш_домен;
set $backend_public_path /var/www/имя_пользователя_backend/data/www/app.ваш_домен/public;
```

Пример:

```nginx
add_header Vary "Accept-Language, Cookie" always;
client_max_body_size 64m;

set $backend_domain app.example.com;
set $backend_cookie_domain .example.com;
set $backend_public_path /var/www/app_example_com_usr/data/www/app.example.com/public;
```

{% endstep %}

{% step %}

### Удаление стандартных FastPanel location-блоков

В конфигурации основного домена удалите стандартные блоки:

```nginx
location / {
    proxy_pass http://127.0.0.1:81;
    proxy_redirect http://127.0.0.1:81/ /;
    include /etc/nginx/proxy_params;
}

location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpeg|avi|zip|gz|bz2|rar|swf|ico|7z|doc|docx|map|ogg|otf|pdf|ttf|tif|txt|wav|webp|woff|woff2|xls|xlsx|xml)$ {
    try_files $uri $uri/ @fallback;
}

location @fallback {
    proxy_pass http://127.0.0.1:81;
    proxy_redirect http://127.0.0.1:81/ /;
    include /etc/nginx/proxy_params;
}
```

Если в конфигурации есть старые блоки `/apis`, их также необходимо удалить:

```nginx
location /apis {
    index index.php index.html index.htm;
    alias /var/www/имя_пользователя_backend/data/www/app.ваш_домен/public;
    try_files $uri $uri/ @apis;
}

location @apis {
    rewrite ^/apis/(.*)$ /apis/index.php?/$1 last;
}
```

В новой конфигурации используется путь: `/backend-api`
{% endstep %}

{% step %}

### Добавление новой конфигурации Frontend

Внутри блока `server` добавьте следующий набор `location`-блоков:

```nginx
location = / {
    return 302 /$selected_lang/$is_args$args;
}

location ~ ^/(ru|en)$ {
    add_header Vary "Accept-Language, Cookie" always;
    add_header Set-Cookie "lang=$1; Path=/; Max-Age=31536000; SameSite=Lax" always;
    return 302 /$1/$is_args$args;
}

location ~* ^/(assets/|theme/|.*\.(?:js|css|map|ico|txt|xml|json|csv|pdf|webmanifest|woff|woff2|ttf|otf|svg|png|jpg|jpeg|gif|webp|avif))$ {
    proxy_pass http://iex_frontend_ssr;

    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-Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;

    expires 1y;
    add_header Cache-Control "public, max-age=31536000, immutable" always;
    access_log off;
}

location ~ ^/(ru|en)/ {
    add_header Vary "Accept-Language, Cookie" always;
    add_header Set-Cookie "lang=$1; Path=/; Max-Age=31536000; SameSite=Lax" always;

    proxy_pass http://iex_frontend_ssr;
    proxy_redirect off;

    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-Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    proxy_buffering on;
    proxy_buffers 16 64k;
    proxy_buffer_size 128k;
    proxy_read_timeout 60s;
    proxy_connect_timeout 10s;
    proxy_send_timeout 10s;
}

location ^~ /ng-custom/ {
    alias /var/www/имя_пользователя_frontend/data/www/ваш_домен/public/ng-custom/;
    try_files $uri =404;

    expires -1;
    add_header Cache-Control "no-store, no-cache, must-revalidate" always;
    access_log off;
}

location = /backend-api {
    return 308 /backend-api/;
}

location ^~ /backend-api/ {
    proxy_pass https://iex_backend_https/;
    proxy_ssl_server_name on;
    proxy_ssl_name $backend_domain;
    proxy_http_version 1.1;

    proxy_set_header Host $backend_domain;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_cookie_domain $backend_domain $backend_cookie_domain;

    proxy_buffering off;
    proxy_read_timeout 60s;
    proxy_connect_timeout 10s;
    proxy_send_timeout 10s;
}

location ^~ /images/ {
    alias $backend_public_path/images/;
    expires 30d;
    add_header Cache-Control "public, max-age=2592000, immutable" always;
    autoindex off;
    access_log off;
}

location ^~ /storage/ {
    alias $backend_public_path/storage/;
    expires 30d;
    add_header Cache-Control "public, max-age=2592000, immutable" always;
    autoindex off;
    access_log off;
}

location ^~ /static/ {
    alias $backend_public_path/static/;
    autoindex off;
    access_log off;
}

location ^~ /dist/ {
    alias $backend_public_path/dist/;
    expires 30d;
    add_header Cache-Control "public, max-age=2592000, immutable" always;
    autoindex off;
    access_log off;
}

location ^~ /exports/ {
    alias $backend_public_path/static/exports/;
    autoindex off;
    access_log off;
}

location ^~ /app/ {
    proxy_pass https://iex_backend_https;
    proxy_ssl_server_name on;
    proxy_ssl_name $backend_domain;
    proxy_http_version 1.1;

    proxy_set_header Host $backend_domain;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
}

location ^~ /apps/ {
    proxy_pass https://iex_backend_https;
    proxy_ssl_server_name on;
    proxy_ssl_name $backend_domain;
    proxy_http_version 1.1;

    proxy_set_header Host $backend_domain;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
}

location / {
    return 302 /$selected_lang$uri$is_args$args;
}
```

После добавления конфигурации нажмите кнопку **«Сохранить».**
{% endstep %}

{% step %}

### Важная информация о языках

По умолчанию конфигурация настроена для языков:&#x20;

```
ru
en
```

К этим языкам относятся следующие части конфигурации:

```nginx
map $http_accept_language $accept_language
```

```nginx
map $cookie_lang $selected_lang
```

```nginx
map $cookie_lang $selected_lang
```

```nginx
location ~ ^/(ru|en)$
```

```nginx
location ~ ^/(ru|en)/
```

Если вы хотите использовать дополнительные языки, их необходимо добавить во все эти места.

Пример для языков `ru`, `en`, `uk`, `ka`:

```nginx
map $http_accept_language $accept_language {
    "~*ru" ru;
    "~*en" en;
    "~*uk" uk;
    "~*ka" ka;
    default ru;
}

map $cookie_lang $selected_lang {
    "~^(ru|en|uk|ka)$" $cookie_lang;
    default $accept_language;
}

location ~ ^/(ru|en|uk|ka)$ {
    add_header Vary "Accept-Language, Cookie" always;
    add_header Set-Cookie "lang=$1; Path=/; Max-Age=31536000; SameSite=Lax" always;
    return 302 /$1/$is_args$args;
}

location ~ ^/(ru|en|uk|ka)/ {
    add_header Vary "Accept-Language, Cookie" always;
    add_header Set-Cookie "lang=$1; Path=/; Max-Age=31536000; SameSite=Lax" always;

    proxy_pass http://iex_frontend_ssr;
    proxy_redirect off;
}
```

{% hint style="warning" %}
Если язык добавлен только в `.env` Frontend, но не добавлен в Nginx, маршруты этого языка могут работать некорректно.
{% endhint %}
{% endstep %}

{% step %}

### Важная информация о /backend-api

В новой конфигурации API-запросы с основного домена должны идти через:&#x20;

```
https://ваш_домен/backend-api/...
```

А не напрямую на: `https://app.ваш_домен/client-api/...`

Это позволяет избежать CORS-ошибок и делает взаимодействие Frontend и Backend более стабильным.
{% endstep %}
{% endstepper %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.iexexchanger.com/get-started/ustanovka/nastroika-fastpanel/nastroika-nginx.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
