cloudflare-dns

Complete Cloudflare DNS operations via REST API with focus on Azure integration.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "cloudflare-dns" with this command: npx skills add julianobarbosa/claude-code-skills/julianobarbosa-claude-code-skills-cloudflare-dns

Cloudflare DNS Skill

Complete Cloudflare DNS operations via REST API with focus on Azure integration.

Overview

This skill covers Cloudflare DNS management for Azure-hosted workloads, including:

  • API token configuration and security

  • DNS record management (A, AAAA, CNAME, TXT, MX)

  • Proxy settings (orange/gray cloud)

  • External-DNS integration for Kubernetes

  • Troubleshooting and monitoring

Authentication

API Token (Recommended)

Create scoped API tokens instead of using Global API Key:

Required Permissions:

Permission Access Purpose

Zone > Zone Read List zones

Zone > DNS Edit Manage DNS records

Create Token:

  • Cloudflare Dashboard > My Profile > API Tokens

  • Create Token > Custom token

  • Add permissions above

  • Zone Resources: Specific zones only

  • (Optional) IP filtering for extra security

Environment Setup:

Export for API calls

export CF_API_TOKEN="your-api-token" export CF_ZONE_ID="your-zone-id"

Get zone ID

curl -s -X GET "https://api.cloudflare.com/client/v4/zones"
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result[] | {name, id}'

Token Verification

Verify token is valid

curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify"
-H "Authorization: Bearer $CF_API_TOKEN"

Quick Reference

List DNS Records

All records

curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records"
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result[] | {name, type, content, proxied}'

Filter by type

curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?type=A"
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result[]'

Search by name

curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?name=app.example.com"
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result[]'

Create DNS Records

A Record (proxied)

curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{ "type": "A", "name": "app", "content": "20.185.100.50", "ttl": 1, "proxied": true }'

A Record (DNS-only)

curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{ "type": "A", "name": "mail", "content": "20.185.100.51", "ttl": 3600, "proxied": false }'

CNAME Record

curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{ "type": "CNAME", "name": "www", "content": "app.example.com", "ttl": 1, "proxied": true }'

TXT Record

curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{ "type": "TXT", "name": "_dmarc", "content": "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com", "ttl": 3600 }'

MX Record

curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{ "type": "MX", "name": "@", "content": "mail.example.com", "priority": 10, "ttl": 3600 }'

Update DNS Records

Get record ID first

RECORD_ID=$(curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?name=app.example.com&type=A"
-H "Authorization: Bearer $CF_API_TOKEN" | jq -r '.result[0].id')

Update record

curl -X PUT "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$RECORD_ID"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{ "type": "A", "name": "app", "content": "20.185.100.60", "ttl": 1, "proxied": true }'

Patch (partial update)

curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$RECORD_ID"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{"proxied": false}'

Delete DNS Records

Get record ID

RECORD_ID=$(curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?name=old.example.com"
-H "Authorization: Bearer $CF_API_TOKEN" | jq -r '.result[0].id')

Delete

curl -X DELETE "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$RECORD_ID"
-H "Authorization: Bearer $CF_API_TOKEN"

Proxy Settings (Orange/Gray Cloud)

When to Enable Proxy (Orange Cloud)

Use Case Proxy Reason

Web applications Yes CDN, DDoS protection

REST APIs Yes Performance, security

Static websites Yes Caching, optimization

WebSockets Yes Supported with config

When to Disable Proxy (Gray Cloud)

Use Case Proxy Reason

Mail servers (MX) No SMTP not supported

SSH access No Non-HTTP protocol

FTP servers No Non-HTTP protocol

Custom TCP/UDP No Only HTTP/HTTPS proxied

VPN endpoints No Direct connection needed

Toggle Proxy via API

Enable proxy

curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$RECORD_ID"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{"proxied": true}'

Disable proxy

curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$RECORD_ID"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{"proxied": false}'

External-DNS Integration

Kubernetes Secret

kubectl create namespace external-dns

kubectl create secret generic cloudflare-api-token
--namespace external-dns
--from-literal=cloudflare_api_token="$CF_API_TOKEN"

Helm Values (kubernetes-sigs/external-dns)

fullnameOverride: external-dns

provider: name: cloudflare

env:

  • name: CF_API_TOKEN valueFrom: secretKeyRef: name: cloudflare-api-token key: cloudflare_api_token

extraArgs: cloudflare-proxied: true cloudflare-dns-records-per-page: 5000

sources:

  • service
  • ingress

domainFilters:

  • example.com

txtOwnerId: "aks-cluster-name" # MUST be unique per cluster txtPrefix: "_externaldns." policy: upsert-only # Production: NEVER use sync interval: "5m"

