Skip to content

Setting Up DNS

This guide walks through creating a DNS zone on the b'nerd platform, adding records, and configuring external-dns for automatic record management from Kubernetes.

Time to complete: ~15 minutes
Prerequisites: An organization and a bearer token. For external-dns, a static API token is recommended.


Step 1 — Create a DNS zone

POST /dns/zones
Authorization: Bearer <token>
Content-Type: application/json

{
  "zone": {
    "name": "example.com",
    "organization_id": "<org-uuid>"
  }
}

Note the id from the response — you'll use it in subsequent calls.


Step 2 — Update your registrar's NS records

The platform assigns authoritative nameservers when a zone is created. Retrieve them:

GET /dns/zones/<zone-id>/records
Authorization: Bearer <token>

Look for the NS records in the response. Update your domain registrar to delegate to the b'nerd nameservers. DNS propagation typically takes a few minutes to a few hours depending on your registrar's TTL.


Step 3 — Add DNS records

Add an A record

POST /dns/zones/<zone-id>/records
Authorization: Bearer <token>
Content-Type: application/json

{
  "record": {
    "name": "www",
    "type": "A",
    "ttl": 300,
    "content": "203.0.113.10"
  }
}

Add a CNAME

POST /dns/zones/<zone-id>/records
Authorization: Bearer <token>
Content-Type: application/json

{
  "record": {
    "name": "blog",
    "type": "CNAME",
    "ttl": 300,
    "content": "myblog.netlify.app."
  }
}

Add MX records (email)

POST /dns/zones/<zone-id>/records
Authorization: Bearer <token>
Content-Type: application/json

{
  "record": {
    "name": "@",
    "type": "MX",
    "ttl": 3600,
    "content": "10 mail.example.com."
  }
}

Step 4 — Update a record

PATCH /dns/zones/<zone-id>/records/www/A
Authorization: Bearer <token>
Content-Type: application/json

{
  "record": {
    "content": "203.0.113.20",
    "ttl": 60
  }
}

Step 5 — Verify domain ownership (optional)

If you plan to use this domain with platform services that require verified ownership (e.g. automatic TLS), verify it:

POST /dns/domains
Authorization: Bearer <token>
Content-Type: application/json

{
  "domain": {
    "name": "example.com",
    "organization_id": "<org-uuid>"
  }
}

Add the TXT record the API provides, then trigger verification:

POST /dns/domains/<domain-id>/verify
Authorization: Bearer <token>

See Domain Verification for full details.


Configure external-dns (Kubernetes)

external-dns can manage DNS records automatically based on Kubernetes Service and Ingress annotations. The b'nerd API exposes a PowerDNS-compatible proxy that external-dns understands natively.

Create a static API token

Generate a static token with dns:read and dns:write scopes through the dashboard. Static tokens are preferred over JWT for long-running automations.

Deploy external-dns

apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
  namespace: external-dns
spec:
  template:
    spec:
      containers:
      - name: external-dns
        image: registry.k8s.io/external-dns/external-dns:v0.14.0
        args:
        - --provider=pdns
        - --pdns-server=https://api.bnerd.cloud/dns/external
        - --pdns-api-key=$(PDNS_API_KEY)
        - --source=ingress
        - --source=service
        - --domain-filter=example.com
        - --txt-owner-id=my-cluster
        env:
        - name: PDNS_API_KEY
          valueFrom:
            secretKeyRef:
              name: external-dns-token
              key: token

Create the secret:

kubectl create secret generic external-dns-token \
  --namespace external-dns \
  --from-literal=token=<your-static-token>

external-dns will now create and update DNS records automatically when you annotate services or ingresses with external-dns.alpha.kubernetes.io/hostname.



Using the dashboard

The dashboard at app.bnerd.cloud covers the full DNS workflow:

  • Create a zone: Services → DNS → New Zone
  • Add and edit records: Zone detail → Records tab
  • Verify domain ownership: Zone detail → Verification tab

Using the CLI

# List DNS zones
bnerd dns zones list

# Create a zone
bnerd dns zones create example.com

# List records in a zone
bnerd dns records list --zone-id <zone-id>

# Add an A record
bnerd dns records create --zone-id <zone-id> --name www --type A --ttl 300 --content 203.0.113.10

# Delete a zone (removes all records)
bnerd dns zones delete <zone-id>

See cli.docs.bnerd.com for the full flag reference.


Using Terraform

resource "bnerd_dns_zone" "primary" {
  name        = "example.com."    # trailing dot required
  kind        = "Native"
  nameservers = ["ns1.bnerd.net.", "ns2.bnerd.net."]
}

resource "bnerd_dns_record" "www" {
  zone_id = bnerd_dns_zone.primary.id
  name    = "www.example.com."
  type    = "A"
  ttl     = 300
  records = ["203.0.113.10"]
}

See Terraform Provider reference for all DNS resource and data source attributes.


Troubleshooting

Symptom Likely cause Fix
NS records not resolving after zone creation Registrar NS records not updated yet Update your registrar's nameservers to the platform NS records (Step 2); wait for propagation
DNS propagation taking > 2 hours High upstream TTL at the registrar Wait for the registrar's existing TTL to expire — nothing to do on the b'nerd side
422 on record create Invalid record content or type Check errors[0].message in the error envelope for the specific validation failure
external-dns not creating records Wrong API key or endpoint Verify the static token has dns:write scope; check --pdns-server is https://api.bnerd.cloud/dns/external
Zone shows no NS records immediately after create Zone is still propagating Wait 30 seconds and re-fetch