Cloudflare API Token
External DNS uses a Cloudflare API Token to create, update and delete DNS records in the commonground.nu, openwoo.app and opencatalogi.nl zones. This document explains how to create the token and load it into the cluster.
Token permissions
Use an API Token (not the Global API Key — that has full account access and is unnecessarily broad).
Required permissions:
| Category | Item | Permission |
|---|---|---|
| Zone | DNS | Edit |
Zone Resources:
- Include → Specific zone → commonground.nu
- Include → Specific zone → openwoo.app
- Include → Specific zone → opencatalogi.nl
No other permissions are needed. Do not enable Cloudflare proxy permissions.
Creating the token
- Log in to Cloudflare dashboard
- Go to My Profile → API Tokens → Create Token
- Choose Create Custom Token
- Set:
- Token name:
external-dns-conduction-cluster - Permissions:
Zone→DNS→Edit - Zone Resources:
Include→Specific zone→commonground.nu,openwoo.app,opencatalogi.nl - (Optional) Client IP filtering: restrict to your cluster's egress IP for extra security
- TTL: set an expiry if your policy requires it
- Click Continue to summary → Create Token
- Copy the token immediately — Cloudflare only shows it once
Loading the token into the cluster
kubectl create namespace external-dns
kubectl create secret generic cloudflare-credentials \
-n external-dns \
--from-literal=api-token=<paste-token-here>
Verify:
kubectl get secret cloudflare-credentials -n external-dns
The secret is referenced in external-dns/values.yaml as:
env:
- name: CF_API_TOKEN
valueFrom:
secretKeyRef:
name: cloudflare-credentials
key: api-token
Token rotation
When rotating the token:
1. Create the new token in Cloudflare first
2. Update the secret: kubectl create secret generic cloudflare-credentials -n external-dns --from-literal=api-token=<new-token> --dry-run=client -o yaml | kubectl apply -f -
3. Restart External DNS to pick up the new token: kubectl rollout restart deployment external-dns -n external-dns
4. Verify DNS records are still being managed: check External DNS logs
5. Revoke the old token in Cloudflare
Verifying External DNS works
After bootstrap, check the logs:
kubectl logs -n external-dns -l app.kubernetes.io/name=external-dns -f
Expected output when a record is created:
time="..." level=info msg="Desired change: CREATE roosendaal.migrate.commonground.nu A ..."
time="..." level=info msg="Desired change: CREATE roosendaal.migrate.commonground.nu TXT ..."
time="..." level=info msg="2 record(s) in zone commonground.nu were successfully updated"
The TXT record (conduction-cluster-...) is External DNS's ownership marker — do not delete it manually.
What External DNS manages
- Creates an
A(orCNAME) record for every hostname in an Ingress resource - Creates a
TXTownership record alongside each DNS record - Deletes both records automatically when the Ingress is removed
- Only touches records it owns (identified by
txtOwnerId: conduction-cluster) - Only operates within the
commonground.nu,openwoo.appandopencatalogi.nlzones — all other zones are ignored