Overview

Cloudflare DNS decides whether a hostname is proxied (orange cloud: Cloudflare’s anycast IPs answer, and caching, Rules, Workers, and WAF apply) or DNS-only (grey cloud: plain authoritative DNS that returns your origin IP). Proxy by default; grey-cloud only what the proxy cannot carry.

Proxy every hostname that serves web traffic

Only A, AAAA, and CNAME records can be proxied. Proxy the apex (@), www, and each web subdomain, and pair it with SSL/TLS Full (strict) (cloudflare). The origin IP stays hidden only if no DNS-only record, old DNS history, or outbound mail header leaks it, and the origin firewall accepts web traffic from Cloudflare’s published IP ranges alone.

Grey-cloud mail, verification, and non-HTTP records

  • MX records and the host they point to (mail.example.com): MX and TXT are always DNS-only, and proxying the mail host breaks SMTP, IMAP, and POP3.
  • Verification TXT records (Google, Vercel, GitHub, ACME): the verifier reads the raw record.
  • Non-HTTP services (SSH, game servers, VPN): the proxy carries HTTP(S) only. Cloudflare Spectrum proxies other TCP and UDP protocols; availability depends on plan (protocols per plan).

Use a flattened CNAME for managed hosts and an A record for a fixed IP

A standard CNAME cannot sit at the apex because the apex also carries SOA and NS records. Cloudflare flattens a CNAME at the apex: it resolves the target and answers with A/AAAA records.

  • Managed hosts (vercel, github-pages, Netlify): flattened CNAME, so the provider can change IPs freely.
  • A VPS with a fixed IP (hostinger-vps): A record, plus AAAA if the origin has IPv6. Proxied records answer on IPv6 at the edge either way.
  • Subdomains: a plain CNAME.

Treat TTL 1 as Auto, not one second

The API, Terraform provider, and zone exports write Auto as 1. Proxied records are always Auto (300 seconds) and cannot be edited. DNS-only records accept 60 seconds (30 on Enterprise) up to 1 day, per Cloudflare’s TTL docs. Applying an exported zone literally at another provider yields a 1-second TTL, so translate on migration. Lower TTLs to 300 at least 24 hours before a cutover and raise them after (namecheap-dns uses the same playbook).

Enable DNSSEC and publish the DS record at the registrar

  1. Enable DNSSEC in the Cloudflare DNS dashboard; Cloudflare shows a DS record.
  2. Paste the DS record at the registrar, which publishes it in the parent zone.
  3. Verify: dig +dnssec example.com DS, then dig @1.1.1.1 +dnssec example.com and look for the ad flag.

Before moving a zone to another DNS host, remove the DS record first. Otherwise validating resolvers reject the new, unsigned answers.

Verify changes against the authoritative server

Resolver caches hide mistakes. Query your zone’s assigned nameserver (shown in the dashboard) directly, then public resolvers:

dig @<assigned>.ns.cloudflare.com example.com A
dig @1.1.1.1 example.com A
dig @8.8.8.8 example.com A

Differing answers mean a cache has not expired yet.