GitHub Actions DNS Workflows
Practical GitHub Actions patterns for DNSControl and Terraform DNS changes, including pull-request previews, protected applies, secrets, and drift checks.
TL;DR
A good GitHub Actions DNS workflow previews changes on pull requests and applies only after merge to a protected branch. Keep write credentials out of untrusted PR contexts, use environment approvals for production, and run a scheduled drift check so manual DNS edits do not survive unnoticed.
What you'll learn
- Build a pull-request DNS preview workflow
- Apply DNS changes safely from protected branches
- Store DNS credentials correctly in GitHub Actions
- Add scheduled drift detection
GitHub Actions is a good fit for DNS changes if the workflow has a hard boundary:
pull request = validate and preview
main branch = applyDo not let every branch mutate production DNS.
Repository Layout
A simple DNS-as-code repository can look like this:
dns/
dnsconfig.js # DNSControl
creds.example.json
zones/
example.com.js
terraform/
dns/
main.tf
variables.tf
versions.tfPick one main path. Mixing Terraform, DNSControl, dashboard edits, and scripts for the same zone creates drift.
DNSControl Preview on Pull Requests
This workflow checks DNSControl config and previews the diff.
name: dnscontrol-preview
on:
pull_request:
paths:
- "dns/**"
- ".github/workflows/dnscontrol-preview.yml"
jobs:
preview:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
steps:
- uses: actions/checkout@v4
- name: Install DNSControl
run: |
curl -L https://github.com/StackExchange/dnscontrol/releases/latest/download/dnscontrol-Linux -o /usr/local/bin/dnscontrol
chmod +x /usr/local/bin/dnscontrol
- name: Check DNS config
working-directory: dns
run: dnscontrol check
- name: Preview DNS changes
working-directory: dns
env:
DNSCALE_API_KEY: ${{ secrets.DNSCALE_READ_TOKEN }}
run: dnscontrol previewUse a read-capable token for preview where possible. If your provider requires write-scoped credentials even for preview, do not run this workflow on untrusted forked pull requests.
DNSControl Apply After Merge
Apply only from main.
name: dnscontrol-apply
on:
push:
branches: ["main"]
paths:
- "dns/**"
jobs:
apply:
runs-on: ubuntu-latest
environment: production
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Install DNSControl
run: |
curl -L https://github.com/StackExchange/dnscontrol/releases/latest/download/dnscontrol-Linux -o /usr/local/bin/dnscontrol
chmod +x /usr/local/bin/dnscontrol
- name: Apply DNS changes
working-directory: dns
env:
DNSCALE_API_KEY: ${{ secrets.DNSCALE_PRODUCTION_TOKEN }}
run: dnscontrol pushUse GitHub environment protection for production so a human approval is required before the job receives production secrets.
Terraform Plan on Pull Requests
For Terraform-managed DNS:
name: terraform-dns-plan
on:
pull_request:
paths:
- "terraform/dns/**"
jobs:
plan:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
defaults:
run:
working-directory: terraform/dns
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform fmt
run: terraform fmt -check
- name: Terraform init
run: terraform init -input=false
- name: Terraform validate
run: terraform validate
- name: Terraform plan
env:
DNSCALE_API_KEY: ${{ secrets.DNSCALE_READ_TOKEN }}
run: terraform plan -input=falseIf your plan needs access to production state, keep that state access out of untrusted PRs.
Terraform Apply After Merge
name: terraform-dns-apply
on:
push:
branches: ["main"]
paths:
- "terraform/dns/**"
jobs:
apply:
runs-on: ubuntu-latest
environment: production
defaults:
run:
working-directory: terraform/dns
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform init
run: terraform init -input=false
- name: Terraform apply
env:
DNSCALE_API_KEY: ${{ secrets.DNSCALE_PRODUCTION_TOKEN }}
run: terraform apply -auto-approve -input=falseFor higher-risk zones, remove -auto-approve and use an environment approval gate before apply.
Scheduled Drift Check
Drift checks catch manual dashboard edits.
name: dns-drift-check
on:
schedule:
- cron: "17 6 * * *"
workflow_dispatch:
jobs:
drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install DNSControl
run: |
curl -L https://github.com/StackExchange/dnscontrol/releases/latest/download/dnscontrol-Linux -o /usr/local/bin/dnscontrol
chmod +x /usr/local/bin/dnscontrol
- name: Preview drift
working-directory: dns
env:
DNSCALE_API_KEY: ${{ secrets.DNSCALE_READ_TOKEN }}
run: dnscontrol previewTurn this into an alert if the tool exits differently when drift exists. The exact exit-code behavior depends on the tool and provider.
Secret Rules
Use separate secrets:
DNSCALE_READ_TOKEN
DNSCALE_STAGING_TOKEN
DNSCALE_PRODUCTION_TOKENPrefer:
- zone-scoped tokens
- separate staging and production zones
- no production secrets in forked PRs
- GitHub environment approval for production
- regular rotation
Review Checklist
Before approving a DNS PR:
- Does the preview match the description?
- Are deleted records intentional?
- Are MX, SPF, DKIM, DMARC, CAA, and DS changes reviewed by the right owner?
- Are TTL changes planned around cache behavior?
- Is rollback obvious?
- Does this change affect certificate issuance or email delivery?
Related Reading
Frequently asked questions
- Should GitHub Actions apply DNS changes from pull requests?
- No. Pull requests should run validation and preview. Apply should run only after merge to a protected branch, ideally behind a production environment approval.
- Can I expose DNS secrets to forked pull requests?
- No. Treat forked pull requests as untrusted. Do not run write-token workflows in that context.
- Where do I put the DNScale API key?
- Store it as a GitHub Actions secret or in a secret manager. Prefer zone-scoped API keys and separate production from staging.
- Should I use Terraform or DNSControl in GitHub Actions?
- Use Terraform when DNS is part of broader infrastructure state. Use DNSControl when you want DNS-specific diffs and multi-provider DNS workflows.
- How often should drift checks run?
- Daily is enough for many teams. Run more often for production zones where manual emergency edits happen.
- How do I roll back a DNS change?
- Revert the commit and let the apply workflow push the previous record state. For migrations, prepare rollback before the change window.
Related guides
Automation
Managing DNS with Terraform
Learn how to manage your DNS zones and records as Infrastructure as Code using the DNScale Terraform Provider.
Automation
Managing DNS with DNSControl
Learn how to manage your DNS zones and records as code using DNSControl with the DNScale provider. Define your entire DNS configuration in JavaScript.
Automation
DNS for Cloud Infrastructure ā Best Practices and Architecture
Learn cloud DNS best practices including service discovery, multi-cloud strategies, automation with Terraform, and TTL optimization for dynamic infrastructure.
Automation
DNS as Code Best Practices
A practical guide to managing DNS as code with ownership, review, previews, drift detection, scoped credentials, and safe migration patterns.
Ready to manage your DNS with confidence?
DNScale provides anycast DNS hosting with a global network, real-time analytics, and an easy-to-use API.
Start free