Goal: Serve images from cdn.yourdomain.com using Azure Blob Storage as origin and Cloudflare for CDN + SSL. This mirrors the setup used for cdn.ryanwilliams.io pointing at rmwwestus.blob.core.windows.net. It’s a simple, low-cost way to host images with global caching.
What you’ll get
-
HTTPS at https://cdn.yourdomain.com/…
-
Cloudflare edge caching (fewer Azure egress charges over time)
-
End-to-end encryption with SSL/TLS: Full (strict) in Cloudflare
Prerequisites
-
An Azure Storage account (e.g., rmwwestus.blob.core.windows.net)
-
Your domain in Cloudflare (e.g., ryanwilliams.io)
-
A subdomain for images (e.g., cdn.ryanwilliams.io)
-
A public blob container for reads (or use the $web container if you prefer Static Website)
Step 1 — Cloudflare DNS: point your CDN subdomain to Azure
In Cloudflare → DNS, create a CNAME for your CDN subdomain and proxy it through Cloudflare.
# Cloudflare DNS Type: CNAME Name: cdn Target: .blob.core.windows.net # e.g., rmwwestus.blob.core.windows.net Proxy: Proxied (orange cloud) TTL: Auto
-
This ensures requests to cdn.yourdomain.com go through Cloudflare (for caching + SSL) to your Azure Blob origin.
Step 2 — Azure: add the custom domain with Indirect CNAME validation
In the Azure Portal, open your Storage account and add your custom host name. Depending on the UI version, the path is either:
-
Settings → Custom domain
-
or Blob service → Custom domain
-
(Some layouts show it under Networking → Custom domain)
Enter your domain (e.g., cdn.yourdomain.com) and select Use indirect CNAME validation. Azure will instruct you to add an asverify record. In Cloudflare, add a second CNAME exactly as shown, but leave it unproxied.
# Cloudflare DNS (validation record) Type: CNAME Name: asverify.cdn Target: asverify..blob.core.windows.net Proxy: DNS only (grey cloud) TTL: Auto
-
Click Save in Azure to complete validation.
-
Keep your main cdn record proxied and the asverify record DNS-only.
Step 3 — Cloudflare: enable strict SSL
In Cloudflare → SSL/TLS, set:
-
Encryption mode: Full (strict)
Why? Azure’s *.blob.core.windows.net
presents a valid Microsoft certificate, so strict mode gives you proper end-to-end TLS (Cloudflare ⇄ Azure over HTTPS).
-
Optional: under Edge Certificates, enable Always Use HTTPS and HSTS if you’re comfortable with strict HTTPS everywhere.
Step 4 — Upload and test
-
Upload an image to your container, e.g.
images/logo.png
. -
Open https://cdn.yourdomain.com/images/logo.png.
-
First load may be a cache MISS; refresh again to see a Cloudflare HIT.
Optional: set strong cache headers on blobs
For long-lived static assets, set blob metadata:
Cache-Control: public, max-age=31536000, immutable
-
Cloudflare will respect your origin’s
Cache-Control
by default, reducing origin egress.
Troubleshooting
-
525/526 SSL errors: Ensure the main cdn record is Proxied, the target is your *.blob.core.windows.net endpoint, and Cloudflare mode is Full (strict).
-
Custom domain won’t validate: Double-check the asverify.cdn CNAME is DNS only and matches Azure’s exact value.
-
403/404s: Confirm the container allows anonymous read access and your blob path is correct.
Why this is cheap
-
Azure Blob Storage is inexpensive for storage + requests.
-
Cloudflare (Free) adds global caching + SSL at no extra cost.
-
You pay Azure egress primarily on cache misses; hits are served from Cloudflare’s edge.
TL;DR — Exact knobs used
Cloudflare → DNS
# Main CDN record (proxied) CNAME cdn -> .blob.core.windows.net (Proxied)
Validation record (DNS only)
CNAME asverify.cdn -> asverify..blob.core.windows.net (DNS only)
Azure → Storage Account → Custom domain
-
Hostname: cdn.yourdomain.com
-
Check Use indirect CNAME validation, then Save
Cloudflare → SSL/TLS
-
Encryption mode: Full (strict)
That’s it. You’ve got a fast, low-cost image CDN on your own domain using Azure Blob + Cloudflare.