logLevel: info logFormat: json

resources: requests: memory: "64Mi" cpu: "25m" limits: memory: "128Mi"

serviceMonitor: enabled: true interval: 30s

Ingress Annotations

metadata: annotations: # Hostname for External-DNS external-dns.alpha.kubernetes.io/hostname: "app.example.com"

# Custom TTL
external-dns.alpha.kubernetes.io/ttl: "300"

# Override proxy setting
external-dns.alpha.kubernetes.io/cloudflare-proxied: "true"

# Multiple hostnames
external-dns.alpha.kubernetes.io/hostname: "app.example.com,www.example.com"

Zone Management

List Zones

curl -s "https://api.cloudflare.com/client/v4/zones"
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result[] | {name, id, status, plan: .plan.name}'

Get Zone Details

curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID"
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result'

Zone Settings

Get all settings

curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/settings"
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result[] | {id, value}'

Get specific setting

curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/settings/ssl"
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result'

Update SSL mode

curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/settings/ssl"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{"value": "full"}'

Export/Import DNS Records

Export (BIND Format)

curl -s "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/export"
-H "Authorization: Bearer $CF_API_TOKEN" > dns-backup-$(date +%Y%m%d).txt

Import (BIND Format)

curl -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/import"
-H "Authorization: Bearer $CF_API_TOKEN"
-F "file=@dns-backup.txt"

Troubleshooting

DNS Verification

Query Cloudflare DNS (1.1.1.1)

dig @1.1.1.1 app.example.com A dig @1.1.1.1 app.example.com AAAA

Check if proxied (returns Cloudflare IP)

dig +short app.example.com

Proxied: 104.x.x.x or 172.64.x.x

DNS-only: Your actual IP

Check TXT records (External-DNS ownership)

dig @1.1.1.1 TXT _externaldns.app.example.com

Full trace

dig +trace app.example.com

Check nameservers

dig NS example.com +short

Common Errors

Error Cause Solution

401 Unauthorized Invalid token Regenerate API token

403 Forbidden Insufficient permissions Add Zone:Read, DNS:Edit

429 Rate Limited Too many requests Increase interval, use pagination

Record exists Duplicate Delete or update existing record

External-DNS Logs

Watch logs

kubectl logs -n external-dns deployment/external-dns -f

Check for Cloudflare errors

kubectl logs -n external-dns deployment/external-dns | grep -i cloudflare

Check sync status

kubectl logs -n external-dns deployment/external-dns | grep -i "All records are already up to date"

Security Best Practices

API Token Security

  • Scope tokens - Use specific zones, not "All zones"

  • IP filtering - Restrict to known IPs when possible

  • Rotate regularly - Every 90 days for production

  • Store securely - Kubernetes Secrets or Azure Key Vault

  • Audit usage - Check Cloudflare audit logs

Token Rotation

1. Create new token in Cloudflare dashboard

2. Update Kubernetes secret

kubectl create secret generic cloudflare-api-token
--namespace external-dns
--from-literal=cloudflare_api_token="NEW_TOKEN"
--dry-run=client -o yaml | kubectl apply -f -

3. Restart External-DNS

kubectl rollout restart deployment external-dns -n external-dns

4. Verify

kubectl logs -n external-dns deployment/external-dns | head -20

5. Revoke old token in Cloudflare dashboard

Rate Limits

Cloudflare API Limits:

  • 1,200 requests per 5 minutes (per account)

  • 100 requests per 5 minutes (per zone, for some endpoints)

Mitigation:

External-DNS optimizations

extraArgs: cloudflare-dns-records-per-page: 5000 # Max pagination zone-id-filter: "specific-zone-id" # Reduce API calls

interval: "10m" # Less frequent polling

Azure Integration

cert-manager with Cloudflare DNS-01

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-cloudflare spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-cloudflare-key solvers: - dns01: cloudflare: apiTokenSecretRef: name: cloudflare-api-token key: api-token selector: dnsZones: - example.com

AKS Ingress Configuration

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myapp annotations: cert-manager.io/cluster-issuer: letsencrypt-cloudflare external-dns.alpha.kubernetes.io/cloudflare-proxied: "true" spec: ingressClassName: nginx tls: - hosts: - app.example.com secretName: app-tls rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: myapp port: number: 80

References

  • references/api-reference.md

  • Complete Cloudflare DNS API documentation

  • references/azure-integration.md

  • Azure-specific patterns and configurations

  • scripts/cloudflare-dns.sh

  • Helper script for common operations

  • Cloudflare API Documentation

  • External-DNS Cloudflare Tutorial

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

obsidian-vault-management

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

zabbix

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

neovim

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

obsidian

No summary provided by upstream source.

Repository SourceNeeds Review