Skip to content

CDN Implementation Plan

The cluster hosts roughly 20 brochure/marketing sites for corporate clients. These are static or near-static content served through Traefik. The origin cluster runs in a single zone (zonal GKE or DOKS), so a CDN provides the availability safety net that makes regional redundancy unnecessary for this workload.

Cloudflare’s free plan covers everything these sites need at $0/domain:

  • Edge caching: static assets served from 300+ PoPs worldwide
  • DDoS protection: automatic L3/L4/L7 mitigation
  • SSL termination: universal SSL certificates, no ACME configuration needed per domain
  • Always Online: serves cached pages when the origin is unreachable (zone outage, maintenance)

Alternatives considered:

  • GCP Cloud CDN ($5-15/mo, GKE only, no WAF/DDoS): vendor-locked, fewer features, costs more
  • DigitalOcean: no CDN product for HTTP traffic
  • Regional GKE ($73/mo control plane + 3x node cost): solves availability at 4-5x the cost, does not help with latency or DDoS
Client -> Cloudflare edge (cached) -> Cluster LB -> Traefik -> Service -> Pod

Cloudflare operates in proxy mode (orange cloud). DNS records point each domain to the cluster’s load balancer IP. Cloudflare terminates TLS at the edge and forwards traffic to the origin over HTTPS.

For brochure sites with infrequent updates, cache TTLs can be set to hours or days. During an origin outage, Cloudflare serves stale cached content, so clients see no downtime.

A new module at tofu/remote/cloudflare/ will manage:

  • Cloudflare zones: one per client domain
  • DNS A records: root and www pointing to the cluster LB IP (output from DO or GKE module)
  • Page rules or cache rules: set cache TTL for static content
VariableTypeDescription
domainslist(string)Client domain names (e.g. ["example.com", "acme.co"])
origin_ipstringCluster load balancer IP (from tofu output of active provider)
cloudflare_api_tokenstringAPI token with Zone:Edit and DNS:Edit permissions
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 5.0"
}
}
}

The Cloudflare API token goes in .env.json (SOPS-encrypted), extracted at runtime the same way DO and GCP credentials are handled:

Terminal window
export CLOUDFLARE_API_TOKEN=$(sops -d --extract '["CLOUDFLARE_API_TOKEN"]' .env.json)
ComponentMonthly cost
Cloudflare free (20 zones)$0
Cloudflare Pro (20 zones, if needed)$400

Free tier is sufficient for brochure sites. Pro adds WAF rules and image optimization; upgrade per-domain if a client requires it.

  • Domain list: need the ~20 client domain names before creating zones
  • Cloudflare account: need an account with the domains added (nameserver delegation)
  • API token: generate a token scoped to Zone:Edit + DNS:Edit, add to .env.json
  1. Receive client domain list
  2. Create Cloudflare account, add domains, delegate nameservers
  3. Generate API token, add to .env.json via sops
  4. Create tofu/remote/cloudflare/ tofu module
  5. Add tofu:cf:check and tofu:cf:cost mise tasks
  6. Wire origin_ip from the active provider’s output into the Cloudflare module
  7. Deploy and verify each domain resolves through Cloudflare