Четыре имени вместо одного
Раньше вся система жила на одном имени: панель в корне, документация в подкаталоге /docs/,
обновления в /assets/, API в /api/. Теперь имён четыре, и это не наведение красоты —
разделение решает конкретную задачу безопасности.
Кто есть кто
| Имя | Что раздаёт | Кто туда ходит |
|---|---|---|
panel.1.router.thepragmaticdev.support | панель оператора и её /api/ | оператор из браузера |
api.1.router.thepragmaticdev.support | только /device/*, всё остальное — 404 | постаматы |
ota.1.router.thepragmaticdev.support | манифест обновлений и ассеты | постаматы |
docs.1.router.thepragmaticdev.support | эту документацию | люди |
Все четыре имени указывают на один и тот же адрес — разводит их nginx по имени, которое пришло в запросе. Сертификат один на все четыре, автопродление включено.
Конфигурация — infra/machine-b/postamat.nginx.conf, сами имена — infra/config.env
(DOMAIN_PANEL, DOMAIN_API, DOMAIN_OTA, DOMAIN_DOCS). Правятся о ни там, а не на машине:
следующая выкладка перезапишет файл.
Зачем разделили: постамат больше не видит панель
В проде постамат выходит в сеть по Wi-Fi, и на роутере объекта стоит фильтр — наружу разрешено ходить только до нашего backend. Фильтр работает по именам. Пока имя было одно, запись в фильтре «разрешить наш backend» означала «разрешить весь хост целиком»: вместе с эндпоинтами устройства терминал получал и страницу входа в панель оператора. Разделить их было нечем — разделять было нечего.
Теперь в фильтр объекта заносятся только api и ota. Панель оператора постамату
недоступна вовсе — не «закрыта паролем», а не существует с его точки зрения.
Постамат стоит на улице. Залочка на нём не сделана намеренно, корпус вскрывается, планшет уносится. Считать его доверенным устройством нельзя, а значит всё, до чего он дотягивается, надо считать доступным тому, кто до него добрался.
Отдельное имя убирает панель из этого списка целиком, и убирает на роутере, до всякой проверки пароля. Это дешевле и надёжнее любой настройки на нашей стороне.
Имя api устроено так же строго и со своей стороны: там разрешён единственный префикс
/device/, а всё остальное отдаёт 404 — ни панели, ни документации, ни ассетов с этого
имени не получить в принципе.
CORS при этом не появился
Обычная плата за разделение хостов — запросы между источниками, преднастройка OPTIONS
и возня с cookie. Здесь её нет: панель держит свой /api/ на своём же имени, nginx
проксирует его на ту же машину с сервером. Для браузера оператора это один источник,
как и раньше:
- CORS не нужен вообще;
- cookie сессии остаётся
httpOnly; SameSite=Strict; Secure; - адрес API в панели задаётся при сборке и по умолчанию равен
/api— относительному пути, а не полному имени.
То есть постамат и панель ходят к одному и тому же серверу, но по разным именам и разными маршрутами, и это единственное, что между ними общее.
Обращение по голому адресу рвётся намеренно
На неизвестное имя и на обращение по IP nginx отвечает разрывом соединения (return 444),
не показывая ничего. Без этого блока такой запрос попал бы в первый попавшийся раздел
конфигурации, то есть показал бы панель оператора тому, кто её не иска л.
⚠️ Практическое следствие: «по IP не открывается» — это правильное поведение, а не поломка развёртывания. Проверять надо по имени.
Что из этого следует для кода
- Киоск не должен знать имени панели. Его адреса —
apiиota, и только они попадают в фильтр на роутере. Ссылка на панель, случайно попавшая в код киоска, на объекте просто не откроется, а выглядеть будет как сетевая ошибка. - Обновления живут на
otaцеликом — и манифест, и ассеты. Так их однажды можно увести на CDN, не трогая ни панель, ни API. Подробнее — что обновляется по воздуху. - Документация живёт в корне своего имени. Подкаталога
/docs/больше нет,baseUrlвdocusaurus.config.tsравен/. Возврат к/docs/сломает сайт тихо: страницы будут открываться, но без оформления. Разбор — разв ёртывание. - Новое имя — это работа в трёх местах сразу:
infra/config.env, блокserverв конфигурации nginx и перевыпуск сертификата на все имена разом. По отдельности любая из трёх правок даёт нерабочее или незащищённое имя.