Skip to content

DNS Change Workflow

This guide describes how to make and validate DNS changes in the OpsDev.nz repository using the OctoDNS Metaname provider.

Prerequisites

  • Python 3.12+ with dependencies installed via uv sync (pulls in OctoDNS, octodns-metaname, and the op_opsdevnz helpers).
  • Access to the Metaname test API credentials in 1Password (the item Metaname Test API Key in the OpsDev.NZ vault). Production credentials are stored in Metaname Prod API Key.

Zone overview

Zone file Domain Config API endpoint Branch
octodns/zones/opstest.nz.yaml opstest.nz metaname.test.yaml test.metaname.net (sandbox) staging
octodns/zones/testmeup.nz.yaml testmeup.nz metaname.test.yaml test.metaname.net (sandbox) staging
octodns/zones/opsdev.nz.yaml opsdev.nz metaname.prod.yaml metaname.net (live) main

The test zones share a single config (metaname.test.yaml) and target Metaname's sandbox API — safe for experimenting. The production zone uses the live API and only deploys from main.

1. Update zone data

Edit the relevant file under octodns/zones/ to add, modify, or remove records. For example, to add a test A record to opstest.nz:

'test-record':
  - ttl: 3600
    type: A
    value: 203.0.113.1

Use RFC 5737 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) for test records.

If the change requires configuration updates (new providers, processors, transforms), adjust the corresponding file under octodns/configs/.

2. Prepare environment variables

The env/ files document the 1Password secret references. Source the one matching your target environment:

# Test (sandbox API — safe for experimentation)
export OCTODNS_METANAME_SECRET_RESOLVER="op_opsdevnz.octodns_hooks:resolve"
source env/metaname-test.env

# Production (live API)
export OCTODNS_METANAME_SECRET_RESOLVER="op_opsdevnz.octodns_hooks:resolve"
source env/metaname-prod.env

The OCTODNS_METANAME_SECRET_RESOLVER hook bridges OctoDNS to the 1Password helper. The env files set *_REF variables (e.g. METANAME_API_TOKEN_REF) that the resolver reads to fetch credentials from the OpsDev.NZ vault.

The env files are for local development only. CI uses GitLab CI/CD variables pointing to the same 1Password service account.

3. Add and register a new domain

Adding a new domain requires both:

  1. A zone file under octodns/zones/
  2. A matching zone entry in the appropriate file under octodns/configs/

For example, a test domain named example-test.nz needs octodns/zones/example-test.nz.yaml and this entry under zones in octodns/configs/metaname.test.yaml:

zones:
  example-test.nz.:
    sources:
      - zones
    targets:
      - metaname-test

OctoDNS can then plan the records, but Metaname must register the domain before those records can be applied. A missing domain appears in the plan log as Domain name not found.

Register manually first

This is the recommended path while learning or troubleshooting the workflow:

# The CLI defaults to Metaname's test API.
octodns-metaname check example-test.nz
octodns-metaname register example-test.nz --term 12 --confirm

The registration command checks availability again before registering. It requires --confirm, consumes Metaname test credit, and defaults to Metaname hosted DNS. Re-run the OctoDNS dry-run after registration to confirm that the plan now contains only the expected record changes.

The production API is selected only with --production, placed before the command, and incurs a real charge:

octodns-metaname --production check example.nz
octodns-metaname --production register example.nz --term 12 --confirm

Register during the manual apply job

registration during the manual apply job: Starting with octodns-metaname 0.2.1, a provider may instead register a missing domain immediately before applying its records. Enable this explicitly on the test provider: registration during the manual apply job:

metaname-test:
  class: octodns_metaname.MetanameProvider
  base_url: https://test.metaname.net/api/1.1
  auto_register_domains: true
  registration_term: 12

The plan job remains a dry-run and does not register anything. Registration happens only when the manual apply_test job runs with --doit. The apply job first registers the missing domain and then creates its records.

Leave automatic registration disabled until the client has been tested manually. Non-test API endpoints require the additional allow_production_registration: true safeguard. The contact and API credential references must also be available to the CI secret resolver before running the apply job.

4. Validate locally

Run the standard validation sequence from the repository root:

# Test zone (dry-run)
octodns-validate --config-file octodns/configs/metaname.test.yaml
octodns-sync --config-file octodns/configs/metaname.test.yaml

# Production zone (dry-run)
octodns-validate --config-file octodns/configs/metaname.prod.yaml
octodns-sync --config-file octodns/configs/metaname.prod.yaml

Without --doit, octodns-sync performs a dry-run and prints the proposed DNS changes as a plan. Review the output for any unexpected diffs before committing. Re-run with --doit only when you are ready to push updates to the Metaname API.

5. Commit and push

Create a new branch, commit the zone/config changes, and push to GitLab.

Target staging for test zone changes (opstest.nz, testmeup.nz). Target main for production zone changes (opsdev.nz).

The CI pipeline triggers automatically when files matching these patterns change:

  • octodns/configs/**
  • octodns/zones/**
  • modules/octodns-metaname/**
  • scripts/**
  • env/metaname-*.env

6. Review the plan

The plan_test job (on staging branches/MRs) and plan_prod job (on main branches/MRs) run automatically. They:

  1. Run octodns-validate against the appropriate config
  2. Detect which zones changed via scripts/octodns_changed_zones.py
  3. Run octodns-sync (dry-run) and tee the output to an artifact (octodns-plan-test.txt or octodns-plan-prod.txt, 3-day expiry)

Download the plan artifact from the pipeline page to verify the proposed changes match your local dry-run.

7. Apply changes

Once the plan looks correct, manually trigger the apply job:

Job Zone Branch How to trigger
apply_test opstest.nz, testmeup.nz staging Click Play on the apply_test job in the pipeline
apply_prod opsdev.nz main Click Play on the apply_prod job in the pipeline

Both apply jobs are manual (when: manual) — they never run automatically. They use the same op_opsdevnz.octodns_hooks:resolve hook to fetch credentials from the 1Password service account configured in the project's CI/CD variables.

8. Update documentation

If the workflow introduced new processes, update the Zensical pages under docs/ so the wider team can follow the same steps. Regenerate the site locally with zensical build or zensical serve and include the Markdown updates with your merge request.