Files
technitium-console/docs/hub-management-plan.md
T
DenozordecandClaude Opus 5.5 8bb1e01936 Hub stage 5: manage each server from one console
Zones, Cache, Blocking, DNS Client, Settings, DHCP and Logs can now be
changed on one chosen server through the hub, with that server's admin
token. Operators manage cache and blocking; admins also zones, settings
and DHCP. Under "All servers", or on a server without an admin token,
the controls are disabled with a hint.

The hub refuses settings/set changes to a server's web service fields
and anything about users, SSO or LDAP; backup, restore, log and stats
deletion and admin/* stay refused. Non-admins get settings with secrets
blanked. Write params travel in the POST body, downloads pass through
with a single-use token, and the audit log names no values.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-31 22:06:37 +07:00

17 KiB
Raw Blame History

Хаб: централизованное управление серверами Technitium без кластера

Общий план. Внутри два пласта:

  • общее управление: каждый сервер из одной консоли, действия «на все серверы», сравнение и выравнивание;
  • упор на Apps: приложения на всех серверах и синхронизация их конфигов.

Статус: этапы 0 и 1 (безопасность, Apps по серверам), 2 (установка и обновление), 3 (сравнение и синхронизация конфигов), 4 (история, откат, расхождения) и 5 (управление каждым сервером) сделаны. Этапы 6 и далее пока планы (docs/hub-deploy.md).


1. Контекст и цель

  • Есть два независимых сервера Technitium DNS: mdns.shnt.top и ndns.shnt.top. Кластера нет и не будет: серверы должны оставаться самостоятельными.
  • Хаб на dnss.shnt.top уже показывает статистику обоих: Dashboard, Logs, About, переключатель «All servers / mdns / ndns», предупреждение об отказе сервера.
  • Цель: управлять обоими серверами из хаба. Прежде всего приложениями (Apps): ставить, обновлять и держать их конфиги одинаковыми там, где нужно, не трогая того, что у каждого сервера своё.

2. Принципы

  1. Два режима записи.
    • На один сервер: действие пересылается выбранному серверу (node=mdns или node=ndns). Так уже работает чтение.
    • На все серверы: хаб выполняет действие на каждом выбранном сервере и показывает итог по каждому отдельно. Тихого «ок» при частичном успехе не бывает.
  2. Чтение и запись разделены.
    • Токены hub-reader (только View) остаются для чтения.
    • Для записи на каждом сервере заводится отдельный hub-admin только с теми правами, которые нужны этапу.
  3. Хаб защищается до того, как получает запись. Роли, ограничение попыток входа, журнал действий (этап 0).
  4. Конфиги синхронизируются, данные нет.
    • Синхронизируются тексты конфигов приложений и настройки.
    • Базы логов, кеш и статистика у каждого сервера свои.
  5. Общая часть плюс локальные поля.
    • В конфигах приложений есть поля, свои для каждого сервера: сети Split Horizon, путь к базе Query Logs, локальные группы клиентов Advanced Blocking.
    • Синхронизируется только общая часть. Локальные поля задаются по каждому серверу.
  6. Источник правды для конфигов: эталон в хабе.
    • Хаб хранит желаемый конфиг в своём томе (/data), серверы приводятся к нему.
    • Первый эталон берётся импортом с любого сервера.
    • Альтернатива: ведущий сервер (mdns) как эталон. Она проще, но хуже: зависит от живучести одного сервера и не даёт истории.
  7. Зоны DNS лучше синхронизировать средствами Technitium. Primary-зона на одном сервере и secondary с передачей зоны (AXFR) на другом надёжнее рассылки каждой правки из хаба. Хаб помогает это настроить и показывает расхождения, но не дублирует записи сам.
  8. Перед изменением предпросмотр, после него итог и откат. Каждое применение конфига сохраняет прежнюю версию.

3. Этапы

Сначала безопасность, потом Apps (главный упор), потом общее управление.

Этап 0. Безопасность записи (обязателен первым)

  • Пользователи хаба с ролями, в файле /data/users.json, пароли в виде хешей:
    • viewer: только смотрит;
    • apps-admin: управляет приложениями;
    • operator: блокировка и кеш;
    • admin: всё.
  • Защита входа:
    • ограничение попыток входа и временная блокировка после серии неудач;
    • по желанию: вход через ваш auth-портал (Traefik forwardAuth).
  • Журнал действий (/data/audit.log, раздел Audit в консоли хаба): кто, когда, на каком сервере, что сделал, итог.
  • Токены записи MDNS_ADMIN_TOKEN и NDNS_ADMIN_TOKEN. На старте права только Modify и Delete на Apps, другие разделы добавляются по этапам.
  • Права в хабе: вместо списка «только чтение»: таблица «эндпоинт → чтение / запись на один сервер / запись на все / нужная роль».
  • Доступ к хабу по сети: закрыть по IP (ipallowlist в Traefik) или через auth-портал.

Этап 1. Apps: обзор по серверам (только чтение)

Матрица «приложение × сервер» в разделе Apps при «All servers»:

  • установлено или нет, версия, есть ли обновление;
  • конфиг: «совпадает», «отличается (N полей)» или «отличается только в локальных полях»;
  • фильтры: «отличаются версии», «отличаются конфиги», «есть обновление».

Отвечает на вопрос «что где стоит и где расхождения» без единой записи.

Этап 2. Apps: установка, обновление, удаление на нескольких серверах

  • Выбор цели у действий: mdns, ndns или все серверы.
  • Из магазина: apps/downloadAndInstall и apps/downloadAndUpdate на каждом выбранном сервере.
  • Свой zip: загружается в хаб один раз, хаб отправляет его через apps/install или apps/update на каждый сервер.
  • Окно итога по серверам и кнопка «Повторить на неудавшихся».
  • «Выровнять версии»: обновить приложение везде до самой новой версии.
  • Удаление на всех: отдельное подтверждение. Хаб перед удалением сохраняет конфиг в историю.

Этап 3. Apps: сравнение и синхронизация конфигов

  • Сравнение рядом: конфиг на mdns и на ndns. Для JSON: по полям (добавлено, удалено, изменено), для не-JSON: построчно.
  • Эталон в хабе:
    • импорт эталона с выбранного сервера;
    • правка эталона в редакторе хаба;
    • хранение в /data/apps/<приложение>/baseline.json.
  • Локальные поля:
    • список путей полей, которые не синхронизируются (например, networks, dbPath), плюс их значения по каждому серверу;
    • хранение в /data/apps/<приложение>/overrides.json;
    • итоговый конфиг сервера = эталон + его локальные значения.
  • Предпросмотр: что изменится на каждом сервере, затем применение через apps/config/set на выбранных серверах с итогом по каждому.
  • Проверка до записи: JSON разбирается в хабе. Если сервер отверг конфиг, показывается его ошибка, а сервер остаётся со старым конфигом.

Этап 4. Apps: история, откат, контроль расхождений

  • История: каждое применение сохраняет прежний конфиг каждого сервера (/data/apps/<приложение>/history/). Можно посмотреть любую версию и откатить один сервер или все.
  • Проверка расхождений по расписанию (по умолчанию раз в 15 минут). Если конфиг поменяли прямо в консоли сервера, в шапке появляется предупреждение с действиями «Принять как эталон» и «Вернуть к эталону».
  • Экспорт и импорт всех эталонов одним файлом: резервная копия и подготовка нового сервера.

Этап 5. Управление каждым сервером из одной консоли

  • Запись на выбранный сервер открывается для разделов Zones, Cache, Blocking, DNS Client, Settings, DHCP, Logs (кроме удаления логов). Права токена hub-admin расширяются под эти разделы.
  • В «All servers» запись по-прежнему закрыта: кнопки неактивны с подсказкой «выберите сервер».
  • Администрирование пользователей, SSO и LDAP серверов остаётся в их собственных консолях.

Этап 6. Действия «на все серверы» вне Apps

  • Блокировка: добавить или удалить домен в Blocked и Allowed, временно отключить блокировку, обновить списки, изменить URL списков.
  • Кеш: сбросить весь кеш или удалить домен.
  • Итог по каждому серверу и повтор на неудавшихся.

Этап 7. Сравнение и выравнивание остального

  • Zones в «All servers»:
    • объединённый список с отметкой, где зона есть, и признаком расхождения (разный SOA serial);
    • действия «Скопировать зону на другой сервер» (экспорт и импорт) и «Сделать secondary на другом сервере» (передача зоны).
  • Blocking и Settings: отчёт о различиях и «Принять как эталон» с предпросмотром, по той же схеме «общая часть плюс локальные поля», что и для Apps.

Этап 8. Удобство (по желанию)

  • Профили: набор приложений с конфигами и правил, который применяется к новому серверу.
  • Уведомления о расхождениях наружу (webhook).

4. Что меняется в коде

Хаб (hub/):

  • server.ts:
    • таблица прав по эндпоинтам;
    • пересылка POST и multipart (zip приложений, импорт зон);
    • рассылка «на все» с итогами по серверам.
  • Новые модули:
    • users.ts: роли, хеши паролей, ограничение попыток входа;
    • audit.ts: журнал действий;
    • store.ts: файлы в /data (эталоны, локальные поля, история), запись атомарно через временный файл;
    • apps-sync.ts: сравнение конфигов, слияние эталона с локальными полями, предпросмотр, применение;
    • drift.ts: проверка расхождений по расписанию.
  • config.ts: <ID>_ADMIN_TOKEN, HUB_DATA (по умолчанию /data), HUB_DRIFT_MINUTES.

Консоль (src/), только в режиме хаба:

  • права разделов приходят от хаба по роли пользователя;
  • Apps: матрица по серверам, выбор цели у действий, окно итогов;
  • экран «Конфиг приложения»: сравнение рядом, эталон, локальные поля, предпросмотр, история и откат;
  • предупреждение о расхождениях в шапке;
  • раздел Audit.

Развёртывание:

  • в compose: том technitium-hub-data:/data и токены MDNS_ADMIN_TOKEN, NDNS_ADMIN_TOKEN в .env;
  • на каждом сервере пользователь hub-admin в отдельной группе с правами записи только на нужные разделы.

5. Риски и как их закрыть

Риск Что делаем
Хаб получает ключи на запись к обоим серверам Этап 0 первым; токены только на нужные разделы; хаб закрыт по IP или через auth-портал
Частичный успех при рассылке Итог по каждому серверу, повтор на неудавшихся, откат из истории
Разные версии приложения ждут разный формат конфига Хаб показывает версии и предлагает сначала выровнять их
Неверно заданные локальные поля перенесут настройки одного сервера на другой Предпросмотр перед каждым применением, история и откат
Конфиг поменяли мимо хаба Проверка расхождений по расписанию и предупреждение
Разные версии Technitium понимают API по-разному Версия каждого сервера в хабе, предупреждение при расхождении

6. Как проверяется каждый этап

  • Модульные тесты хаба (vitest): права по эндпоинтам, роли и защита входа, слияние эталона с локальными полями, сравнение JSON, история и откат.
  • Тест с двумя фейковыми серверами: рассылка, частичный отказ, итоги.
  • Мок (dev/mock-api.mjs) получает приложения и конфиги, разные на двух портах. В браузере проверяются матрица, сравнение, применение и откат.
  • Порядок работы: код по этапам пишет Sonnet, Opus проверяет дифф, тесты и браузер, коммит после каждого принятого этапа.
  • На серверах: сначала на одном приложении с безобидным конфигом, потом шире.

7. Решения перед стартом

  1. Источник правды для конфигов: эталон в хабе (рекомендация) или ведущий сервер mdns.
  2. Вход в хаб: свои пользователи хаба с ролями или ваш auth-портал через Traefik forwardAuth.
  3. Какие приложения стоят на серверах и какие поля в их конфигах заведомо локальные. Это станет начальными списками локальных полей.