Custom Domains & SSL
By the end of this module you will be able to configure a custom domain with automatic SSL on Cloudflare Pages — including both Cloudflare-managed DNS and external registrar scenarios.
Overview
Every Cloudflare Pages project gets a free *.pages.dev subdomain. Custom domains let you serve your site at domains like docs.yourdomain.com with:
- Automatic SSL — certificate provisioned within ~60 seconds
- Unlimited custom domains per project
- Automatic HTTP→HTTPS redirect
- Global CDN — same as the default pages.dev URL
Scenario 1: Domain DNS Managed by Cloudflare (Easiest)
This is the recommended setup and the one tested in the author's workflow. If your domain's nameservers point to Cloudflare, setup is automatic.
Step 1 — Add Domain in Dashboard
- Go to Workers & Pages → your project → Custom domains
- Click Set up a custom domain
- Enter your subdomain:
docs.yourdomain.com - Click Continue
- Cloudflare shows the DNS record it will create:
Type: CNAME
Name: docs
Target: my-docs.pages.dev
Proxy: ✅ Proxied (orange cloud) - Click Activate domain
Cloudflare automatically:
- Creates the CNAME DNS record
- Issues a TLS certificate
- Configures HTTP→HTTPS redirect
- Enables All Cloudflare security features (DDoS, WAF, etc.)
Step 2 — Verify
# Check DNS propagation
dig docs.yourdomain.com CNAME
# Should return:
# docs.yourdomain.com. CNAME my-docs.pages.dev.
# Check HTTPS
curl -I https://docs.yourdomain.com
# Should return:
# HTTP/2 200
# server: cloudflare
Scenario 2: Apex Domain (yourdomain.com)
Apex domains (bare domain, no subdomain) cannot use CNAME records. Cloudflare handles this automatically if DNS is managed by Cloudflare:
Type: CNAME (Cloudflare's DNS supports CNAME at apex via CNAME flattening)
Name: @ (apex)
Target: my-docs.pages.dev
Proxy: ✅ Proxied
Cloudflare automatically flattens the CNAME to A records — this is unique to Cloudflare's DNS implementation and not available at most other registrars.
www → Root Redirect
If you use the apex domain (yourdomain.com), add a www redirect:
- Add a CNAME for
www:Type: CNAME
Name: www
Target: my-docs.pages.dev - Add a Cloudflare Redirect Rule (or use Pages
_redirectsfile):
# In your Docusaurus static/ directory, create static/_redirects:
https://www.yourdomain.com/* https://yourdomain.com/:splat 301
Scenario 3: External DNS (Not Managed by Cloudflare)
If your domain is at another registrar (Namecheap, GoDaddy, Route 53, etc.):
Subdomain (docs.yourdomain.com)
Add this CNAME record at your registrar:
Host: docs
Type: CNAME
Value: my-docs.pages.dev
TTL: 3600 (or Auto)
Then in Cloudflare Pages:
- Add the custom domain
docs.yourdomain.com - Cloudflare will attempt to verify ownership via DNS TXT record
- Once verified, SSL is provisioned automatically
Apex Domain with External DNS
External registrars usually don't support CNAME at apex. Options:
Option A: Use A records (Cloudflare's IP ranges) — Not supported for Pages (Pages has no static IPs).
Option B: Migrate DNS to Cloudflare — Recommended. Transfer nameservers to Cloudflare (free):
- Add your domain to Cloudflare (free plan)
- Update nameservers at your registrar to Cloudflare's
- Then follow Scenario 1 above
Option C: Use www subdomain as canonical URL — Set www.yourdomain.com as your Pages domain, then redirect apex to www at your registrar level.
Managing Custom Domains via API
List Domains
curl "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/${CF_PROJECT}/domains" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
| jq '.result[] | {name, status, ssl}'
Add Domain
curl -X POST \
"https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/${CF_PROJECT}/domains" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name": "docs.yourdomain.com"}' | jq .
Delete Domain
curl -X DELETE \
"https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/${CF_PROJECT}/domains/docs.yourdomain.com" \
-H "Authorization: Bearer ${CF_API_TOKEN}"
SSL Configuration
SSL is Always Automatic
Cloudflare Pages provisions SSL via:
- Cloudflare Universal SSL for
*.pages.devdomains - Cloudflare SSL for custom domains (DV certificate, 90-day rotation handled automatically)
You do not need to configure Let's Encrypt, Certbot, or any ACME client. The certificate is:
- Free
- Automatically renewed
- Valid for your domain + all subdomains
SSL Mode
When your domain DNS is managed by Cloudflare:
- SSL mode is set to Full (strict) by default — Cloudflare validates the certificate between itself and Pages.
- This is the highest security mode and requires no configuration.
Check SSL Status via API
curl "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/${CF_PROJECT}/domains/docs.yourdomain.com" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
| jq '.result | {name, status, ssl: .ssl}'
Redirects with _redirects File
Cloudflare Pages supports Netlify-compatible _redirects files for URL redirects and rewrites.
Place _redirects in your output directory (for Docusaurus: static/_redirects → copied to build/_redirects).
# Redirect old URL structure to new
/guide /docs/intro 301
# Redirect www to apex
https://www.yourdomain.com/* https://yourdomain.com/:splat 301
# Redirect old docs prefix
/docs/* /:splat 301
# Rewrite API calls (proxy to Worker without redirect)
/api/* https://api.yourdomain.com/:splat 200
# SPA fallback (not needed for Docusaurus — it generates real HTML files)
/* /index.html 200
Syntax: <source> <destination> <status>
_headers File
Control response headers per path:
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
/docs/*
Cache-Control: public, max-age=0, must-revalidate
HSTS and Security
Cloudflare Pages automatically adds:
Strict-Transport-Securityheader- Automatic HTTPS redirect
You can enhance security headers via the _headers file or Cloudflare Transform Rules (in the zone settings).
Troubleshooting Custom Domains
Domain Shows "Initializing" for More Than 5 Minutes
# Check if DNS record exists
dig docs.yourdomain.com CNAME
# If record doesn't exist:
# - For Cloudflare DNS: check if record was auto-created in DNS tab
# - For external DNS: add the CNAME record manually at your registrar
SSL Certificate Takes Too Long
# Check domain status via API
curl "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/${CF_PROJECT}/domains/docs.yourdomain.com" \
-H "Authorization: Bearer ${CF_API_TOKEN}" | jq .
# Common fix: wait 5-10 minutes after DNS propagation
# If "blocked" status: check for CNAME conflicts (existing A or AAAA record at same name)
Domain Shows "Blocked" Status
Causes:
- An A or AAAA record already exists for the same hostname — delete it
- Ownership verification failed — re-add the domain and follow verification steps
Custom Domain Works But Shows Wrong Content
# Clear Cloudflare cache
curl -X POST \
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"purge_everything": true}'
Key Takeaways
- Cloudflare Pages supports unlimited custom domains per project, free SSL included.
- If your DNS is Cloudflare-managed, adding a custom domain takes ~60 seconds.
- Use the
_redirectsfile (instatic/for Docusaurus) for URL redirects — Netlify-compatible syntax. - Use the
_headersfile for custom response headers (CSP, HSTS, Cache-Control). - Apex domains work with Cloudflare DNS via CNAME flattening.
What's Next
- Continue to Pages Functions (Edge Functions) to add server-side logic to your Docusaurus site.