Cloudflare DNS Management

Adding and modifying DNS records via Cloudflare API, including Clerk custom domain setup

Overview

All SanMarcSoft domains use Cloudflare for DNS. Records are managed via the Cloudflare API using the API token stored in the pass store. DNS changes should be made via API (not the dashboard) to maintain an audit trail.

Prerequisites

  • Cloudflare API token: pass cloudflare/api-token
  • Zone IDs are per-domain. Look up via API or Cloudflare dashboard.

Common Zone IDs

DomainZone ID Location
sanmarcsoft.compass cloudflare/zones/sanmarcsoft-com
verifieddit.compass cloudflare/zones/verifieddit-com
matthewstevens.orgpass cloudflare/zones/matthewstevens-org

Procedure: Add a DNS Record

Step 1: Identify the zone

1
2
ZONE_ID=$(pass cloudflare/zones/<domain>)
CF_TOKEN=$(pass cloudflare/api-token)

Step 2: Create the record

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "CNAME",
    "name": "subdomain.example.com",
    "content": "target.example.com",
    "ttl": 1,
    "proxied": false
  }'

Note: ttl: 1 means “automatic” (Cloudflare manages TTL). Set proxied: false for records that must not go through Cloudflare proxy (e.g., Clerk verification records).

Step 3: Verify

1
2
curl -s "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=subdomain.example.com" \
  -H "Authorization: Bearer ${CF_TOKEN}" | jq '.result[]'

Example: Clerk Custom Domain DNS (verifieddit.com)

Clerk requires 5 DNS records for a custom domain setup. These were created for clerk.verifieddit.com:

Record 1: Frontend API CNAME

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "CNAME",
    "name": "clerk.verifieddit.com",
    "content": "frontend-api.clerk.services",
    "ttl": 1,
    "proxied": false
  }'

Record 2: Accounts CNAME

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Points accounts subdomain to Clerk
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "CNAME",
    "name": "accounts.verifieddit.com",
    "content": "accounts.clerk.services",
    "ttl": 1,
    "proxied": false
  }'

Record 3: DKIM (clk._domainkey)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "CNAME",
    "name": "clk._domainkey.verifieddit.com",
    "content": "dkim1.f4g7h8j9.clerk.services",
    "ttl": 1,
    "proxied": false
  }'

Record 4: DKIM (clk2._domainkey)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "CNAME",
    "name": "clk2._domainkey.verifieddit.com",
    "content": "dkim2.f4g7h8j9.clerk.services",
    "ttl": 1,
    "proxied": false
  }'

Record 5: Mail CNAME (clkmail)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "CNAME",
    "name": "clkmail.verifieddit.com",
    "content": "mail1.f4g7h8j9.clerk.services",
    "ttl": 1,
    "proxied": false
  }'

Important Notes for Clerk DNS

  • All Clerk DNS records MUST have proxied: false – Clerk needs direct access for SSL certificate provisioning.
  • If records are proxied, Clerk will fail to verify ownership and SSL certificates will not provision.
  • After creating all 5 records, wait up to 24 hours for Clerk to verify and provision the SSL certificate.
  • The dkim1, dkim2, and mail1 CNAME targets are unique per Clerk instance – get the exact values from the Clerk Dashboard under “Domains”.

Procedure: List All DNS Records for a Zone

1
2
curl -s "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?per_page=100" \
  -H "Authorization: Bearer ${CF_TOKEN}" | jq '.result[] | {name, type, content, proxied}'

Procedure: Delete a DNS Record

1
2
3
RECORD_ID="<record-id-from-list>"
curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
  -H "Authorization: Bearer ${CF_TOKEN}"

Procedure: Update a DNS Record

1
2
3
4
5
6
7
RECORD_ID="<record-id-from-list>"
curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "content": "new-target.example.com"
  }'

Troubleshooting

  • Record already exists: Check for existing records with the same name before creating. Use the list endpoint to verify.
  • SSL not provisioning (Clerk): Ensure proxied: false on all Clerk DNS records. Cloudflare proxy interferes with Clerk’s certificate issuance.
  • Propagation delay: Changes typically propagate within seconds for Cloudflare-managed DNS. External verification (e.g., Clerk) may take up to 24 hours.