Skip to content
cloudflare-dns logo

Cloudflare DNS Skill

cloudflare-dns

Comprehensive guide for managing Cloudflare DNS with Azure integration. Use when configuring Cloudflare as authoritative DNS provider for Azure-hosted applications, managing DNS records via API, setting up API tokens, configuring proxy settings, troubleshooting DNS issues, implementing DNS securi...

SKILL.md

Full skill instructions

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:

PermissionAccessPurpose
Zone > ZoneReadList zones
Zone > DNSEditManage DNS records

Create Token:

  1. Cloudflare Dashboard > My Profile > API Tokens
  2. Create Token > Custom token
  3. Add permissions above
  4. Zone Resources: Specific zones only
  5. (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:[email protected]",
    "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 CaseProxyReason
Web applicationsYesCDN, DDoS protection
REST APIsYesPerformance, security
Static websitesYesCaching, optimization
WebSocketsYesSupported with config

When to Disable Proxy (Gray Cloud)

Use CaseProxyReason
Mail servers (MX)NoSMTP not supported
SSH accessNoNon-HTTP protocol
FTP serversNoNon-HTTP protocol
Custom TCP/​UDPNoOnly HTTP/​HTTPS proxied
VPN endpointsNoDirect 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 "[email protected]"

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

ErrorCauseSolution
401 UnauthorizedInvalid tokenRegenerate API token
403 ForbiddenInsufficient permissionsAdd Zone:Read, DNS:Edit
429 Rate LimitedToo many requestsIncrease interval, use pagination
Record existsDuplicateDelete 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

  1. Scope tokens - Use specific zones, not "All zones"
  2. IP filtering - Restrict to known IPs when possible
  3. Rotate regularly - Every 90 days for production
  4. Store securely - Kubernetes Secrets or Azure Key Vault
  5. 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: [email protected]
    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

More DevOps & CI/CD skills

Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.

6K 472.6K
View

Set up tracing, logging, and monitoring for deployed ADK agents across Cloud Trace, BigQuery, and third-party platforms.

6K 472.6K
View

Enterprise Azure infrastructure architect generating Bicep or Terraform from workload descriptions.

1.5K 454.3K
View
azure-kubernetes logo
DevOps & CI/CD

azure-kubernetes

Plan and configure production-ready Azure Kubernetes Service clusters with Day-0 and Day-1 best practices.

1.5K 447.1K
View

Raw mechanical interfaces fusing Swiss typographic print with military terminal aesthetics. Rigid grids, extreme type scale contrast, utilitarian color, analog degradation effects. For data-heavy dashboards, portfolios, or editorial sites that need to feel like declassified blueprints.

92.7K 354.9K
View
just-scrape logo
DevOps & CI/CD

just-scrape

Web search, scraping, extraction, crawling, and monitoring via ScrapeGraph AI CLI.

69 245K
View

Skill for working with Firebase Hosting (Classic). Use this when you want to deploy static web apps, Single Page Apps (SPAs), or simple microservices. Do NOT use for Firebase App Hosting.

462 159.7K
View

Deploy and manage web apps with Firebase App Hosting. Use this skill when deploying Next.js/Angular apps with backends.

462 159.1K
View
deploy-to-vercel logo
DevOps & CI/CD

deploy-to-vercel

Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".

31.9K 146.6K
View
programmatic-seo logo
DevOps & CI/CD

programmatic-seo

Build SEO-optimized pages at scale using templates, data, and proven playbook patterns.

53.3K 140.1K
View

Design and build isolated, reusable Convex backend components with clear boundaries and app-facing wrappers.

63 123.5K
View

Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".

31.9K 116.1K
View

Coding & apps AI tools

Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View
I
Coding & apps

Imagica

Build a no-code AI app in minutes.

Freemium
View
E
Coding & apps

Emergent.sh

An IDE for code migration from legacy to modern frameworks through coding agents.

Freemium
View
Wonder Dynamics logo
Coding & apps

Wonder Dynamics

Automate CGI animation in live-action scenes

Paid
View
M
Coding & apps

Mixo

Launch a website in seconds with AI.

Paid
View
AI Code Convert logo
Coding & apps

AI Code Convert

Streamline Your Coding Experience with AI Code Helper

Free
View