> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/ru/getting-started/reverse-proxy-and-domains.md).

# Обратный прокси и домены

MyIP обслуживает обычный HTTP на порту `18966` и не завершает TLS. Для любого публичного развертывания поставьте перед ним обратный прокси.

## Проксирование к MyIP

Ничего необычного настраивать не нужно. Укажите в вашем прокси порт `18966` и готово:

* **Обработка апгрейда WebSocket не требуется.** Бэкенд MyIP использует обычный HTTP.
* **Нет `try_files` или правила переписывания для SPA.** Фронтенд-сервер уже делает fallback на `index.html` для клиентских маршрутов вроде `/tools/whois`.
* **Нет `/api` без специальных случаев.** Тот же сервер проксирует `/api` во внутренний бэкенд.
* **Не добавляйте кеширование на уровне прокси.** MyIP устанавливает собственные `Cache-Control` для каждого класса ресурсов — хешированные ресурсы неизменяемы в течение года, `index.html` пере-валидируется, `/api/*` по умолчанию `no-store`. Если это переопределить, после деплоя будут показываться устаревшие страницы.

{% tabs %}
{% tab title="Nginx" %}
{% code title="/etc/nginx/sites-available/myip" %}

```nginx
server {
    listen 443 ssl http2;
    server_name myip.example.com;

    ssl_certificate     /etc/letsencrypt/live/myip.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/myip.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:18966;
        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;
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Caddy" %}
{% code title="Caddyfile" %}

```
myip.example.com {
    reverse_proxy 127.0.0.1:18966
}
```

{% endcode %}

Caddy обрабатывает TLS-сертификаты и устанавливает `X-Forwarded-*` заголовки за вас.
{% endtab %}
{% endtabs %}

### Важные заголовки

Бэкенд работает с Express `trust proxy` установленным на один хоп, и определяет IP клиента в следующем порядке:

1. `CF-Connecting-IP` (Cloudflare)
2. первую запись из `X-Forwarded-For`
3. `CF-Connecting-IPv6`
4. адрес сокета

Именно этот адрес используется для ограничения частоты запросов и записи в журнал заблокированных IP. Если ваш прокси не передаёт `X-Forwarded-For`, каждый посетитель выглядит как один клиент, и ограничения частоты применяются ко всем сразу. См. [Параметры безопасности](/developer/ru/configuration/security-options.md).

{% hint style="info" %}
**Размер тела запроса.** Общие диагностические отчёты отправляют до 500 КБ на `/api/report`, а если вы включите фронтенд-туннель Sentry, `/api/monitoring` принимает envelope размером до 10 МБ. Если вы ужесточите `client_max_body_size` (по умолчанию в Nginx — 1 МБ), оставьте значение выше этих лимитов.
{% endhint %}

## `ALLOWED_DOMAINS` — требуется на реальном домене

Каждый `/api/*` маршрут находится за `Referer` проверкой. Запрос отклоняется с **403** если только `Referer` hostname в заголовке `localhost` не является `ALLOWED_DOMAINS`.

или не указан в списке. Именно это не позволяет другим сайтам встраивать ваш экземпляр и использовать ваши API-ключи и лимиты запросов. Это также самая распространённая ошибка при самостоятельном хостинге: приложение загружается, а затем не работает ни один инструмент.

{% hint style="danger" %}
Если вы обслуживаете MyIP по адресу `https://myip.example.com` и оставите `ALLOWED_DOMAINS` пустым, **весь API вернёт 403**. Страница отображается, а ничего на ней не работает.
{% endhint %}

```bash
ALLOWED_DOMAINS="myip.example.com,www.myip.example.com"
```

Точное поведение, чтобы вы сразу всё сделали правильно:

| Правило               | Деталь                                                                                                                                     |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Разделитель           | Запятая. **Без пробелов** — записи сопоставляются буквально, и `" b.com"` никогда ни с чем не совпадает.                                   |
| Сопоставление         | Точное имя хоста. `example.com` не **не** разрешает `sub.example.com`, и наоборот.                                                         |
| `www`                 | Отдельное имя хоста. Укажите оба, если оба доступны.                                                                                       |
| Порт и путь           | Игнорируются. `example.com` охватывает `https://example.com:8443/anything`.                                                                |
| `localhost`           | Всегда разрешено, независимо от того, что вы настроили.                                                                                    |
| Обычный IP-адрес      | Рассматривается как имя хоста. Чтобы получить доступ к приложению по адресу `http://192.168.1.10:18966`, добавьте `192.168.1.10` в список. |
| Отсутствует `Referer` | Отклонено с `{"error":"Что вы делаете?"}`.                                                                                                 |
| Запрещённое имя хоста | Отклонено с `{"error":"Доступ запрещён"}`.                                                                                                 |

{% hint style="info" %}
Отсутствие `Referer` всегда приводит к отклонению, поэтому `curl https://myip.example.com/api/...` возвращает 403 по задумке. API предназначен для собственного фронтенда приложения, а не для прямых скриптов.
{% endhint %}

## IP-эндпоинты, удобные для curl

В MyIP есть панель "Command Line API", которая показывает посетителям `curl` однострочную команду для проверки своего IP из терминала. Необязательный `/geo` путь добавляет геолокацию к ответу:

```bash
curl 4.example.com
curl 4.example.com/geo
```

Три переменные определяют, какие имена хостов панель выводит:

| Переменная               | Элемент панели                                            |
| ------------------------ | --------------------------------------------------------- |
| `VITE_CURL_IPV4_DOMAIN`  | Получить IPv4-адрес машины                                |
| `VITE_CURL_IPV6_DOMAIN`  | Получить IPv6-адрес машины                                |
| `VITE_CURL_IPV64_DOMAIN` | Получить предпочитаемый IP-адрес выхода в сеть для машины |

Укажите им имена хостов, которые разрешаются соответствующим образом — только A, только AAAA и dual-stack.

{% hint style="warning" %}
**Все три обязательны.** Фронтенд показывает панель curl только когда заданы все три; если хотя бы одно пусто, функция остаётся скрытой, а диалог сообщает, что она недоступна.
{% endhint %}

{% hint style="warning" %}
**Это переменные времени сборки.** Как и любая `VITE_*` переменная, они встраиваются в JavaScript-бандл с помощью Vite. Передача их в уже собранный Docker-образ во время выполнения ничего не даёт — задайте их в `.env` до `pnpm run build`, или перед `docker build` своего собственного образа. См. [Развертывание с Node.js](/developer/ru/getting-started/deploy-with-nodejs.md).
{% endhint %}

{% hint style="info" %}
**MyIP не реализует `/geo` эндпоинт.** Эти переменные лишь говорят фронтенду, какие имена хостов выводить в панели curl. Сервис, отвечающий на `4.example.com/geo` — это то, что вы запускаете отдельно. Оставьте переменные пустыми, и функция просто останется выключенной — см. [Функции, привязанные к IPCheck.ing](/developer/ru/configuration/features-tied-to-ipcheck-ing.md).
{% endhint %}

## Устранение неполадок

<details>

<summary>Страница загружается, но каждый инструмент показывает ошибку</summary>

Почти всегда `ALLOWED_DOMAINS`. Откройте сетевую вкладку браузера и посмотрите ответы 403 на `/api/*`. Тело ответа подскажет, какой случай у вас:

* `{"error":"Доступ запрещён"}` — имя хоста отсутствует в списке. Добавьте точное имя хоста, которое вы вводите в адресной строке.
* `{"error":"Что вы делаете?"}` — нет `Referer` дошло до бэкенда. Проверьте, не удаляет ли его ваш прокси или расширение для приватности.

Перезапустите бэкенд после изменения `ALLOWED_DOMAINS`.

</details>

<details>

<summary>Ограничения частоты срабатывают для всех одновременно</summary>

Ваш прокси не передаёт реальный IP клиента, поэтому весь трафик сваливается на один адрес. Добавьте `X-Forwarded-For` (см. пример Nginx выше) и перезапустите.

</details>

<details>

<summary>Устаревший контент после обновления</summary>

Проверьте, нет ли кеширования на уровне прокси или CDN. MyIP уже устанавливает соответствующие `Cache-Control` заголовки; если ваш прокси кеширует `index.html` дольше, посетители продолжают загружать сборку, чьи файлы ресурсов уже не существуют.

</details>

## Следующие шаги

* [Параметры безопасности](/developer/ru/configuration/security-options.md) — ограничение частоты, замедление, журналирование заблокированных IP
* [Переменные окружения](/developer/ru/reference/environment-variables.md)
* [API-эндпоинты](/developer/ru/reference/api-endpoints.md)


---

# 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, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/ru/getting-started/reverse-proxy-and-domains.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
