Files
technitium-console/docs/hub-management-plan.md
T
DenozordecandClaude Opus 5.5 9742f0fe69
CI / check (push) Successful in 4m27s
Hub / check (push) Successful in 1m17s
CI / image (push) Successful in 1m54s
Hub / image (push) Successful in 1m56s
Hub stage 8: settings drift, webhook notices, profiles
The drift check now also covers the settings baseline and the Blocked
and Allowed lists baseline; the drift dialog offers Open compare,
Accept as baseline and Revert to baseline for them. Old drift.json
files still load.

HUB_WEBHOOK_URL (and an optional HUB_WEBHOOK_SECRET for an HMAC
signature) receives drift.found, drift.cleared and write.failed
notices, only on change, without values, never blocking a request and
never logging the address beyond its host. Admins see the webhook
status and can send a test from About and from the drift dialog.

Profiles bundle the hub's app, settings and lists baselines. Applying
one to a server runs install, app configs, settings and lists in order
after a preview; a failed step stops that server's later steps and
Retry failed resumes from it. Profiles export and import as a file.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 02:11:19 +07:00

17 KiB
Raw Blame History

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

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

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

Статус: этапы 0 и 1 (безопасность, Apps по серверам), 2 (установка и обновление), 3 (сравнение и синхронизация конфигов), 4 (история, откат, расхождения), 5 (управление каждым сервером), 6 (действия на все серверы вне Apps), 7 (зоны, настройки и блокировка: сравнение и выравнивание) и 8 (профили, webhook, расхождения настроек и списков) сделаны. Этапы после 8 пока планы (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. Какие приложения стоят на серверах и какие поля в их конфигах заведомо локальные. Это станет начальными списками локальных полей.