1. What octoDNS Is¶
octoDNS is a tool from GitHub for managing DNS records as code, across one or more DNS providers, from a single declarative source of truth. It doesn't run as a DNS server itself (unlike everything else in this set of guides) — it's a synchronization tool: you describe the records you want in YAML, and octoDNS pushes (or diffs, or pulls) that state to/from real DNS providers via their APIs — Route 53, Cloudflare, Google Cloud DNS, Azure DNS, NS1, PowerDNS, and dozens more, including plain BIND zone files as a provider.
The core problem it solves: DNS records managed by hand through provider web consoles or ad hoc API scripts drift, go undocumented, and have no change history or review process. octoDNS treats zone data the way infrastructure-as-code tools treat infrastructure — version-controlled, diffable, reviewable in a pull request, and reproducibly applied.
2. Installation¶
python3 -m venv env
source env/bin/activate
pip install octodns
# Provider-specific plugins are separate packages, e.g.:
pip install octodns-route53 octodns-cloudflare
3. Core Concepts¶
- Config file (
config.yaml) — defines providers and which zones each is a source/target for. - Zone files (one YAML file per zone, e.g.
example.com.yaml) — the actual declarative record data. - Providers — a Python-plugin abstraction over each DNS backend's API, each implementing the same source/target interface so octoDNS's diff/apply logic doesn't need to know provider-specific quirks.
- Sources vs. targets — a provider can be a source (read records from) and/or a target (write records to). This is what makes multi-provider replication and migration workflows possible: read from one provider, write to another, or read from a YAML file and write to several providers simultaneously for redundant/multi-vendor DNS hosting.
4. Example Configuration¶
config.yaml
providers:
config:
class: octodns.provider.yaml.YamlProvider
directory: ./config
default_ttl: 3600
enforce_order: false
route53:
class: octodns_route53.Route53Provider
access_key_id: env/AWS_ACCESS_KEY_ID
secret_access_key: env/AWS_SECRET_ACCESS_KEY
zones:
example.com.:
sources:
- config
targets:
- route53
config/example.com.yaml
'':
- type: A
values:
- 192.0.2.10
- 192.0.2.11
- type: MX
values:
- exchange: 10
preference: 10
# (octodns MX format: 'value: 10 mail.example.com.')
www:
type: CNAME
value: example.com.
mail:
type: A
value: 192.0.2.20
_dmarc:
type: TXT
value: "v=DMARC1; p=reject;"
'' (empty string) represents the zone apex, the same role @ plays in a BIND zone file. Note credentials are referenced as env/AWS_ACCESS_KEY_ID rather than embedded in the YAML — octoDNS resolves these from environment variables at runtime, keeping secrets out of the version-controlled config.
5. The Plan/Apply Workflow¶
octoDNS's defining safety feature, directly analogous to Terraform's plan/apply:
# Compute and print a diff between desired (YAML) and actual (provider) state — no changes made
octodns-sync --config-file=config.yaml
# Apply the changes shown by the plan
octodns-sync --config-file=config.yaml --doit
Without --doit, octoDNS only ever shows what it would change — added, removed, and modified records, per provider — making it safe to run in CI on every pull request for review before a human (or an automated merge-triggered apply) commits to the change. This plan-before-apply discipline is the main practical advantage over editing records directly in a provider's console: every DNS change becomes a reviewable, revertible diff instead of an unaudited click.
6. Multi-Provider and Migration Use Cases¶
Because sources and targets are decoupled, common patterns include:
- Multi-provider redundancy: define records once, push identically to two independent DNS providers (e.g., Route 53 and NS1) so a single vendor's outage doesn't take down resolution — the same resilience goal BIND's multi-secondary setup targets, but across vendors rather than just servers.
- Provider migration: set an existing provider as the source to pull current live records into YAML automatically (
octodns-dump), review/clean the result, then add the new provider as a target and cut over — avoiding a manual, error-prone re-entry of every record during a DNS provider switch. - Zone file interop: the
YamlProvidercan coexist with azonefile-format provider, letting octoDNS bridge a hand-maintained BIND zone file into the same reviewable pipeline as cloud-hosted zones.
7. Dynamic Records / Provider-Specific Features¶
Cloud DNS providers support routing features beyond plain static records — Route 53's weighted/latency/geolocation routing (see the dedicated geolocation-routing guide), Cloudflare's proxying — and octoDNS exposes these through provider-specific YAML extensions (octodns.dynamic blocks) rather than forcing everything into a lowest-common-denominator record model:
www:
type: A
dynamic:
pools:
us-east:
values:
- value: 192.0.2.10
eu-west:
values:
- value: 192.0.2.20
rules:
- geos:
- NA
pool: us-east
- pool: eu-west
value: 192.0.2.10 # fallback/default
Not every provider supports every dynamic feature, and octoDNS will refuse (rather than silently degrade) to apply a construct the target provider can't represent — worth checking a given provider's plugin documentation before assuming a feature like this is portable across providers.
8. CI/CD Integration¶
A typical workflow: DNS YAML lives in a Git repo; a CI pipeline runs octodns-sync (plan mode) on every pull request and posts the diff as a PR comment for review; merging to the main branch triggers a second pipeline run with --doit against the real providers. This turns DNS changes into the same reviewed, auditable process as any other infrastructure change, with the repo's Git history serving as the change log BIND/Unbound configs don't have natively.
9. octoDNS vs. Running Your Own Server¶
octoDNS is orthogonal to, not a replacement for, the servers covered in the other guides — it's a management layer above DNS hosting, not a resolver or authoritative daemon itself:
| octoDNS | BIND / CoreDNS / cloud DNS | |
|---|---|---|
| Role | Declarative config management, plan/apply | Actually answers DNS queries |
| Runs continuously? | No — invoked on demand / in CI | Yes — a running daemon or managed service |
| Data source of truth | YAML in version control | Whatever the provider/zone file holds live |
A BIND zone file can be an octoDNS target (YamlProvider writing zone-file syntax, or specific zonefile-format providers), meaning octoDNS can manage even a self-hosted BIND setup's zone files in the same reviewable pipeline as cloud providers — useful if you want IaC-style discipline without moving off self-hosted authoritative servers.
10. Reference Links¶
- Project repository: https://github.com/octodns/octodns
- Provider plugin list: https://github.com/octodns/octodns#providers