DNS as code. One binary.
Sync DNS records across providers from YAML zone files — no runtime, no dependencies.
dns-sync plan -c config.yaml # Preview changes
dns-sync apply -c config.yaml # Apply changesYou define your DNS zones as YAML files. dns-sync reads them and syncs your DNS providers to match — creating, updating, or deleting records as needed.
It works like Terraform for DNS: plan shows what would change, apply makes it happen.
Why are you using Terraform for DNS? Don't you love yourself?
| dns-sync | Terraform | |
|---|---|---|
| State file | None. Your DNS provider is the state. | A .tfstate you must store, lock, back up and pray over. |
| Adding a record | One line of YAML. | A resource block, a unique name, and a quiet moment of reflection. |
| Same records on 3 providers | Add 3 targets. Done. | Write it 3 times. Or write a module. Then maintain the module. |
| Switching providers | Change one line in config.yaml. |
Rewrite the resources, terraform state mv, cancel your weekend. |
| Adopting an existing zone | dns-sync import |
terraform import, one record at a time, until the heat death of the universe. |
| Someone clicked around in the dashboard | dns-sync drift tells you. |
plan tells you, if the state file agrees. It rarely agrees. |
| Install | One binary. | The CLI, the providers, a backend, and a lock table. |
| Your therapist's opinion | Proud of you. | Concerned. |
Already managing everything else in Terraform with a single DNS provider? Fine, stay there. We won't judge. Much.
Thanks to @cuza for asking the question that started this section.
| Feature | Description |
|---|---|
| DNS sync | Sync records across providers from YAML zone files — creates, updates, or deletes to match desired state |
| Plan before applying | dns-sync plan shows every change that would be made before a single record is touched |
| Multi-zone, single source | One zone file applied to multiple domains — define records once, deploy everywhere |
| Multi-provider targets | Sync the same records to Cloudflare, Route 53, GCP Cloud DNS, and more simultaneously |
| GitOps workflow | Open a PR → get a diff comment → merge to apply. One uses: line in GitHub Actions is all it takes |
| Saved plan artifacts | --save-plan captures a signed plan; --from-plan applies exactly what was reviewed — no re-reads, no drift |
| Live provider comparison | dns-sync diff compares two providers directly without a zone file |
| Import from providers | dns-sync import pulls live records from any provider into a local YAML zone file |
| Validation | dns-sync validate catches config and zone file errors before any network call is made |
| JSON Schema | Zone files and config.yaml ship with JSON Schemas — get autocomplete and inline errors in VS Code |
| Single binary | One self-contained binary, no runtime or dependencies — download and run |
| Cross-platform | Native binaries for Linux (x64), macOS (Apple Silicon + Intel) |
| Provider | Type | Read | Write |
|---|---|---|---|
| YAML files | yaml |
✓ | — |
| Cloudflare | cloudflare |
✓ | ✓ |
| GCP Cloud DNS | gcp_cloud_dns |
✓ | ✓ |
| Porkbun | porkbun |
✓ | ✓ |
| AWS Route 53 | route53 |
✓ | ✓ |
Supported record types: A, AAAA, CNAME, MX, TXT, NS, CAA, SRV
For the full list including planned and unsupported types, see Record Types in the wiki.
# Detects OS and CPU (Linux x64/arm64, macOS x64/arm64)
curl -fsSL https://raw.githubusercontent.com/cl8dep/dns-sync/main/install.sh | sh
# Pin a version or choose the directory (default: ~/.local/bin)
curl -fsSL https://raw.githubusercontent.com/cl8dep/dns-sync/main/install.sh \
| DNS_SYNC_INSTALL_DIR=/usr/local/bin sh -s v0.12.0Binaries for each platform are also on the releases page.
Shell completion (add to ~/.bashrc or ~/.zshrc to persist):
source <(dns-sync completions bash) # bash
source <(dns-sync completions zsh) # zsh- Getting Started — install, first config, first sync
- Configuration Reference — all providers and options
- Zone File Format — record types and syntax
- CI/CD Integration — GitHub Actions, GitOps workflow
Measured with hyperfine on ubuntu-latest (linux/x64) — dns-sync 0.0.0-dev+b5377a7e0398c19c4ce40847005568299df34c41, octoDNS 1.16.0. Updated 2026-04-19.
Startup time (--help)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
dns-sync |
95.6 ± 2.7 | 93.5 | 106.4 | 1.00 |
octodns-sync |
117.3 ± 2.0 | 114.5 | 121.5 | 1.23 ± 0.04 |
Plan time (YAML → YAML, no network)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
dns-sync |
142.6 ± 3.4 | 137.3 | 150.4 | 1.00 |
octodns-sync |
164.5 ± 2.9 | 159.8 | 171.8 | 1.15 ± 0.03 |
See CONTRIBUTING.md.
MIT — see LICENSE