2026-07-05 17:01:33 +07:00
2026-07-05 17:01:33 +07:00
2026-07-05 17:01:33 +07:00

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-проба, используется как Docker HEALTHCHECK через встроенный 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), пароль не логируется. Учётные данные проверяются пробным логином прямо при добавлении аккаунта.

Рабочий процесс

  1. Зарегистрироваться (self-registration, автоматически создаётся личный проект).
  2. Добавить аккаунт Selectel (данные сервисного пользователя, см. выше).
  3. Импортировать зоны аккаунта — на каждую зону заводится домен.
  4. Привязать шаблон: создать снимком из зоны или собрать вручную с плейсхолдерами {{domain_name}}; без шаблона доступен только просмотр записей.
  5. Открыть диф домена, отметить нужные изменения/удаления, применить.

Стек

Go 1.26 (statically-linked бинарь, SPA встроена через embed), React + Vite (SPA), PostgreSQL 17, Prometheus client, distroless/static-debian12 рантайм-образ.

Запуск в Docker

Требуется Docker Engine + Docker Compose v2.

  1. Скопировать пример конфигурации:

    cp .env.example .env
    
  2. Сгенерировать ключ шифрования секретов (провайдеров/каналов) — ровно 32 байта в base64 — и вписать его в .env как DNS_AR_ENC_KEY:

    openssl rand -base64 32
    

    Также задать POSTGRES_PASSWORD (без дефолта — сервис не поднимется без явного пароля).

  3. Поднять стек (postgres + app), сборка образа приложения — на лету:

    docker compose up -d --build
    # или: make docker-up
    

    app стартует только после того, как postgres станет healthy; миграции схемы БД приложение накатывает само при старте.

  4. Открыть UI: http://localhost:8080

Остановить стек: 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.

S
Description
No description provided
Readme 535 KiB
Languages
Go 61%
TypeScript 37.5%
CSS 1.2%
Dockerfile 0.1%