araelespinosa.dev
Open Source

dns-sync

One binary. All your DNS.

A lightweight alternative to OctoDNS built on .NET. A single compiled binary that synchronizes your DNS records across providers and zones — no Python runtime, no complex setup, no lock-in.

What it does

Plan before applying

preview every create, update, and delete across all zones before a single record is touched

GitOps workflow

open a PR, get a diff comment, merge to apply; one uses: line in GitHub Actions

Multi-zone, single source

define records once in a zone file, deploy to every domain automatically

Multi-provider targets

sync to Cloudflare, Route 53, GCP Cloud DNS, Porkbun, and GoDaddy simultaneously

Live provider diff

compare two providers directly with dns-sync diff, no zone file needed

Drift detection

dns-sync drift catches live record changes before they cause incidents, with JSON output for CI alerting

Zone groups

apply one zone file to every domain in a provider automatically, no per-domain config needed

Import from providers

pull live records from any provider into a local YAML zone file

Validate before apply

catch config and zone file errors before any network call is made

Single compiled binary

one self-contained executable, no runtime or dependencies to install

terminal
# Download the binary (no installation required)
curl -L https://github.com/cl8dep/dns-sync/releases/latest/download/dns-sync-linux-x64 \
  -o dns-sync && chmod +x dns-sync

# Preview DNS changes
./dns-sync plan --config dns.yaml

# Apply DNS changes
./dns-sync apply --config dns.yaml

Feature spotlight

Multi-zone, single source of truth

Define your DNS records once. Deploy to every domain. Both example.com and example.eu point to the same yaml_source, so the same zone file is applied to all of them — no duplication, no drift.

dns.yaml — config

dns.yaml
providers:
  yaml_source:
    type: yaml
    directory: ./domains
  cloudflare:
    type: cloudflare
    api_token: ${CLOUDFLARE_API_TOKEN}
  route53:
    type: route53
    access_key_id: ${AWS_ACCESS_KEY_ID}
    secret_access_key: ${AWS_SECRET_ACCESS_KEY}

zones:
  example.com.:
    source: yaml_source
    targets:
      - cloudflare
      - route53
  example.eu.:
    source: yaml_source
    targets:
      - cloudflare

domains/example.yaml — records

domains/example.yaml
# domains/zones.yaml
# One file. Applied to every zone.

www:
  type: CNAME
  ttl: 3600
  value: app.example.com.

api:
  type: A
  ttl: 60
  value: 203.0.113.10

Each zone maps to its own YAML file. Add a new domain, create its file, point it to the same source — done.

Feature spotlight

Zone groups — scale without repetition

Managing dozens of domains? zone_groups discovers every domain in a provider and applies your zone files automatically — no per-domain config block required. Mix individual zones and groups in the same config for full control over complex multi-provider setups.

dns.yaml — advanced config

dns.yaml
providers:
  yaml_source:
    type: yaml
    directory: ./domains
  cloudflare:
    type: cloudflare
    api_token: ${CLOUDFLARE_API_TOKEN}
  gcp:
    type: gcp_cloud_dns
    project: my-gcp-project

zone_groups:
  # Sync all Cloudflare domains that match the pattern
  production:
    source: yaml_source
    targets:
      - cloudflare
    include_pattern: ".*\.com\.$"  # only .com domains
    exclude_pattern: "staging\..*" # skip staging domains

# Individual zones for special requirements
zones:
  internal.example.com.:
    source: yaml_source
    targets:
      - gcp

zone_groups discovers all domains from the provider at runtime. Use include_pattern and exclude_pattern regex filters to control which domains are synced.

Individual zones still work alongside groups — use them for domains that need a different source or special targets.

In action

See the plan before you apply

Run plan to preview every change across all zones — zero surprises when you apply.

terminal
$ dns-sync plan -c config.yaml --config-file .env --verbose

[DBG] Auto-detected .env in current directory (2 variable(s) set)
Loading config from config.yaml
✓ Config valid (2 zone(s), 2 provider(s))

Running pre-flight checks...
✓ Source provider 'source' reachable
[DBG] POST https://api.cloudflare.com/client/v4/zones
[DBG] ← 200 (312 bytes)
[INF] Cloudflare API authenticated successfully
✓ Target provider 'cloudflare' reachable

Zone: example.com. → cloudflare
+ example.com. MX 3600
10 mail.example.com., 20 mail2.example.com.
+ example.com. TXT 600
"v=spf1 include:_spf.google.com ~all"
+ www.example.com. CNAME 3600
app.example.com.
+ api.example.com. A 300
203.0.113.10, 203.0.113.11
+ _dmarc.example.com. TXT 600
"v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"

5 create(s)

5 total change(s) — run dns-sync apply to apply.

GitOps workflow

Review before you apply.

Open a PR, see exactly what changes. Merge to deploy.

zones/example.com.yaml
www:
type: CNAME
ttl: 3600
value: app.example.com.
api:
type: A
ttl: 60
value: 203.0.113.42
01Edit your zone file

Commit a change to any zone file and open a pull request.

github-actionsbot
⚠ Changes pending
Full plan output
# Zone: example.com. → route53
- mail._domainkey.example.com. CNAME 1 (ttl only)
+ mail._domainkey.example.com. CNAME 3600 (ttl only)
- api.example.com. A 1
- 203.0.113.42
# 1 update(s), 1 delete(s)
# Zone: example.org. → cloudflare
# No changes
02Review the plan

dns-sync posts a diff comment showing every change before it lands.

All checks passed
Plan
Successful
Validate
Successful
Lint
Successful
03Merge to apply

Merge and the exact reviewed plan is applied — no re-reads, no drift.

Ready to sync your DNS?

The Getting Started guide walks you through installation, writing your first config, and running your first plan in under 5 minutes.

Getting Started

Compatibility

DNS providers

Multiple DNS providers are fully supported today, with more on the roadmap — contributions welcome.

ProviderPlanApply
Google Cloud DNS
AvailableAvailable
Cloudflare
AvailableAvailable
Porkbun
AvailableAvailable
Amazon Route 53
AvailableAvailable
GoDaddy
AvailableAvailable

Open Source

Get involved

dns-sync is free and open source. Whether you use it, break it, or improve it — every contribution matters.