Skip to content
Ali Akbari
Menu

ADR-0011 · accepted · 9 October 2026

Cloudflare CDN in front of the origin, with the HTML left untouched

Context

The owner switched both DNS records to Cloudflare's proxy to put a CDN in front of the single origin (ADR-0007). With default settings, Cloudflare rewrote pages: Web Analytics injected a beacon script that the hash-based CSP blocks, and Email Address Obfuscation replaced mailto: links with a script-decoded link. nginx also saw every visitor as a Cloudflare address, so per-IP rate limits and connection limits were shared by everyone behind the same edge location.

Options

  • DNS only. The origin already terminates TLS, caches assets and rate-limits; this was the original design.
  • Proxy with Cloudflare defaults. Breaks the CSP, the no-analytics promise and the rate limits.
  • Proxy, configured to be transparent. The CDN caches immutable assets near visitors and absorbs abuse, while HTML and the security model stay exactly what the origin serves.

Decision

Keep the proxy, configured to be transparent:

  • nginx restores the visitor address from CF-Connecting-IP, trusting it only from Cloudflare's published ranges (snippets/cloudflare-realip.conf, checked weekly by cloudflare-ips.yml). Logs stay truncated.
  • Pages are sent with Cache-Control: public, max-age=0, must-revalidate, so neither the edge nor a browser can serve HTML from an older release, whose hashed assets no longer exist. /_next/static/ stays immutable and is cached at the edge.
  • ACME challenges are also served over HTTPS, so renewal keeps working if the edge upgrades HTTP.
  • In the Cloudflare dashboard, every HTML-rewriting feature is off (Web Analytics automatic setup, Email Address Obfuscation, Rocket Loader), SSL/TLS mode is Full (strict), and Browser Cache TTL respects origin headers. The production verification fails if the served HTML differs in any of those ways.

Consequences

  • Cloudflare processes every request and sees full client addresses; the site's own logs still truncate them (ADR-0009 is amended accordingly). No cookies or scripts are added.
  • The origin is still reachable directly by IP. Restricting ports 80/443 to Cloudflare's ranges would need a host firewall rule that Docker port publishing respects (DOCKER-USER chain); not done yet.
  • The CSP check, the e2e suite and Lighthouse run through the CDN in the deploy verification, so they test what visitors receive.

Source: docs/adr/0011-cloudflare-cdn-in-front-of-origin.md

← All decisions