8.5 KiB
DNS Autoresolver
Утилита автонастройки и проверки DNS-зон: multi-tenant сервис, который сверяет фактическое состояние зоны у провайдера (Selectel DNS API v2) с шаблоном записей, показывает диф и применяет изменения только вручную — никакого автоматического apply без подтверждения оператора.
Возможности
- Multi-tenant: проекты, аккаунты провайдера, домены — с авторизацией (регистрация/логин, сессии); всё изолировано по проекту.
- Провайдер Selectel (Cloud DNS v2): авторизация через project IAM-токен сервисного пользователя (не статический API-ключ — см. ниже), чтение зон/RRSet, импорт зон, диф против шаблона, ручной apply.
- Шаблоны записей с плейсхолдером
{{domain_name}}: один шаблон переиспользуется на многих доменах — при проверке подставляется имя зоны. Шаблон можно завести вручную или снять снимком с существующей зоны («создать шаблон из зоны», с авто-параметризацией имени домена). - Просмотр зоны без шаблона: текущие записи зоны видны даже до привязки
шаблона; статус домена без шаблона — «без шаблона», а не
unknown. - Диф + выборочный ручной apply: чекбоксы на каждой записи (updates и
prunes), удаления по умолчанию сняты (opt-in). Удаления применяются
перед обновлениями — иначе провайдер отвергает конфликт (например
CNAMEна имени, где ещё живаA-запись). При ошибке показывается реальный ответ провайдера, а не generic-текст. - Расписание проверок: планировщик периодически гоняет read-only check+notify (без Apply), пишет историю проверок и статус drift.
- Уведомления: каналы Telegram и Webhook, per-channel статус доставки.
- Метрики: Prometheus
/metrics(публичный, без auth, только агрегаты). - Health-check:
/healthz— liveness-проба, используется как DockerHEALTHCHECKчерез встроенный CLI-режимapp -healthcheck.
Учётные данные Selectel
Cloud DNS v2 требует project IAM-токен, а не статический API-ключ. При добавлении аккаунта Selectel в UI указываются данные сервисного пользователя:
- имя сервисного пользователя,
- пароль,
- номер аккаунта (
account_id, вида123456), - имя проекта.
Сервисный пользователь создаётся в панели Selectel (раздел
Пользователи и роли) и ему выдаётся роль
на нужный проект. Приложение само обменивает эти данные на 24-часовой
IAM-токен (Identity API cloud.api.selcloud.ru) и кэширует его; данные
хранятся зашифрованными (AES-256-GCM), пароль не логируется. Учётные данные
проверяются пробным логином прямо при добавлении аккаунта.
Рабочий процесс
- Зарегистрироваться (self-registration, автоматически создаётся личный проект).
- Добавить аккаунт Selectel (данные сервисного пользователя, см. выше).
- Импортировать зоны аккаунта — на каждую зону заводится домен.
- Привязать шаблон: создать снимком из зоны или собрать вручную с
плейсхолдерами
{{domain_name}}; без шаблона доступен только просмотр записей. - Открыть диф домена, отметить нужные изменения/удаления, применить.
Стек
Go 1.26 (statically-linked бинарь, SPA встроена через embed), React +
Vite (SPA), PostgreSQL 17, Prometheus client, distroless/static-debian12
рантайм-образ.
Запуск в Docker
Требуется Docker Engine + Docker Compose v2.
-
Скопировать пример конфигурации:
cp .env.example .env -
Сгенерировать ключ шифрования секретов (провайдеров/каналов) — ровно 32 байта в base64 — и вписать его в
.envкакDNS_AR_ENC_KEY:openssl rand -base64 32Также задать
POSTGRES_PASSWORD(без дефолта — сервис не поднимется без явного пароля). -
Поднять стек (postgres + app), сборка образа приложения — на лету:
docker compose up -d --build # или: make docker-upappстартует только после того, какpostgresстанет healthy; миграции схемы БД приложение накатывает само при старте. -
Открыть UI: http://localhost:8080
- Метрики (Prometheus): http://localhost:8080/metrics
- Health-check: http://localhost:8080/healthz
Остановить стек: docker compose down (или make docker-down).
Логи приложения: docker compose logs -f app (или make docker-logs).
Переменные окружения (.env)
| Переменная | Назначение | По умолчанию |
|---|---|---|
POSTGRES_USER |
пользователь PostgreSQL | dnsar |
POSTGRES_PASSWORD |
пароль PostgreSQL — обязателен, без дефолта | — |
POSTGRES_DB |
имя БД | dnsar |
APP_PORT |
порт публикации приложения на хосте | 8080 |
DNS_AR_ENC_KEY |
ключ шифрования секретов, base64 → ровно 32 байта — обязателен | — |
Секреты передаются только через переменные окружения, никогда — в образ, логи или git.
Локальная разработка (без Docker)
make build # go build ./...
make test # go test ./... (тесты internal/store требуют Docker — testcontainers)
make web # сборка SPA (npm ci && npm run build) в internal/web/dist
make build-all # web + build
go test ./internal/service/ -run TestName -v # один тест / пакет
cd web && npm run test -- --run # фронт-тесты (Vitest)
cd web && npx tsc --noEmit # проверка типов SPA
Для запуска бинаря напрямую нужны те же переменные окружения:
DNS_AR_DB_DSN, DNS_AR_ENC_KEY (обязательные), DNS_AR_LISTEN
(по умолчанию :8080).
internal/web/dist/— цельgo:embed; в git коммитится только плейсхолдерindex.html.npm run buildперезаписывает его — перед коммитом выполнитьgit checkout internal/web/dist/index.html, а реальный бандл собирать черезmake web.