🧩
Домены

DNS как код: управление записями через Terraform и OctoDNS

10.11.2026
← Все статьи

Чаще всего DNS-записи добавляют вручную через веб-панель: сначала A-запись, затем MX, потом SPF и DKIM для почты. Для одного сайта этого достаточно. Но когда доменов больше десяти, в команде работают несколько человек или нужно точно знать, кто и зачем изменил запись, ручное управление превращается в источник путаницы. Подход «DNS как код» означает, что зона хранится в текстовых файлах, версионируется в Git и применяется к DNS-провайдеру специальным инструментом.

Зачем хранить DNS в файлах

Первое преимущество — история и ответственность. Каждое изменение становится коммитом с автором, датой и комментарием. Если утром перестала работать почта, сразу видно, кто вчера трогал MX или SPF, и изменение можно откатить одной командой. В панели же приходится вспоминать старое значение или искать его на скриншотах.

Второе преимущество — проверка. Изменение попадает не сразу в живую зону, а сначала в pull request: коллега его просматривает, а инструмент заранее показывает, какие именно записи будут добавлены, изменены или удалены. Третье — единообразие: сеть из десяти филиалов получает записи по одному шаблону, и ни у одного сайта не остаётся «забытого» DMARC или старого IP-адреса.

Кому это подходит, а кому нет

Небольшой кофейне в Ташкенте с одним доменом и пятью записями Terraform не нужен — настройка займёт больше времени, чем сэкономит. Зато интернет-магазину с несколькими брендами, тестовой и боевой средой и десятками поддоменов или IT-отделу сети клиник такой подход окупается быстро. Главное условие: у DNS-провайдера должен быть API, либо вы управляете собственным DNS-сервером. Без API инструмент не сможет обновлять записи, и вы всё равно вернётесь в панель.

Если домен зарегистрирован в sayt.uz, NS-серверы можно направить на любой DNS-сервис через личный кабинет. Тогда регистрация и оплата домена остаются в кабинете, а зона живёт на DNS-сервере, которым вы управляете кодом.

DNS-записи в Terraform

Terraform описывает инфраструктуру декларативно: вы пишете, каким должно быть состояние, а инструмент сравнивает его с текущим и применяет разницу. Для DNS существуют провайдеры разных сервисов. В примере ниже используется универсальный провайдер hashicorp/dns, который работает через динамические обновления RFC 2136 с собственным сервером, например BIND. Доступ проверяется ключом TSIG.

terraform {
  required_providers {
    dns = {
      source  = "hashicorp/dns"
      version = "~> 3.4"
    }
  }
}

provider "dns" {
  update {
    server        = "192.0.2.53"
    key_name      = "terraform-key."
    key_algorithm = "hmac-sha256"
    key_secret    = var.tsig_secret
  }
}

resource "dns_a_record_set" "www" {
  zone      = "example.uz."
  name      = "www"
  addresses = ["203.0.113.10"]
  ttl       = 3600
}

resource "dns_mx_record_set" "mail" {
  zone = "example.uz."
  ttl  = 3600
  mx {
    preference = 10
    exchange   = "mail.example.uz."
  }
}

Рабочий цикл состоит из трёх команд: terraform init загружает провайдеры, terraform plan показывает будущие изменения, terraform apply применяет их. Всегда внимательно читайте план: неожиданная строка destroy означает, что кто-то добавил запись вручную или в файле опечатка в имени.

terraform init
terraform plan -out=dns.plan
terraform apply dns.plan

OctoDNS: зона в виде YAML

OctoDNS создан именно для DNS: зона хранится в простом YAML-файле и синхронизируется с одним или несколькими провайдерами. Это особенно удобно, когда одну зону нужно вести одновременно у двух провайдеров ради резервирования. Конфигурация задаёт источник и цель:

providers:
  config:
    class: octodns.provider.yaml.YamlProvider
    directory: ./zones
  cloudflare:
    class: octodns_cloudflare.CloudflareProvider
    token: env/CLOUDFLARE_TOKEN

zones:
  example.uz.:
    sources:
      - config
    targets:
      - cloudflare

Файл зоны zones/example.uz.yaml хранит записи в читаемом виде, пустой ключ обозначает сам домен (apex):

---
'':
  - type: A
    value: 203.0.113.10
  - type: MX
    values:
      - exchange: mail.example.uz.
        preference: 10
www:
  type: CNAME
  value: example.uz.

Команда octodns-sync --config-file=config/production.yaml по умолчанию работает в пробном режиме и только выводит список изменений. Чтобы применить их, добавляют флаг --doit. Эта защита спасает от случайных удалений.

Перенос существующей зоны

Самый рискованный этап — первоначальный перенос. Если какой-то существующей записи нет в файле, инструмент сочтёт её лишней и может удалить. Поэтому сначала полностью экспортируйте текущую зону, перенесите каждую запись и добейтесь, чтобы первый plan или dry-run не показывал никаких изменений. В Terraform существующие записи добавляются в состояние через terraform import или блоки import, а в OctoDNS команда octodns-dump выгружает зону провайдера в YAML.

Пример: IT-специалист учебного центра в Самарканде при переносе зоны из 40 записей сначала сделал дамп, затем привёл файл в порядок и внёс первое реальное изменение только после того, как план показал «0 to add, 0 to change, 0 to destroy». Благодаря этому ни сайт, ни почта не прерывались ни на минуту.

Секреты, state-файл и ручные правки

API-токены и TSIG-ключи никогда не коммитят в Git — их передают через переменные окружения или секреты CI. Файл состояния terraform.tfstate может содержать чувствительные значения в открытом виде, поэтому он тоже не попадает в репозиторий и хранится в защищённом месте. Кроме того, договоритесь в команде не править вручную зону, управляемую кодом: следующий apply молча отменит такую правку, и это часто заканчивается неожиданным сбоем.

Следите за TTL. За сутки до крупного переноса или смены IP снизьте TTL важных записей до 300 секунд, чтобы при ошибке быстро вернуться назад. После завершения работ TTL снова поднимают до часа или больше.

Автоматизация через CI

Удобнее всего схема, в которой CI на каждый pull request автоматически запускает plan или dry-run и оставляет результат комментарием, а после слияния в основную ветку выполняет apply. Так никто не трогает живую зону напрямую, каждое изменение проходит вторую пару глаз, а откат сводится к revert предыдущего коммита. Даже небольшой команде такая схема настраивается за день и экономит время годами.

Похожие статьи

🤖 Почему домен .ai стоит дорого и какие ограничения нужно знать до регистрации 🌐 С www или без: какой вариант адреса сайта правильный 🤝 Как стать реселлером доменов: бизнес-модель в Узбекистане 🕳️ Subdomain takeover: чем опасны забытые DNS-записи
🌐 Язык
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский ✓ 🇬🇧 English