Cloudflare TLS
Cloudflare TLS
Migration in progress.
api.legendary-arena.comand its PostgreSQL are moving off Render onto a self-hosted DigitalOcean Ubuntu droplet fronted by Cloudflare, perdocs/PLAN.md. Until decommission, Render stays warm as the rollback target.
Summary
This page terminates TLS on the origin with a Cloudflare Origin Certificate and narrows the firewall so only Cloudflare can reach port 443. It rewrites the Nginx site the reverse-proxy step created, redirecting HTTP to HTTPS and preserving the WebSocket upgrade path for Socket.IO.
Mechanics
The owning artifact is infra/scripts/21-cloudflare-tls.ps1
— root-required, Set-StrictMode/stop. It runs in order:
Install cert material. Writes the Origin Certificate and key from
CF_ORIGIN_CERT/CF_ORIGIN_KEY(or expects them pre-installed) with strict permissions:/etc/ssl/cloudflare/origin.crt # 644 /etc/ssl/cloudflare/origin.key # 600Rewrite Nginx with TLS. Overwrites
/etc/nginx/sites-available/la-api.conf: port 80 becomes a301redirect to HTTPS; port 443 isssl http2withssl_certificate/ssl_certificate_key,ssl_protocols TLSv1.2 TLSv1.3, the same WebSocket-upgrade proxy block to127.0.0.1:$UpstreamPort, andlocation = /health:DOMAIN = api.legendary-arena.com UPSTREAM_PORT = 3000 ssl_protocols TLSv1.2 TLSv1.3Validate + reload. Runs
nginx -tand reloads.Restrict UFW to Cloudflare. If
ufwis active, fetches Cloudflare’s IPv4 and IPv6 ranges live and adds one allow rule per CIDR, then (defaultREMOVE_PUBLIC_443=true) deletes the broad public 443 rule:REMOVE_PUBLIC_443 = true ufw allow proto tcp from <cidr> to any port 443 # per Cloudflare CIDR # then: delete allow 443/tcp
A final log line reminds the operator to set the Cloudflare DNS record to proxied (orange-cloud) and SSL mode to Full (strict) in the dashboard. Per docs/PLAN.md
, the target posture is Cloudflare-proxied api. with an Origin Certificate under SSL mode Full (strict) and UFW 443 restricted to Cloudflare ranges; Socket.IO WebSockets pass the proxy.
Interactions
- Nginx Reverse Proxy
— this step rewrites the
la-api.confit created, upgrading the port-80 site to TLS on 443. - UFW Firewall
— this narrows the 443 rule to Cloudflare CIDRs, so
ufwmust already be active (the06step) for the restriction to apply. - Render-to-DigitalOcean Migration — the proxied edge posture is part of Phase 2 of the migration plan.
Edge Cases
- Origin Certificate requires the proxy. An Origin Cert is only valid while the record is proxied — grey-clouding for debugging breaks TLS and Full (strict) validation fails at the edge.
- Key permissions.
origin.keymust stay600; a world-readable private key is a credential leak. - UFW step is conditional. The firewall narrowing only runs if
ufwis already active — run the UFW step first or 443 stays wide open. - Cloudflare ranges drift. The CIDR list is fetched live and changes over time; re-run to refresh, or new Cloudflare edge IPs will be blocked. The DNS-proxy and Full (strict) toggles are dashboard actions the script cannot perform. WebSockets pass the Cloudflare proxy and are exempt from the 100s HTTP timeout.
Execute
# Supply cert material via env (documented default REMOVE_PUBLIC_443=true)
sudo CF_ORIGIN_CERT="$(cat origin.pem)" CF_ORIGIN_KEY="$(cat origin.key)" \
pwsh -File infra/scripts/21-cloudflare-tls.ps1
# Alternative: pre-install /etc/ssl/cloudflare/origin.crt + origin.key, then:
sudo pwsh -File infra/scripts/21-cloudflare-tls.ps1
Verify
sudo nginx -t
# Expected: syntax is ok / test is successful
sudo ufw status | grep 443
# Expected: ALLOW rules from Cloudflare CIDRs on 443; no broad "443/tcp ALLOW Anywhere"
curl -I https://api.legendary-arena.com/health
# Expected: HTTP/2 200
References
infra/scripts/21-cloudflare-tls.ps1— the owning TLS artifact.docs/PLAN.md— Full (strict) + proxied edge posture, UFW-to-Cloudflare restriction.content/web/cloudflare-tls.md— source content for this page.- Nginx Reverse Proxy — the site file this step rewrites.
- UFW Firewall — the firewall this step narrows to Cloudflare.