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 <noreply@anthropic.com>
17 KiB
17 KiB
Хаб: централизованное управление серверами 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. Принципы
- Два режима записи.
- На один сервер: действие пересылается выбранному серверу (
node=mdnsилиnode=ndns). Так уже работает чтение. - На все серверы: хаб выполняет действие на каждом выбранном сервере и показывает итог по каждому отдельно. Тихого «ок» при частичном успехе не бывает.
- На один сервер: действие пересылается выбранному серверу (
- Чтение и запись разделены.
- Токены
hub-reader(только View) остаются для чтения. - Для записи на каждом сервере заводится отдельный
hub-adminтолько с теми правами, которые нужны этапу.
- Токены
- Хаб защищается до того, как получает запись. Роли, ограничение попыток входа, журнал действий (этап 0).
- Конфиги синхронизируются, данные нет.
- Синхронизируются тексты конфигов приложений и настройки.
- Базы логов, кеш и статистика у каждого сервера свои.
- Общая часть плюс локальные поля.
- В конфигах приложений есть поля, свои для каждого сервера: сети Split Horizon, путь к базе Query Logs, локальные группы клиентов Advanced Blocking.
- Синхронизируется только общая часть. Локальные поля задаются по каждому серверу.
- Источник правды для конфигов: эталон в хабе.
- Хаб хранит желаемый конфиг в своём томе (
/data), серверы приводятся к нему. - Первый эталон берётся импортом с любого сервера.
- Альтернатива: ведущий сервер (mdns) как эталон. Она проще, но хуже: зависит от живучести одного сервера и не даёт истории.
- Хаб хранит желаемый конфиг в своём томе (
- Зоны DNS лучше синхронизировать средствами Technitium. Primary-зона на одном сервере и secondary с передачей зоны (AXFR) на другом надёжнее рассылки каждой правки из хаба. Хаб помогает это настроить и показывает расхождения, но не дублирует записи сам.
- Перед изменением предпросмотр, после него итог и откат. Каждое применение конфига сохраняет прежнюю версию.
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. Решения перед стартом
- Источник правды для конфигов: эталон в хабе (рекомендация) или ведущий сервер mdns.
- Вход в хаб: свои пользователи хаба с ролями или ваш auth-портал через Traefik
forwardAuth. - Какие приложения стоят на серверах и какие поля в их конфигах заведомо локальные. Это станет начальными списками локальных полей.